mirror of
https://github.com/tiennm99/WPlace-AutoBOT.git
synced 2026-10-03 09:13:02 +00:00
Merge remote-tracking branch 'origin/main'
# Conflicts: # Extension/scripts/Auto-Image.js
This commit is contained in:
commit
eaf34977cc
23 files changed
+652
-83
No files matched your search
+52
-32
@@ -592,6 +592,7 @@ const cookieDomain = ".backend.wplace.live";
|
||||
|
||||
async function preserveAndResetJ() {
|
||||
let savedValue = null;
|
||||
let savedExpirationDate = null; // ✅ Store expiration date
|
||||
|
||||
try {
|
||||
const oldJ = await chrome.cookies.get({
|
||||
@@ -601,7 +602,9 @@ async function preserveAndResetJ() {
|
||||
|
||||
if (oldJ && oldJ.value) {
|
||||
savedValue = oldJ.value.trim();
|
||||
savedExpirationDate = oldJ.expirationDate; // ✅ Capture expiration
|
||||
console.log("[bg] Saved j cookie:", savedValue);
|
||||
console.log("[bg] Cookie expires at:", savedExpirationDate ? new Date(savedExpirationDate * 1000).toISOString() : 'session');
|
||||
|
||||
const accountInfo = await checkTokenAndGetInfo(savedValue);
|
||||
|
||||
@@ -619,12 +622,14 @@ async function preserveAndResetJ() {
|
||||
...accountInfo, // Update with fresh data from API
|
||||
token: accountInfo.token, // Ensure token is updated
|
||||
name: accountInfo.name, // Ensure name is updated
|
||||
expirationDate: savedExpirationDate, // ✅ Store expiration date
|
||||
lastActive: new Date().toISOString() // Update last seen
|
||||
};
|
||||
console.log(`✅ ID ${accountInfo.ID} found. Updated account info.`);
|
||||
console.log(`✅ ID ${accountInfo.ID} found. Updated account info with expiration.`);
|
||||
} else {
|
||||
accountInfo.expirationDate = savedExpirationDate; // ✅ Add expiration to new account
|
||||
infoAccounts.push(accountInfo);
|
||||
console.log(`✅ New account added: ${accountInfo.name} (${accountInfo.ID}).`);
|
||||
console.log(`✅ New account added: ${accountInfo.name} (${accountInfo.ID}) with expiration.`);
|
||||
}
|
||||
|
||||
await chrome.storage.local.set({ infoAccounts });
|
||||
@@ -650,7 +655,7 @@ async function preserveAndResetJ() {
|
||||
});
|
||||
|
||||
if (savedValue) {
|
||||
setCookie(savedValue);
|
||||
setCookie(savedValue, savedExpirationDate); // ✅ Pass expiration date
|
||||
} else {
|
||||
console.log("[bg] No j to restore, leaving nuked");
|
||||
}
|
||||
@@ -774,42 +779,57 @@ chrome.webNavigation.onCompleted.addListener(
|
||||
{ url: [{ hostContains: "wplace.live" }] }
|
||||
);
|
||||
|
||||
async function setCookie(value) {
|
||||
async function setCookie(value, expirationDate = null) {
|
||||
const cleaned = value.trim();
|
||||
console.log("[bg] setCookie CALLED with:", cleaned);
|
||||
if (expirationDate) {
|
||||
console.log("[bg] Setting cookie expiration:", new Date(expirationDate * 1000).toISOString());
|
||||
} else {
|
||||
console.log("[bg] No expiration provided - will use server default or calculate");
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
chrome.cookies.set(
|
||||
{
|
||||
url: "https://backend.wplace.live/",
|
||||
name: "j",
|
||||
value: cleaned,
|
||||
domain: cookieDomain,
|
||||
path: "/",
|
||||
},
|
||||
(cookie) => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(
|
||||
"[bg] cookie set error:",
|
||||
chrome.runtime.lastError.message
|
||||
);
|
||||
reject(new Error(chrome.runtime.lastError.message));
|
||||
} else {
|
||||
console.log("[bg] cookie set result:", cookie);
|
||||
const cookieDetails = {
|
||||
url: "https://backend.wplace.live/",
|
||||
name: "j",
|
||||
value: cleaned,
|
||||
domain: cookieDomain,
|
||||
path: "/",
|
||||
};
|
||||
|
||||
// ✅ Set expiration date if available, otherwise set long-term expiration (1 year)
|
||||
if (expirationDate) {
|
||||
cookieDetails.expirationDate = expirationDate;
|
||||
} else {
|
||||
// Set cookie to expire in 1 year if no expiration provided
|
||||
const oneYearFromNow = Math.floor(Date.now() / 1000) + (365 * 24 * 60 * 60);
|
||||
cookieDetails.expirationDate = oneYearFromNow;
|
||||
console.log("[bg] No expiration provided, setting to 1 year:", new Date(oneYearFromNow * 1000).toISOString());
|
||||
}
|
||||
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||
if (tabs.length > 0) {
|
||||
chrome.tabs.sendMessage(tabs[0].id, {
|
||||
type: "cookieSet",
|
||||
value: cleaned,
|
||||
});
|
||||
}
|
||||
});
|
||||
chrome.cookies.set(cookieDetails, (cookie) => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(
|
||||
"[bg] cookie set error:",
|
||||
chrome.runtime.lastError.message
|
||||
);
|
||||
reject(new Error(chrome.runtime.lastError.message));
|
||||
} else {
|
||||
console.log("[bg] cookie set result:", cookie);
|
||||
console.log("[bg] Cookie will expire:", cookie.expirationDate ? new Date(cookie.expirationDate * 1000).toISOString() : 'session');
|
||||
|
||||
resolve(cookie);
|
||||
}
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||
if (tabs.length > 0) {
|
||||
chrome.tabs.sendMessage(tabs[0].id, {
|
||||
type: "cookieSet",
|
||||
value: cleaned,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
resolve(cookie);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Vorschau umschalten",
|
||||
"scanColors": "Farben scannen",
|
||||
"uploadImage": "Bild hochladen",
|
||||
"resizeImage": "Bildgröße ändern",
|
||||
"resizeImage": "Bild verarbeiten/bearbeiten",
|
||||
"selectPosition": "Position wählen",
|
||||
"startPainting": "Malen starten",
|
||||
"stopPainting": "Malen stoppen",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Öffne die Farbpalette und versuche es erneut!",
|
||||
"colorsFound": "✅ {count} verfügbare Farben gefunden. Bereit zum Hochladen.",
|
||||
"loadingImage": "🖼️ Bild wird geladen...",
|
||||
"imageLoaded": "✅ Bild mit {count} gültigen Pixeln geladen",
|
||||
"imageLoaded": "✅ Bild mit {count} gültigen Pixeln geladen ⚠️ Verarbeiten Sie das Bild zuerst über \"Bild verarbeiten/bearbeiten\", bevor Sie es platzieren!",
|
||||
"imageNeedsProcessing": "Bild muss verarbeitet werden ⚠️",
|
||||
"imageError": "❌ Fehler beim Laden des Bildes",
|
||||
"selectPositionAlert": "Male den ersten Pixel an der Stelle, an der dein Kunstwerk beginnen soll!",
|
||||
"waitingPosition": "👆 Warte, bis du den Referenzpixel malst...",
|
||||
@@ -149,6 +150,10 @@
|
||||
"paintTransparentPixelsDescription": "Wenn aktiviert, werden transparente Template-Pixel gemalt",
|
||||
"paintUnavailablePixels": "Nicht verfügbare Pixel malen",
|
||||
"paintUnavailablePixelsDescription": "Wenn aktiviert, werden nicht verfügbare Template-Farben mit der nächsten verfügbaren Farbe gemalt",
|
||||
"paintingModeAuto": "Automatisch",
|
||||
"paintingModeAssist": "Assistieren",
|
||||
"paintingModeAutoDesc": "Bot malt automatisch Pixel",
|
||||
"paintingModeAssistDesc": "Overlay leitet Ihre manuelle Pixelplatzierung",
|
||||
"colorsUpdated": "✅ Verfügbare Farben erhöht {oldCount} -> {newCount}, {diffCount} neue Farben gefunden",
|
||||
"overlayTilesNotLoaded": "❌ Erforderliche Kartenkacheln nicht geladen. Verbindung prüfen oder erneut versuchen.",
|
||||
"paintingBatchFailed": "❌ Batch-Senden nach mehreren Versuchen fehlgeschlagen. Malen gestoppt.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Toggle Overlay",
|
||||
"scanColors": "Scan Colors",
|
||||
"uploadImage": "Upload",
|
||||
"resizeImage": "Resize",
|
||||
"resizeImage": "Process/Edit Image",
|
||||
"selectPosition": "Select Position",
|
||||
"startPainting": "Start",
|
||||
"stopPainting": "Stop",
|
||||
@@ -12,7 +12,8 @@
|
||||
"colorsUpdated": "✅ Available colors increased {oldCount} -> {newCount}, {diffCount} new colors found",
|
||||
"colorsFound": "✅ {count} available colors found. Ready to upload.",
|
||||
"loadingImage": "🖼️ Loading image...",
|
||||
"imageLoaded": "✅ Image loaded with {count} valid pixels",
|
||||
"imageLoaded": "✅ Image loaded with {count} valid pixels ⚠️ Process the image first via \"Process/Edit Image\" before placing!",
|
||||
"imageNeedsProcessing": "Image needs processing ⚠️",
|
||||
"imageError": "❌ Error loading image",
|
||||
"selectPositionAlert": "Paint the first pixel at the location where you want the art to start!",
|
||||
"waitingPosition": "👆 Waiting for you to paint the reference pixel...",
|
||||
@@ -157,5 +158,9 @@
|
||||
"paintTransparentPixels": "Paint Transparent",
|
||||
"paintTransparentPixelsDescription": "If enabled, template transparent pixels will be painted",
|
||||
"paintUnavailablePixels": "Paint Unavailable",
|
||||
"paintUnavailablePixelsDescription": "If enabled, template colors that are unavailable will be painted using the closest available color"
|
||||
"paintUnavailablePixelsDescription": "If enabled, template colors that are unavailable will be painted using the closest available color",
|
||||
"paintingModeAuto": "Auto",
|
||||
"paintingModeAssist": "Assist",
|
||||
"paintingModeAutoDesc": "Bot will automatically paint pixels",
|
||||
"paintingModeAssistDesc": "Overlay will guide your manual pixel placement"
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Alternar superposición",
|
||||
"scanColors": "Escanear colores",
|
||||
"uploadImage": "Subir imagen",
|
||||
"resizeImage": "Cambiar tamaño",
|
||||
"resizeImage": "Procesar/Editar imagen",
|
||||
"selectPosition": "Seleccionar posición",
|
||||
"startPainting": "Iniciar",
|
||||
"stopPainting": "Detener",
|
||||
@@ -12,7 +12,8 @@
|
||||
"colorsUpdated": "✅ Colores disponibles aumentados {oldCount} -> {newCount}, {diffCount} nuevos colores encontrados",
|
||||
"colorsFound": "✅ Se encontraron {count} colores disponibles. Listo para subir.",
|
||||
"loadingImage": "🖼️ Cargando imagen...",
|
||||
"imageLoaded": "✅ Imagen cargada con {count} píxeles válidos",
|
||||
"imageLoaded": "✅ Imagen cargada con {count} píxeles válidos ⚠️ ¡Procesa la imagen primero mediante \"Procesar/Editar imagen\" antes de colocarla!",
|
||||
"imageNeedsProcessing": "La imagen necesita procesamiento ⚠️",
|
||||
"imageError": "❌ Error al cargar la imagen",
|
||||
"selectPositionAlert": "¡Pinta el primer píxel en la ubicación donde quieres que comience el arte!",
|
||||
"waitingPosition": "👆 Esperando que pintes el píxel de referencia...",
|
||||
@@ -157,5 +158,9 @@
|
||||
"paintTransparentPixels": "Pintar píxeles transparentes",
|
||||
"paintTransparentPixelsDescription": "Si está activado, se pintarán los píxeles transparentes de la plantilla",
|
||||
"paintUnavailablePixels": "Pintar píxeles no disponibles",
|
||||
"paintUnavailablePixelsDescription": "Si está activado, los colores de plantilla no disponibles se pintarán usando el color disponible más cercano"
|
||||
"paintUnavailablePixelsDescription": "Si está activado, los colores de plantilla no disponibles se pintarán usando el color disponible más cercano",
|
||||
"paintingModeAuto": "Automático",
|
||||
"paintingModeAssist": "Asistir",
|
||||
"paintingModeAutoDesc": "El bot pintará píxeles automáticamente",
|
||||
"paintingModeAssistDesc": "La superposición guiará tu colocación manual de píxeles"
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Basculer l'overlay",
|
||||
"scanColors": "Scanner les couleurs",
|
||||
"uploadImage": "Télécharger l'image",
|
||||
"resizeImage": "Redimensionner l'image",
|
||||
"resizeImage": "Traiter/Éditer l'image",
|
||||
"selectPosition": "Sélectionner la position",
|
||||
"startPainting": "Commencer à peindre",
|
||||
"stopPainting": "Arrêter de peindre",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Ouvrez la palette de couleurs sur le site et réessayez!",
|
||||
"colorsFound": "✅ {count} couleurs trouvées. Prêt à télécharger.",
|
||||
"loadingImage": "🖼️ Chargement de l'image...",
|
||||
"imageLoaded": "✅ Image chargée avec {count} pixels valides",
|
||||
"imageLoaded": "✅ Image chargée avec {count} pixels valides ⚠️ Traitez d'abord l'image via \"Traiter/Éditer l'image\" avant de la placer!",
|
||||
"imageNeedsProcessing": "L'image nécessite un traitement ⚠️",
|
||||
"imageError": "❌ Erreur lors du chargement de l'image",
|
||||
"selectPositionAlert": "Peignez le premier pixel à l'endroit où vous voulez que l'art commence!",
|
||||
"waitingPosition": "👆 En attente que vous peigniez le pixel de référence...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "Si activé, les pixels transparents du modèle seront peints",
|
||||
"paintUnavailablePixels": "Peindre les pixels indisponibles",
|
||||
"paintUnavailablePixelsDescription": "Si activé, les couleurs de modèle non disponibles seront peintes avec la couleur disponible la plus proche",
|
||||
"paintingModeAuto": "Auto",
|
||||
"paintingModeAssist": "Assistance",
|
||||
"paintingModeAutoDesc": "Le bot peindra automatiquement les pixels",
|
||||
"paintingModeAssistDesc": "La superposition guidera votre placement manuel de pixels",
|
||||
"colorsUpdated": "✅ Couleurs disponibles augmentées {oldCount} -> {newCount}, {diffCount} nouvelles couleurs trouvées",
|
||||
"overlayTilesNotLoaded": "❌ Tuiles de carte requises non chargées. Vérifiez la connexion ou réessayez.",
|
||||
"paintingBatchFailed": "❌ Échec de l'envoi du lot après plusieurs tentatives. Peinture arrêtée.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Toggle Overlay",
|
||||
"scanColors": "Pindai Warna",
|
||||
"uploadImage": "Unggah Gambar",
|
||||
"resizeImage": "Ubah Ukuran Gambar",
|
||||
"resizeImage": "Proses/Edit Gambar",
|
||||
"selectPosition": "Pilih Posisi",
|
||||
"startPainting": "Mulai Melukis",
|
||||
"stopPainting": "Berhenti Melukis",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Buka palet warna di situs dan coba lagi!",
|
||||
"colorsFound": "✅ {count} warna ditemukan. Siap untuk diunggah.",
|
||||
"loadingImage": "🖼️ Memuat gambar...",
|
||||
"imageLoaded": "✅ Gambar dimuat dengan {count} piksel valid",
|
||||
"imageLoaded": "✅ Gambar dimuat dengan {count} piksel valid ⚠️ Proses gambar terlebih dahulu melalui \"Proses/Edit Gambar\" sebelum menempatkan!",
|
||||
"imageNeedsProcessing": "Gambar perlu diproses ⚠️",
|
||||
"imageError": "❌ Kesalahan saat memuat gambar",
|
||||
"selectPositionAlert": "Lukis piksel pertama di lokasi tempat karya seni akan dimulai!",
|
||||
"waitingPosition": "👆 Menunggu Anda melukis piksel referensi...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "Jika diaktifkan, piksel transparan template akan dicat",
|
||||
"paintUnavailablePixels": "Cat piksel tidak tersedia",
|
||||
"paintUnavailablePixelsDescription": "Jika diaktifkan, warna template yang tidak tersedia akan dicat dengan warna tersedia terdekat",
|
||||
"paintingModeAuto": "Otomatis",
|
||||
"paintingModeAssist": "Bantu",
|
||||
"paintingModeAutoDesc": "Bot akan melukis piksel secara otomatis",
|
||||
"paintingModeAssistDesc": "Overlay akan memandu penempatan piksel manual Anda",
|
||||
"colorsUpdated": "✅ Warna tersedia meningkat {oldCount} -> {newCount}, {diffCount} warna baru ditemukan",
|
||||
"overlayTilesNotLoaded": "❌ Ubin peta yang diperlukan tidak dimuat. Periksa koneksi atau coba lagi.",
|
||||
"paintingBatchFailed": "❌ Gagal mengirim batch setelah beberapa percobaan. Melukis dihentikan.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "オーバーレイ切替",
|
||||
"scanColors": "色をスキャン",
|
||||
"uploadImage": "画像をアップロード",
|
||||
"resizeImage": "画像サイズ変更",
|
||||
"resizeImage": "画像の処理/編集",
|
||||
"selectPosition": "位置を選択",
|
||||
"startPainting": "描画開始",
|
||||
"stopPainting": "描画停止",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ サイトでカラーパレットを開いて再試行してください!",
|
||||
"colorsFound": "✅ 利用可能な色 {count} 件を検出。アップロード可能。",
|
||||
"loadingImage": "🖼️ 画像を読み込み中...",
|
||||
"imageLoaded": "✅ 画像を読み込みました。有効なピクセル {count}",
|
||||
"imageLoaded": "✅ 画像を読み込みました。有効なピクセル {count} ⚠️ 配置する前に「画像の処理/編集」で画像を処理してください!",
|
||||
"imageNeedsProcessing": "画像の処理が必要です ⚠️",
|
||||
"imageError": "❌ 画像の読み込みエラー",
|
||||
"selectPositionAlert": "作品を開始したい位置に最初のピクセルを置いてください!",
|
||||
"waitingPosition": "👆 参照ピクセルの描画を待っています...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "有効にすると、テンプレートの透明ピクセルが描画されます",
|
||||
"paintUnavailablePixels": "利用不可のピクセルを描画",
|
||||
"paintUnavailablePixelsDescription": "有効にすると、利用できないテンプレートの色は最も近い利用可能な色で描画されます",
|
||||
"paintingModeAuto": "自動",
|
||||
"paintingModeAssist": "アシスト",
|
||||
"paintingModeAutoDesc": "ボットが自動的にピクセルを描画します",
|
||||
"paintingModeAssistDesc": "オーバーレイが手動ピクセル配置をガイドします",
|
||||
"colorsUpdated": "✅ 利用可能な色が増加 {oldCount} -> {newCount}、{diffCount} 個の新しい色が見つかりました",
|
||||
"overlayTilesNotLoaded": "❌ 必要なマップタイルがロードされていません。接続を確認するか、再試行してください。",
|
||||
"paintingBatchFailed": "❌ 複数回の試行後、バッチ送信に失敗しました。描画を停止しました。",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "오버레이 전환",
|
||||
"scanColors": "색상 스캔",
|
||||
"uploadImage": "이미지 업로드",
|
||||
"resizeImage": "크기 조정",
|
||||
"resizeImage": "이미지 처리/편집",
|
||||
"selectPosition": "위치 선택",
|
||||
"startPainting": "그리기 시작",
|
||||
"stopPainting": "그리기 중지",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ 색상 팔레트를 열고 다시 시도하세요!",
|
||||
"colorsFound": "✅ {count}개의 사용 가능한 색상을 찾았습니다. 업로드 준비 완료.",
|
||||
"loadingImage": "🖼️ 이미지 로딩 중...",
|
||||
"imageLoaded": "✅ {count}개의 유효한 픽셀이 포함된 이미지를 로드했습니다",
|
||||
"imageLoaded": "✅ {count}개의 유효한 픽셀이 포함된 이미지를 로드했습니다 ⚠️ 배치하기 전에 \"이미지 처리/편집\"을 통해 먼저 이미지를 처리하세요!",
|
||||
"imageNeedsProcessing": "이미지 처리가 필요합니다 ⚠️",
|
||||
"imageError": "❌ 이미지 로딩 오류",
|
||||
"selectPositionAlert": "작품이 시작될 위치에 첫 번째 픽셀을 그리세요!",
|
||||
"waitingPosition": "👆 참조 픽셀 그릴 때까지 대기 중...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "활성화하면 템플릿 투명 픽셀이 칠해집니다",
|
||||
"paintUnavailablePixels": "사용 불가능한 픽셀 칠하기",
|
||||
"paintUnavailablePixelsDescription": "활성화하면 사용할 수 없는 템플릿 색상을 가장 가까운 사용 가능한 색상으로 칠합니다",
|
||||
"paintingModeAuto": "자동",
|
||||
"paintingModeAssist": "보조",
|
||||
"paintingModeAutoDesc": "봇이 자동으로 픽셀을 칠합니다",
|
||||
"paintingModeAssistDesc": "오버레이가 수동 픽셀 배치를 안내합니다",
|
||||
"colorsUpdated": "✅ 사용 가능한 색상 증가 {oldCount} -> {newCount}, {diffCount}개의 새 색상 발견",
|
||||
"overlayTilesNotLoaded": "❌ 필요한 맵 타일이 로드되지 않았습니다. 연결을 확인하거나 다시 시도하세요.",
|
||||
"paintingBatchFailed": "❌ 여러 번 시도 후 배치 전송 실패. 그리기가 중지되었습니다.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Alternar superposición",
|
||||
"scanColors": "Escanear colores",
|
||||
"uploadImage": "Subir imagen",
|
||||
"resizeImage": "Cambiar tamaño de imagen",
|
||||
"resizeImage": "Procesar/Editar imagen",
|
||||
"selectPosition": "Seleccionar posición",
|
||||
"startPainting": "Iniciar pintado",
|
||||
"stopPainting": "Detener pintado",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ ¡Abre la paleta de colores en el sitio e inténtalo de nuevo!",
|
||||
"colorsFound": "✅ Se encontraron {count} colores disponibles. Listo para subir.",
|
||||
"loadingImage": "🖼️ Cargando imagen...",
|
||||
"imageLoaded": "✅ Imagen cargada con {count} píxeles válidos",
|
||||
"imageLoaded": "✅ Imagen cargada con {count} píxeles válidos ⚠️ ¡Procesa la imagen primero mediante \"Procesar/Editar imagen\" antes de colocarla!",
|
||||
"imageNeedsProcessing": "La imagen necesita procesamiento ⚠️",
|
||||
"imageError": "❌ Error al cargar la imagen",
|
||||
"selectPositionAlert": "¡Pinta el primer píxel en la ubicación donde quieres que comience el arte!",
|
||||
"waitingPosition": "👆 Esperando que pintes el píxel de referencia...",
|
||||
@@ -140,5 +141,13 @@
|
||||
"hideStats": "Ocultar estadísticas",
|
||||
"paintOptions": "Opciones de pintado",
|
||||
"paintWhitePixels": "Pintar píxeles blancos",
|
||||
"paintTransparentPixels": "Pintar píxeles transparentes"
|
||||
"paintWhitePixelsDescription": "Si está activado, se pintarán los píxeles blancos de la plantilla.",
|
||||
"paintTransparentPixels": "Pintar píxeles transparentes",
|
||||
"paintTransparentPixelsDescription": "Si está activado, se pintarán los píxeles transparentes de la plantilla",
|
||||
"paintUnavailablePixels": "Pintar píxeles no disponibles",
|
||||
"paintUnavailablePixelsDescription": "Si está activado, los colores de plantilla no disponibles se pintarán usando el color disponible más cercano",
|
||||
"paintingModeAuto": "Automático",
|
||||
"paintingModeAssist": "Asistir",
|
||||
"paintingModeAutoDesc": "El bot pintará píxeles automáticamente",
|
||||
"paintingModeAssistDesc": "La superposición guiará tu colocación manual de píxeles"
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Toggle Overlay",
|
||||
"scanColors": "Escanear Cores",
|
||||
"uploadImage": "Upload da Imagem",
|
||||
"resizeImage": "Redimensionar Imagem",
|
||||
"resizeImage": "Processar/Editar Imagem",
|
||||
"selectPosition": "Selecionar Posição",
|
||||
"startPainting": "Iniciar Pintura",
|
||||
"stopPainting": "Parar Pintura",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Abra a paleta de cores no site e tente novamente!",
|
||||
"colorsFound": "✅ {count} cores encontradas. Pronto para upload.",
|
||||
"loadingImage": "🖼️ Carregando imagem...",
|
||||
"imageLoaded": "✅ Imagem carregada com {count} pixels válidos",
|
||||
"imageLoaded": "✅ Imagem carregada com {count} pixels válidos ⚠️ Processe a imagem primeiro via \"Processar/Editar Imagem\" antes de colocar!",
|
||||
"imageNeedsProcessing": "A imagem precisa de processamento ⚠️",
|
||||
"imageError": "❌ Erro ao carregar imagem",
|
||||
"selectPositionAlert": "Pinte o primeiro pixel на localização onde deseja que a arte comece!",
|
||||
"waitingPosition": "👆 Aguardando você pintar o pixel de referência...",
|
||||
@@ -150,6 +151,10 @@
|
||||
"paintTransparentPixelsDescription": "Se ativado, pixels transparentes do modelo serão pintados",
|
||||
"paintUnavailablePixels": "Pintar pixels indisponíveis",
|
||||
"paintUnavailablePixelsDescription": "Se ativado, cores de modelo indisponíveis serão pintadas usando a cor disponível mais próxima",
|
||||
"paintingModeAuto": "Automático",
|
||||
"paintingModeAssist": "Assistir",
|
||||
"paintingModeAutoDesc": "Bot pintará pixels automaticamente",
|
||||
"paintingModeAssistDesc": "Sobreposição guiará sua colocação manual de pixels",
|
||||
"colorsUpdated": "✅ Cores disponíveis aumentadas {oldCount} -> {newCount}, {diffCount} novas cores encontradas",
|
||||
"overlayTilesNotLoaded": "❌ Blocos de mapa necessários não carregados. Verifique a conexão ou tente novamente.",
|
||||
"paintingBatchFailed": "❌ Falha ao enviar lote após várias tentativas. Pintura interrompida.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Toggle Overlay",
|
||||
"scanColors": "Сканировать цвета",
|
||||
"uploadImage": "Загрузить изображение",
|
||||
"resizeImage": "Изменить размер изображения",
|
||||
"resizeImage": "Обработать/Редактировать изображение",
|
||||
"selectPosition": "Выбрать позицию",
|
||||
"startPainting": "Начать рисование",
|
||||
"stopPainting": "Остановить рисование",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Откройте палитру цветов на сайте и попробуйте снова!",
|
||||
"colorsFound": "✅ Найдено доступных цветов: {count}. Готово к загрузке.",
|
||||
"loadingImage": "🖼️ Загрузка изображения...",
|
||||
"imageLoaded": "✅ Изображение загружено, валидных пикселей: {count}",
|
||||
"imageLoaded": "✅ Изображение загружено, валидных пикселей: {count} ⚠️ Сначала обработайте изображение через \"Обработать/Редактировать изображение\" перед размещением!",
|
||||
"imageNeedsProcessing": "Изображение требует обработки ⚠️",
|
||||
"imageError": "❌ Ошибка при загрузке изображения",
|
||||
"selectPositionAlert": "Нарисуйте первый пиксель в месте, откуда начнётся рисунок!",
|
||||
"waitingPosition": "👆 Ожидание, пока вы нарисуете опорный пиксель...",
|
||||
@@ -150,6 +151,10 @@
|
||||
"paintTransparentPixelsDescription": "Если включено, прозрачные пиксели шаблона будут рисоваться",
|
||||
"paintUnavailablePixels": "Рисовать недоступные пиксели",
|
||||
"paintUnavailablePixelsDescription": "Если включено, недоступные цвета шаблона будут рисоваться ближайшим доступным цветом",
|
||||
"paintingModeAuto": "Авто",
|
||||
"paintingModeAssist": "Помощь",
|
||||
"paintingModeAutoDesc": "Бот будет автоматически рисовать пиксели",
|
||||
"paintingModeAssistDesc": "Оверлей будет направлять вашу ручную расстановку пикселей",
|
||||
"colorsUpdated": "✅ Доступные цвета увеличены {oldCount} -> {newCount}, найдено {diffCount} новых цветов",
|
||||
"overlayTilesNotLoaded": "❌ Необходимые тайлы карты не загружены. Проверьте соединение или попробуйте снова.",
|
||||
"paintingBatchFailed": "❌ Не удалось отправить пакет после нескольких попыток. Рисование остановлено.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Katmanı Aç/Kapat",
|
||||
"scanColors": "Renkleri Tara",
|
||||
"uploadImage": "Resim Yükle",
|
||||
"resizeImage": "Resmi Yeniden Boyutlandır",
|
||||
"resizeImage": "Resmi İşle/Düzenle",
|
||||
"selectPosition": "Konum Seç",
|
||||
"startPainting": "Boyamayı Başlat",
|
||||
"stopPainting": "Boyamayı Durdur",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Sitede renk paletini açın ve tekrar deneyin!",
|
||||
"colorsFound": "✅ {count} uygun renk bulundu. Yüklemeye hazır.",
|
||||
"loadingImage": "🖼️ Resim yükleniyor...",
|
||||
"imageLoaded": "✅ Resim {count} geçerli piksel ile yüklendi",
|
||||
"imageLoaded": "✅ Resim {count} geçerli piksel ile yüklendi ⚠️ Yerleştirmeden önce \"Resmi İşle/Düzenle\" yoluyla resmi işleyin!",
|
||||
"imageNeedsProcessing": "Resim işleme gerektirir ⚠️",
|
||||
"imageError": "❌ Resim yüklenirken hata oluştu",
|
||||
"selectPositionAlert": "Sanatı başlatmak istediğiniz ilk pikseli boyayın!",
|
||||
"waitingPosition": "👆 Referans pikseli boyamanız bekleniyor...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "Etkinleştirilirse, şablon şeffaf pikselleri boyanacaktır",
|
||||
"paintUnavailablePixels": "Kullanılamayan pikselleri boya",
|
||||
"paintUnavailablePixelsDescription": "Etkinleştirilirse, kullanılamayan şablon renkleri en yakın uygun renkle boyanacaktır",
|
||||
"paintingModeAuto": "Otomatik",
|
||||
"paintingModeAssist": "Yardımcı",
|
||||
"paintingModeAutoDesc": "Bot pikselleri otomatik olarak boyayacak",
|
||||
"paintingModeAssistDesc": "Katman, manuel piksel yerleştirmenizi yönlendirecek",
|
||||
"colorsUpdated": "✅ Uygun renkler arttı {oldCount} -> {newCount}, {diffCount} yeni renk bulundu",
|
||||
"overlayTilesNotLoaded": "❌ Gerekli harita karoları yüklenmedi. Bağlantıyı kontrol edin veya yeniden deneyin.",
|
||||
"paintingBatchFailed": "❌ Toplu gönderim birkaç denemeden sonra başarısız oldu. Boyama durduruldu.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Перемкнути оверлей",
|
||||
"scanColors": "Сканувати кольори",
|
||||
"uploadImage": "Завантажити зображення",
|
||||
"resizeImage": "Змінити розмір зображення",
|
||||
"resizeImage": "Обробити/Редагувати зображення",
|
||||
"selectPosition": "Вибрати позицію",
|
||||
"startPainting": "Почати малювання",
|
||||
"stopPainting": "Зупинити малювання",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Відкрий палітру кольорів на сайті та спробуй ще раз!",
|
||||
"colorsFound": "✅ Знайдено {count} доступних кольорів. Готово до завантаження.",
|
||||
"loadingImage": "🖼️ Завантаження зображення...",
|
||||
"imageLoaded": "✅ Зображення завантажено. Валідних пікселів: {count}",
|
||||
"imageLoaded": "✅ Зображення завантажено. Валідних пікселів: {count} ⚠️ Спочатку обробіть зображення через \"Обробити/Редагувати зображення\" перед розміщенням!",
|
||||
"imageNeedsProcessing": "Зображення потребує обробки ⚠️",
|
||||
"imageError": "❌ Помилка завантаження зображення",
|
||||
"selectPositionAlert": "Намалюй перший піксель у місці, де має починатися арт!",
|
||||
"waitingPosition": "👆 Очікування на малювання референсного пікселя...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "Якщо ввімкнено, прозорі пікселі шаблону будуть намальовані",
|
||||
"paintUnavailablePixels": "Малювати недоступні пікселі",
|
||||
"paintUnavailablePixelsDescription": "Якщо ввімкнено, недоступні кольори шаблону будуть намальовані найближчим доступним кольором",
|
||||
"paintingModeAuto": "Авто",
|
||||
"paintingModeAssist": "Допомога",
|
||||
"paintingModeAutoDesc": "Бот буде автоматично малювати пікселі",
|
||||
"paintingModeAssistDesc": "Оверлей буде направляти ваше ручне розташування пікселів",
|
||||
"colorsUpdated": "✅ Доступні кольори збільшено {oldCount} -> {newCount}, знайдено {diffCount} нових кольорів",
|
||||
"overlayTilesNotLoaded": "❌ Необхідні тайли карти не завантажені. Перевір з'єднання або спробуй знову.",
|
||||
"paintingBatchFailed": "❌ Не вдалося відправити пакет після кількох спроб. Малювання зупинено.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "Bật/tắt lớp phủ",
|
||||
"scanColors": "Quét màu",
|
||||
"uploadImage": "Tải lên hình ảnh",
|
||||
"resizeImage": "Thay đổi kích thước",
|
||||
"resizeImage": "Xử lý/Chỉnh sửa hình ảnh",
|
||||
"selectPosition": "Chọn vị trí",
|
||||
"startPainting": "Bắt đầu vẽ",
|
||||
"stopPainting": "Dừng vẽ",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ Hãy mở bảng màu trên trang web và thử lại!",
|
||||
"colorsFound": "✅ Tìm thấy {count} màu. Sẵn sàng để tải lên.",
|
||||
"loadingImage": "🖼️ Đang tải hình ảnh...",
|
||||
"imageLoaded": "✅ Đã tải hình ảnh với {count} pixel hợp lệ",
|
||||
"imageLoaded": "✅ Đã tải hình ảnh với {count} pixel hợp lệ ⚠️ Xử lý hình ảnh trước qua \"Xử lý/Chỉnh sửa hình ảnh\" trước khi đặt!",
|
||||
"imageNeedsProcessing": "Hình ảnh cần xử lý ⚠️",
|
||||
"imageError": "❌ Lỗi khi tải hình ảnh",
|
||||
"selectPositionAlert": "Vẽ pixel đầu tiên tại vị trí bạn muốn tác phẩm nghệ thuật bắt đầu!",
|
||||
"waitingPosition": "👆 Đang chờ bạn vẽ pixel tham chiếu...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "Nếu được bật, các pixel trong suốt của mẫu sẽ được vẽ",
|
||||
"paintUnavailablePixels": "Vẽ pixel không khả dụng",
|
||||
"paintUnavailablePixelsDescription": "Nếu được bật, màu mẫu không khả dụng sẽ được vẽ bằng màu khả dụng gần nhất",
|
||||
"paintingModeAuto": "Tự động",
|
||||
"paintingModeAssist": "Trợ giúp",
|
||||
"paintingModeAutoDesc": "Bot sẽ tự động vẽ pixel",
|
||||
"paintingModeAssistDesc": "Lớp phủ sẽ hướng dẫn việc đặt pixel thủ công của bạn",
|
||||
"colorsUpdated": "✅ Màu khả dụng tăng {oldCount} -> {newCount}, tìm thấy {diffCount} màu mới",
|
||||
"overlayTilesNotLoaded": "❌ Ô bản đồ cần thiết chưa được tải. Kiểm tra kết nối hoặc thử lại.",
|
||||
"paintingBatchFailed": "❌ Gửi lô thất bại sau nhiều lần thử. Dừng vẽ.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "切换覆盖层",
|
||||
"scanColors": "扫描颜色",
|
||||
"uploadImage": "上传图像",
|
||||
"resizeImage": "调整大小",
|
||||
"resizeImage": "处理/编辑图像",
|
||||
"selectPosition": "选择位置",
|
||||
"startPainting": "开始绘制",
|
||||
"stopPainting": "停止绘制",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ 请在网站上打开调色板后再试!",
|
||||
"colorsFound": "✅ 找到 {count} 个可用颜色,准备上传。",
|
||||
"loadingImage": "🖼️ 正在加载图像...",
|
||||
"imageLoaded": "✅ 图像已加载,包含 {count} 个有效像素",
|
||||
"imageLoaded": "✅ 图像已加载,包含 {count} 个有效像素 ⚠️ 放置前请先通过\"处理/编辑图像\"处理图像!",
|
||||
"imageNeedsProcessing": "图像需要处理 ⚠️",
|
||||
"imageError": "❌ 加载图像时出错",
|
||||
"selectPositionAlert": "请在你想让作品开始的位置绘制第一个像素!",
|
||||
"waitingPosition": "👆 正在等待你绘制参考像素...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "如果启用,将绘制模板透明像素",
|
||||
"paintUnavailablePixels": "绘制不可用像素",
|
||||
"paintUnavailablePixelsDescription": "如果启用,不可用的模板颜色将使用最接近的可用颜色绘制",
|
||||
"paintingModeAuto": "自动",
|
||||
"paintingModeAssist": "辅助",
|
||||
"paintingModeAutoDesc": "机器人将自动绘制像素",
|
||||
"paintingModeAssistDesc": "叠加层将引导您手动放置像素",
|
||||
"colorsUpdated": "✅ 可用颜色增加 {oldCount} -> {newCount},找到 {diffCount} 个新颜色",
|
||||
"overlayTilesNotLoaded": "❌ 所需的地图图块未加载。检查连接或重试。",
|
||||
"paintingBatchFailed": "❌ 多次尝试后批量发送失败。绘制已停止。",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"toggleOverlay": "切換覆蓋層",
|
||||
"scanColors": "掃描顏色",
|
||||
"uploadImage": "上傳圖像",
|
||||
"resizeImage": "調整大小",
|
||||
"resizeImage": "處理/編輯圖像",
|
||||
"selectPosition": "選擇位置",
|
||||
"startPainting": "開始繪製",
|
||||
"stopPainting": "停止繪製",
|
||||
@@ -11,7 +11,8 @@
|
||||
"noColorsFound": "❌ 請在網站上打開調色板後再試!",
|
||||
"colorsFound": "✅ 找到 {count} 個可用顏色,準備上傳。",
|
||||
"loadingImage": "🖼️ 正在載入圖像...",
|
||||
"imageLoaded": "✅ 圖像已載入,包含 {count} 個有效像素",
|
||||
"imageLoaded": "✅ 圖像已載入,包含 {count} 個有效像素 ⚠️ 放置前請先透過\"處理/編輯圖像\"處理圖像!",
|
||||
"imageNeedsProcessing": "圖像需要處理 ⚠️",
|
||||
"imageError": "❌ 載入圖像時出錯",
|
||||
"selectPositionAlert": "請在你想讓作品開始的位置繪製第一個像素!",
|
||||
"waitingPosition": "👆 正在等待你繪製參考像素...",
|
||||
@@ -151,6 +152,10 @@
|
||||
"paintTransparentPixelsDescription": "如果啟用,將繪製範本透明像素",
|
||||
"paintUnavailablePixels": "繪製不可用像素",
|
||||
"paintUnavailablePixelsDescription": "如果啟用,不可用的範本顏色將使用最接近的可用顏色繪製",
|
||||
"paintingModeAuto": "自動",
|
||||
"paintingModeAssist": "輔助",
|
||||
"paintingModeAutoDesc": "機器人將自動繪製像素",
|
||||
"paintingModeAssistDesc": "疊加層將引導您手動放置像素",
|
||||
"colorsUpdated": "✅ 可用顏色增加 {oldCount} -> {newCount},找到 {diffCount} 個新顏色",
|
||||
"overlayTilesNotLoaded": "❌ 所需的地圖圖塊未載入。檢查連線或重試。",
|
||||
"paintingBatchFailed": "❌ 多次嘗試後批次傳送失敗。繪製已停止。",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "WPlace AutoBOT Script Launcher",
|
||||
"version": "2.0.6",
|
||||
"version": "2.0.7",
|
||||
"description": "Launch and manage automation scripts for WPlace",
|
||||
"icons": {
|
||||
"16": "icons/icon16.png",
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
<footer>
|
||||
<div class="footer-info">
|
||||
<span>v2.0.6</span>
|
||||
<span>v2.0.7</span>
|
||||
<a href="#" id="settingsBtn">Settings</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -315,6 +315,17 @@ async function switchToAccount(index) {
|
||||
|
||||
console.log('✅ Account switched successfully');
|
||||
|
||||
// Auto-refresh the page after account switch
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
if (tab && tab.url.includes('wplace.live')) {
|
||||
console.log('🔄 Auto-refreshing page after account switch');
|
||||
await chrome.tabs.reload(tab.id);
|
||||
|
||||
// Close popup after a short delay
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error(response?.error || 'Failed to switch account');
|
||||
|
||||
+463
-15
@@ -57,8 +57,8 @@ localStorage.removeItem("lp");
|
||||
},
|
||||
OVERLAY: {
|
||||
OPACITY_DEFAULT: 0.6,
|
||||
BLUE_MARBLE_DEFAULT: false,
|
||||
ditheringEnabled: true,
|
||||
BLUE_MARBLE_DEFAULT: true, // Enable blue marble effect by default
|
||||
ditheringEnabled: false, // Default dithering OFF
|
||||
}, // --- START: Color data from colour-converter.js ---
|
||||
// New color structure with proper ID mapping
|
||||
COLOR_MAP: {
|
||||
@@ -692,7 +692,9 @@ localStorage.removeItem("lp");
|
||||
toggleOverlay: 'Toggle Overlay',
|
||||
scanColors: 'Scan Colors',
|
||||
uploadImage: 'Upload Image',
|
||||
resizeImage: 'Resize Image',
|
||||
resizeImage: 'Process/Edit Image',
|
||||
processImageFirst: '⚠️ Process the image first via "Process/Edit Image" before placing!',
|
||||
imageNeedsProcessing: 'Image needs processing',
|
||||
selectPosition: 'Select Position',
|
||||
startPainting: 'Start Painting',
|
||||
stopPainting: 'Stop Painting',
|
||||
@@ -1014,6 +1016,7 @@ localStorage.removeItem("lp");
|
||||
const state = {
|
||||
running: false,
|
||||
imageLoaded: false,
|
||||
imageProcessed: false, // Track if image has been processed through resize panel
|
||||
processing: false,
|
||||
totalPixels: 0,
|
||||
paintedPixels: 0,
|
||||
@@ -1087,6 +1090,7 @@ localStorage.removeItem("lp");
|
||||
accountIndex: 0, // Keep for backward compatibility with existing logic
|
||||
// Legacy state removed - now using accountManager instead
|
||||
isFetchingAllAccounts: false,
|
||||
paintingMode: 'auto', // 'auto' or 'assist' - default to auto
|
||||
};
|
||||
|
||||
// Expose state globally for the utils manager and other modules
|
||||
@@ -1173,12 +1177,198 @@ localStorage.removeItem("lp");
|
||||
}
|
||||
});
|
||||
|
||||
// Helper function to find closest color ID for assist mode
|
||||
function findClosestColorId(r, g, b) {
|
||||
let minDistance = Infinity;
|
||||
let closestColorId = null;
|
||||
|
||||
for (const colorData of Object.values(CONFIG.COLOR_MAP)) {
|
||||
if (!colorData.rgb) continue;
|
||||
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(r - colorData.rgb.r, 2) +
|
||||
Math.pow(g - colorData.rgb.g, 2) +
|
||||
Math.pow(b - colorData.rgb.b, 2)
|
||||
);
|
||||
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
closestColorId = colorData.id;
|
||||
}
|
||||
}
|
||||
|
||||
return closestColorId;
|
||||
}
|
||||
|
||||
const originalFetch = window.fetch;
|
||||
// Setup fetch interceptions
|
||||
console.log('🚀 [Auto-Image] Fetch interception initialized');
|
||||
|
||||
// Expose state for debugging
|
||||
window.__WPLACE_AUTOBOT_STATE__ = state;
|
||||
|
||||
window.fetch = async function (...args) {
|
||||
let url = args[0] instanceof Request ? args[0].url : args[0];
|
||||
|
||||
// Parse URL if it's a string
|
||||
let urlObj = null;
|
||||
if (typeof url === 'string') {
|
||||
try {
|
||||
urlObj = new URL(url);
|
||||
} catch (e) {
|
||||
// Invalid URL, proceed normally
|
||||
}
|
||||
}
|
||||
|
||||
// ASSIST MODE: Intercept pixel placement requests
|
||||
if (state.paintingMode === 'assist' && urlObj !== null && urlObj.pathname.startsWith('/s0/pixel')) {
|
||||
console.log(`🎯 [Assist Mode] Intercepting pixel placement:`, urlObj.pathname);
|
||||
console.log(`🔍 [Assist Mode] Check state - imageData:`, !!state.imageData, 'startPosition:', !!state.startPosition, 'body:', !!args[1]?.body);
|
||||
|
||||
// Check if we have overlay data
|
||||
if (state.imageData && state.startPosition && args[1]?.body) {
|
||||
try {
|
||||
// Parse region coordinates from URL path: /s0/pixel/{tileX}/{tileY}
|
||||
const pathParts = urlObj.pathname.split('/');
|
||||
const regionX = parseInt(pathParts[3]);
|
||||
const regionY = parseInt(pathParts[4]);
|
||||
|
||||
console.log(`📦 [Assist Mode] Region coords: (${regionX}, ${regionY})`);
|
||||
|
||||
// Parse request body
|
||||
const payload = typeof args[1].body === 'string' ? JSON.parse(args[1].body) : args[1].body;
|
||||
console.log(`📝 [Assist Mode] Original payload:`, JSON.stringify(payload));
|
||||
|
||||
// Debug: Check what's in state.region
|
||||
console.log(`🔍 [Assist Mode] state.region:`, state.region);
|
||||
console.log(`🔍 [Assist Mode] state.startPosition:`, state.startPosition);
|
||||
|
||||
// CRITICAL FIX: The issue is that startPosition is in TILE-LOCAL coordinates (0-999)
|
||||
// but we're clicking on a tile at (1732, 1014). We need to find which tile
|
||||
// our image overlay is on by checking all loaded tiles.
|
||||
|
||||
// For now, let's use the REQUEST's tile coordinates as a reference
|
||||
// If the user is clicking within this tile, check if our LOCAL startPosition
|
||||
// would overlap with the click position
|
||||
let startX, startY;
|
||||
|
||||
// COORDINATE RECONSTRUCTION
|
||||
// state.startPosition = LOCAL coords within a 1000x1000 tile (0-999)
|
||||
// state.region = TILE coordinates {x, y} (e.g., {x: 1732, y: 1014})
|
||||
// Absolute canvas coords = region.x * 1000 + startPosition.x
|
||||
|
||||
if (state.region && state.region.x !== undefined && state.region.y !== undefined) {
|
||||
// Use saved region to reconstruct absolute coordinates
|
||||
startX = state.region.x * 1000 + state.startPosition.x;
|
||||
startY = state.region.y * 1000 + state.startPosition.y;
|
||||
console.log(`[Assist Mode] Using saved region: tile=(${state.region.x},${state.region.y}) + local=(${state.startPosition.x},${state.startPosition.y}) = absolute (${startX},${startY})`);
|
||||
} else {
|
||||
// Fallback: assume image is on the clicked tile (may be wrong!)
|
||||
// Since startPosition appears to be LOCAL coords within a tile,
|
||||
// we need to convert them to absolute by finding which tile they're on.
|
||||
// The simplest approach: assume the image is on the tile being clicked!
|
||||
startX = regionX * 1000 + state.startPosition.x;
|
||||
startY = regionY * 1000 + state.startPosition.y;
|
||||
console.log(`[Assist Mode] No saved region - assuming image on clicked tile (${regionX},${regionY}): absolute = (${startX},${startY})`);
|
||||
}
|
||||
console.log(`� [Assist Mode] Assuming image is on clicked tile: absolute coords = (${startX},${startY})`);
|
||||
|
||||
const { width, height } = state.imageData;
|
||||
|
||||
console.log(`🖼️ [Assist Mode] Image bounds: start=(${startX},${startY}), size=${width}x${height}`);
|
||||
|
||||
// Calculate which tiles the image spans
|
||||
// Note: startX/startY are ABSOLUTE canvas coordinates (e.g., 1732432 means tile 1732, pixel 432)
|
||||
const imageStartTileX = Math.floor(startX / 1000);
|
||||
const imageStartTileY = Math.floor(startY / 1000);
|
||||
const imageEndTileX = Math.floor((startX + width - 1) / 1000);
|
||||
const imageEndTileY = Math.floor((startY + height - 1) / 1000);
|
||||
|
||||
console.log(`🗺️ [Assist Mode] Image tiles: X[${imageStartTileX}-${imageEndTileX}], Y[${imageStartTileY}-${imageEndTileY}]`);
|
||||
console.log(`🎯 [Assist Mode] Checking if region (${regionX},${regionY}) overlaps...`);
|
||||
|
||||
if (regionX >= imageStartTileX && regionX <= imageEndTileX &&
|
||||
regionY >= imageStartTileY && regionY <= imageEndTileY) {
|
||||
|
||||
console.log(`✅ [Assist Mode] Region (${regionX},${regionY}) overlaps with image - modifying pixels`);
|
||||
|
||||
// Modify the colors array based on overlay data
|
||||
if (payload.coords && payload.colors) {
|
||||
let modifiedCount = 0;
|
||||
|
||||
for (let i = 0; i < payload.coords.length; i += 2) {
|
||||
// Calculate absolute pixel position
|
||||
const absoluteX = regionX * 1000 + payload.coords[i];
|
||||
const absoluteY = regionY * 1000 + payload.coords[i + 1];
|
||||
|
||||
// Calculate position relative to our image
|
||||
const imgX = absoluteX - startX;
|
||||
const imgY = absoluteY - startY;
|
||||
|
||||
console.log(`🎨 [Assist Mode] Pixel ${i/2}: absolute=(${absoluteX},${absoluteY}), relative=(${imgX},${imgY})`);
|
||||
|
||||
// Check if pixel is within our image bounds
|
||||
if (imgX >= 0 && imgX < width && imgY >= 0 && imgY < height) {
|
||||
// Get color from processed image data
|
||||
// Note: state.imageData uses 'pixels' property, not 'data'
|
||||
const pixelData = state.imageData.pixels || state.imageData.data;
|
||||
if (!pixelData) {
|
||||
console.error(`❌ [Assist Mode] No pixel data available in state.imageData`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const pixelIndex = (imgY * width + imgX) * 4;
|
||||
const r = pixelData[pixelIndex];
|
||||
const g = pixelData[pixelIndex + 1];
|
||||
const b = pixelData[pixelIndex + 2];
|
||||
const a = pixelData[pixelIndex + 3];
|
||||
|
||||
console.log(`🎨 [Assist Mode] Color at (${imgX},${imgY}): rgba(${r},${g},${b},${a}), original colorId: ${payload.colors[i/2]}`);
|
||||
|
||||
// Skip transparent pixels
|
||||
if (a < CONFIG.TRANSPARENCY_THRESHOLD) {
|
||||
console.log(`⏭️ [Assist Mode] Skipping transparent pixel`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find matching color from palette
|
||||
const colorId = findClosestColorId(r, g, b);
|
||||
console.log(`🔍 [Assist Mode] Found closest colorId: ${colorId}`);
|
||||
if (colorId) {
|
||||
const oldColorId = payload.colors[i / 2];
|
||||
payload.colors[i / 2] = colorId;
|
||||
console.log(`✏️ [Assist Mode] Changed colorId from ${oldColorId} to ${colorId}`);
|
||||
modifiedCount++;
|
||||
}
|
||||
} else {
|
||||
console.log(`❌ [Assist Mode] Pixel out of bounds`);
|
||||
}
|
||||
}
|
||||
|
||||
// Update request body with modified payload
|
||||
args[1] = {
|
||||
...args[1],
|
||||
body: JSON.stringify(payload)
|
||||
};
|
||||
|
||||
console.log(`✅ [Assist Mode] Modified ${modifiedCount} pixel color(s)`);
|
||||
console.log(`📝 [Assist Mode] Modified payload:`, JSON.stringify(payload));
|
||||
} else {
|
||||
console.warn(`⚠️ [Assist Mode] Payload missing coords or colors`);
|
||||
}
|
||||
} else {
|
||||
console.log(`⏭️ [Assist Mode] Region (${regionX},${regionY}) does NOT overlap with image`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ [Assist Mode] Error intercepting pixel placement:', error);
|
||||
console.error(error.stack);
|
||||
}
|
||||
} else {
|
||||
console.warn('⚠️ [Assist Mode] No overlay data available - imageData:', !!state.imageData, 'startPosition:', !!state.startPosition);
|
||||
}
|
||||
}
|
||||
|
||||
const response = await originalFetch.apply(this, args);
|
||||
const url = args[0] instanceof Request ? args[0].url : args[0];
|
||||
|
||||
// TILE REQUEST logging removed to reduce console spam
|
||||
|
||||
@@ -1304,6 +1494,37 @@ localStorage.removeItem("lp");
|
||||
}
|
||||
return getText(key, params);
|
||||
},
|
||||
|
||||
// Open website color palette if not already open
|
||||
openColorPalette: () => {
|
||||
try {
|
||||
// Check if color palette modal is already open
|
||||
const paletteModal = document.querySelector('dialog[open]');
|
||||
if (paletteModal) {
|
||||
console.log('✅ Color palette already open');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search for Paint/Pintar button (like Auto-Farm does)
|
||||
const allButtons = Array.from(document.querySelectorAll('button'));
|
||||
const paletteButton = allButtons.find(btn =>
|
||||
/(Pintar|Paint)/i.test(btn.textContent.trim())
|
||||
);
|
||||
|
||||
if (paletteButton) {
|
||||
console.log('🎨 Opening color palette automatically...');
|
||||
paletteButton.click();
|
||||
return true;
|
||||
}
|
||||
|
||||
console.warn('⚠️ Color palette button not found');
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('❌ Error opening color palette:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
showAlert: (message, type) => {
|
||||
if (window.globalUtilsManager) {
|
||||
window.globalUtilsManager.showAlert(message, type);
|
||||
@@ -2476,12 +2697,19 @@ localStorage.removeItem("lp");
|
||||
<span>${Utils.t('stopPainting')}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="wplace-row single">
|
||||
<button id="toggleOverlayBtn" class="wplace-btn wplace-btn-overlay" disabled>
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>${Utils.t('toggleOverlay')}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="wplace-row" style="display: flex; gap: 8px; align-items: center;">
|
||||
<button id="toggleOverlayBtn" class="wplace-btn wplace-btn-overlay" disabled style="flex: 1;">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>${Utils.t('toggleOverlay')}</span>
|
||||
</button>
|
||||
<label class="wplace-mode-toggle">
|
||||
<input type="checkbox" id="paintingModeToggle" aria-label="Toggle painting mode">
|
||||
<div class="wplace-mode-toggle-inner">
|
||||
<span class="wplace-mode-option wplace-mode-option-auto">Auto</span>
|
||||
<span class="wplace-mode-option wplace-mode-option-assist">Assist</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3186,6 +3414,80 @@ localStorage.removeItem("lp");
|
||||
.wplace-content::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
/* Painting Mode segmented control */
|
||||
.wplace-mode-toggle {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.wplace-mode-toggle input {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.wplace-mode-toggle-inner {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-width: 140px;
|
||||
border-radius: 999px;
|
||||
background: var(--surface-variant, #2a2a2a);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wplace-mode-toggle-inner::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: calc(50% - 2px);
|
||||
height: calc(100% - 4px);
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
|
||||
border-radius: inherit;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.wplace-mode-toggle input:checked + .wplace-mode-toggle-inner::before {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.wplace-mode-option {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
padding: 8px 0;
|
||||
color: var(--text-secondary, #909090);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
transition: color 0.25s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.wplace-mode-toggle input:not(:checked) + .wplace-mode-toggle-inner .wplace-mode-option-auto,
|
||||
.wplace-mode-toggle input:checked + .wplace-mode-toggle-inner .wplace-mode-option-assist {
|
||||
color: var(--text-primary, #ffffff);
|
||||
}
|
||||
|
||||
.wplace-mode-toggle:focus-within .wplace-mode-toggle-inner {
|
||||
outline: 2px solid rgba(79, 172, 254, 0.4);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
@@ -4173,6 +4475,9 @@ localStorage.removeItem("lp");
|
||||
|
||||
if (loadBtn) {
|
||||
loadBtn.addEventListener('click', async () => {
|
||||
// Auto-open color palette if not already open
|
||||
Utils.openColorPalette();
|
||||
|
||||
const savedData = Utils.loadProgress();
|
||||
if (!savedData) {
|
||||
updateUI('noSavedData', 'warning');
|
||||
@@ -4998,9 +5303,12 @@ localStorage.removeItem("lp");
|
||||
};
|
||||
|
||||
// Skip expensive dithering while user is dragging sliders
|
||||
console.log(`🎨 Preview render - ditheringEnabled: ${state.ditheringEnabled}, _isDraggingSize: ${_isDraggingSize}`);
|
||||
if (state.ditheringEnabled && !_isDraggingSize) {
|
||||
console.log('✅ Applying dithering to preview');
|
||||
applyFSDither();
|
||||
} else {
|
||||
console.log('⛔ Skipping dithering - applying direct color conversion');
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i],
|
||||
g = data[i + 1],
|
||||
@@ -5799,6 +6107,17 @@ localStorage.removeItem("lp");
|
||||
width: newWidth,
|
||||
height: newHeight,
|
||||
});
|
||||
|
||||
// ✅ Mark image as processed and enable position selection
|
||||
state.imageProcessed = true;
|
||||
selectPosBtn.disabled = false;
|
||||
selectPosBtn.title = Utils.t('selectPosition') || 'Select starting position on canvas';
|
||||
|
||||
// Enable start button if position is already set
|
||||
if (state.startPosition) {
|
||||
startBtn.disabled = false;
|
||||
}
|
||||
|
||||
closeResizeDialog();
|
||||
};
|
||||
|
||||
@@ -7450,6 +7769,9 @@ localStorage.removeItem("lp");
|
||||
|
||||
if (uploadBtn) {
|
||||
uploadBtn.addEventListener('click', async () => {
|
||||
// Auto-open color palette if not already open
|
||||
Utils.openColorPalette();
|
||||
|
||||
const availableColors = Utils.extractAvailableColors();
|
||||
if (availableColors === null || availableColors.length < 10) {
|
||||
updateUI('noColorsFound', 'error');
|
||||
@@ -7510,6 +7832,7 @@ localStorage.removeItem("lp");
|
||||
state.paintedPixels = 0;
|
||||
state.currentPaintingColor = null; // Reset color tracking
|
||||
state.imageLoaded = true;
|
||||
state.imageProcessed = false; // New upload - not processed yet
|
||||
|
||||
// Reset session-specific flags when a new image is loaded
|
||||
state.preFilteringDone = false;
|
||||
@@ -7530,7 +7853,7 @@ localStorage.removeItem("lp");
|
||||
state.originalImage = { dataUrl: imageSrc, width, height };
|
||||
saveBotSettings();
|
||||
|
||||
// Use the original image for the overlay initially
|
||||
// ⚠️ Use the ORIGINAL image for the overlay initially (will be replaced after processing)
|
||||
const imageBitmap = await createImageBitmap(processor.img);
|
||||
await overlayManager.setImage(imageBitmap);
|
||||
overlayManager.enable();
|
||||
@@ -7544,12 +7867,20 @@ localStorage.removeItem("lp");
|
||||
}
|
||||
saveBtn.disabled = false;
|
||||
|
||||
// ⚠️ IMPORTANT: Disable position selection until image is processed
|
||||
selectPosBtn.disabled = true;
|
||||
selectPosBtn.title = Utils.t('imageNeedsProcessing');
|
||||
|
||||
// Disable start button since position can't be set yet
|
||||
if (state.startPosition) {
|
||||
startBtn.disabled = false;
|
||||
startBtn.disabled = true; // Disable even if position was set before
|
||||
}
|
||||
|
||||
await updateStats();
|
||||
updateDataButtons();
|
||||
|
||||
// Show warning alert to process image first
|
||||
Utils.showAlert(Utils.t('processImageFirst'), 'warning');
|
||||
updateUI('imageLoaded', 'success', { count: totalValidPixels });
|
||||
} catch {
|
||||
updateUI('imageError', 'error');
|
||||
@@ -7562,6 +7893,9 @@ localStorage.removeItem("lp");
|
||||
if (loadExtractedBtn) {
|
||||
loadExtractedBtn.addEventListener('click', async () => {
|
||||
try {
|
||||
// Auto-open color palette if not already open
|
||||
Utils.openColorPalette();
|
||||
|
||||
updateUI('loadingImage', 'default');
|
||||
const fileData = await Utils.loadExtractedFileData();
|
||||
|
||||
@@ -7673,6 +8007,15 @@ localStorage.removeItem("lp");
|
||||
// For extracted images, ensure overlay is enabled but don't set position yet
|
||||
try {
|
||||
if (overlayManager && state.imageData) {
|
||||
console.log('🖼️ Creating overlay from loaded pixel data:', {
|
||||
width: state.imageData.width,
|
||||
height: state.imageData.height,
|
||||
pixelCount: state.imageData.pixels?.length,
|
||||
firstPixels: state.imageData.pixels?.slice(0, 12), // First 3 pixels (RGBA)
|
||||
isUint8ClampedArray: state.imageData.pixels instanceof Uint8ClampedArray,
|
||||
isArray: Array.isArray(state.imageData.pixels)
|
||||
});
|
||||
|
||||
// Create image bitmap from the restored image data
|
||||
const canvas = new OffscreenCanvas(state.imageData.width, state.imageData.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
@@ -7686,7 +8029,15 @@ localStorage.removeItem("lp");
|
||||
|
||||
await overlayManager.setImage(imageBitmap);
|
||||
overlayManager.enable();
|
||||
console.log('✅ Overlay enabled for extracted artwork');
|
||||
console.log('✅ Overlay enabled for extracted artwork - should show PROCESSED pixels');
|
||||
|
||||
// ✅ Loaded files already contain processed pixels - no need to reprocess
|
||||
// Mark as processed since the overlay is showing the correct processed data
|
||||
state.imageProcessed = true;
|
||||
|
||||
// Enable position selection immediately
|
||||
selectPosBtn.disabled = false;
|
||||
selectPosBtn.title = Utils.t('selectPosition') || 'Select starting position on canvas';
|
||||
}
|
||||
} catch (overlayError) {
|
||||
console.warn('⚠️ Could not set overlay for extracted artwork:', overlayError);
|
||||
@@ -7978,10 +8329,52 @@ localStorage.removeItem("lp");
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to update start button state
|
||||
function updateStartButtonState() {
|
||||
if (!startBtn) return;
|
||||
|
||||
if (state.paintingMode === 'assist') {
|
||||
startBtn.disabled = true;
|
||||
startBtn.title = 'Start button is disabled in Assist mode. Manually place pixels with overlay guidance.';
|
||||
} else {
|
||||
startBtn.disabled = !state.imageLoaded || state.running || !state.startPosition;
|
||||
startBtn.title = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (startBtn) {
|
||||
startBtn.addEventListener('click', startPainting);
|
||||
}
|
||||
|
||||
// Painting Mode Toggle
|
||||
const paintingModeToggle = container.querySelector('#paintingModeToggle');
|
||||
if (paintingModeToggle) {
|
||||
// Initialize toggle state - MUST be unchecked for auto mode (default)
|
||||
paintingModeToggle.checked = state.paintingMode === 'assist';
|
||||
console.log(`🎨 [Painting Mode] Initial state: ${state.paintingMode}, Toggle checked: ${paintingModeToggle.checked}`);
|
||||
|
||||
paintingModeToggle.addEventListener('change', () => {
|
||||
state.paintingMode = paintingModeToggle.checked ? 'assist' : 'auto';
|
||||
|
||||
// Update start button state
|
||||
updateStartButtonState();
|
||||
|
||||
// NOTE: We don't save paintingMode - it always resets to 'auto' on page load
|
||||
|
||||
// Show notification
|
||||
const modeName = state.paintingMode === 'assist' ? 'Assist' : 'Auto';
|
||||
const modeDesc = state.paintingMode === 'assist'
|
||||
? 'Overlay will guide your manual pixel placement'
|
||||
: 'Bot will automatically paint pixels';
|
||||
Utils.showAlert(`Painting Mode: ${modeName}\n${modeDesc}`, 'info');
|
||||
|
||||
console.log(`🎨 [Painting Mode] Switched to ${modeName.toUpperCase()} mode`);
|
||||
});
|
||||
|
||||
// Initial state update
|
||||
updateStartButtonState();
|
||||
}
|
||||
|
||||
if (stopBtn) {
|
||||
stopBtn.addEventListener('click', () => {
|
||||
state.stopFlag = true;
|
||||
@@ -8114,6 +8507,13 @@ localStorage.removeItem("lp");
|
||||
loadBotSettings();
|
||||
// Ensure notification poller reflects current settings
|
||||
NotificationManager.syncFromState();
|
||||
|
||||
// Sync painting mode toggle with loaded state
|
||||
if (paintingModeToggle) {
|
||||
paintingModeToggle.checked = state.paintingMode === 'assist';
|
||||
updateStartButtonState();
|
||||
console.log(`🔄 [Painting Mode] Synced after load: ${state.paintingMode}, Toggle checked: ${paintingModeToggle.checked}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getMsToTargetCharges(current, target, cooldown, intervalMs = 0) {
|
||||
@@ -9464,6 +9864,12 @@ localStorage.removeItem("lp");
|
||||
notifyOnlyWhenUnfocused: state.notifyOnlyWhenUnfocused,
|
||||
notificationIntervalMinutes: state.notificationIntervalMinutes,
|
||||
originalImage: state.originalImage,
|
||||
ditheringMigrated: true, // Migration flag for dithering default change
|
||||
blueMarbleMigrated: true, // Migration flag for blue marble default change
|
||||
// NOTE: paintingMode is intentionally NOT saved - always defaults to 'auto' on page load
|
||||
// Save region and startPosition for assist mode coordinate calculations
|
||||
region: state.region,
|
||||
startPosition: state.startPosition,
|
||||
};
|
||||
CONFIG.PAINTING_SPEED_ENABLED = settings.paintingSpeedEnabled;
|
||||
// AUTO_CAPTCHA_ENABLED is always true - no need to save/load
|
||||
@@ -9492,8 +9898,31 @@ localStorage.removeItem("lp");
|
||||
CONFIG.PAINTING_SPEED_ENABLED = settings.paintingSpeedEnabled ?? false;
|
||||
CONFIG.AUTO_CAPTCHA_ENABLED = settings.autoCaptchaEnabled ?? false;
|
||||
state.overlayOpacity = settings.overlayOpacity ?? CONFIG.OVERLAY.OPACITY_DEFAULT;
|
||||
state.blueMarbleEnabled = settings.blueMarbleEnabled ?? CONFIG.OVERLAY.BLUE_MARBLE_DEFAULT;
|
||||
state.ditheringEnabled = settings.ditheringEnabled ?? false;
|
||||
|
||||
// MIGRATION: Force enable blue marble for existing users if not explicitly set
|
||||
// This ensures the new default (blue marble ON) is applied to existing users
|
||||
if (settings.blueMarbleMigrated !== true) {
|
||||
state.blueMarbleEnabled = true;
|
||||
console.log('🔄 Migrated: Blue Marble enabled (new default)');
|
||||
// Save the migration flag
|
||||
settings.blueMarbleMigrated = true;
|
||||
localStorage.setItem('wplace-bot-settings', JSON.stringify(settings));
|
||||
} else {
|
||||
state.blueMarbleEnabled = settings.blueMarbleEnabled ?? CONFIG.OVERLAY.BLUE_MARBLE_DEFAULT;
|
||||
}
|
||||
|
||||
// MIGRATION: Force reset dithering to false if not explicitly set in saved settings
|
||||
// This ensures the new default (dithering OFF) is applied to existing users
|
||||
if (settings.ditheringMigrated !== true) {
|
||||
state.ditheringEnabled = false;
|
||||
console.log('🔄 Migrated: Dithering reset to OFF (new default)');
|
||||
// Save the migration flag
|
||||
settings.ditheringMigrated = true;
|
||||
localStorage.setItem('wplace-bot-settings', JSON.stringify(settings));
|
||||
} else {
|
||||
state.ditheringEnabled = settings.ditheringEnabled ?? false;
|
||||
}
|
||||
|
||||
state.colorMatchingAlgorithm = settings.colorMatchingAlgorithm || 'lab';
|
||||
state.enableChromaPenalty = settings.enableChromaPenalty ?? true;
|
||||
state.chromaPenaltyWeight = settings.chromaPenaltyWeight ?? 0.15;
|
||||
@@ -9518,6 +9947,18 @@ localStorage.removeItem("lp");
|
||||
settings.notifyOnlyWhenUnfocused ?? CONFIG.NOTIFICATIONS.ONLY_WHEN_UNFOCUSED;
|
||||
state.notificationIntervalMinutes =
|
||||
settings.notificationIntervalMinutes ?? CONFIG.NOTIFICATIONS.REPEAT_MINUTES;
|
||||
// NOTE: paintingMode is NOT restored - always defaults to 'auto' on page load
|
||||
|
||||
// Restore region and startPosition for assist mode coordinate calculations
|
||||
if (settings.region) {
|
||||
state.region = settings.region;
|
||||
console.log('✅ Restored region from save file:', state.region);
|
||||
}
|
||||
if (settings.startPosition) {
|
||||
state.startPosition = settings.startPosition;
|
||||
console.log('✅ Restored startPosition from save file:', state.startPosition);
|
||||
}
|
||||
|
||||
// Restore ignore mask if dims match current resizeSettings
|
||||
if (
|
||||
settings.resizeIgnoreMask &&
|
||||
@@ -10695,6 +11136,13 @@ localStorage.removeItem("lp");
|
||||
const transInput = document.getElementById('transparencyThresholdInput');
|
||||
const whiteInput = document.getElementById('whiteThresholdInput');
|
||||
const ditherToggle = document.getElementById('enableDitheringToggle');
|
||||
|
||||
// Ensure dithering checkbox matches state (explicit sync on init)
|
||||
if (ditherToggle) {
|
||||
ditherToggle.checked = state.ditheringEnabled;
|
||||
console.log(`🎨 Dithering initialized: ${state.ditheringEnabled ? 'ON' : 'OFF'}`);
|
||||
}
|
||||
|
||||
if (algoSelect)
|
||||
algoSelect.addEventListener('change', (e) => {
|
||||
state.colorMatchingAlgorithm = e.target.value;
|
||||
|
||||
@@ -149,6 +149,7 @@ class OverlayManager {
|
||||
|
||||
// Method 2: Force browser to bypass cache by adding cache-busting parameter
|
||||
// We need to intercept and modify tile requests to add cache-busting
|
||||
// IMPORTANT: Preserve any existing fetch override (e.g., from Auto-Image assist mode)
|
||||
const originalFetch = window.fetch;
|
||||
let fetchOverrideActive = true;
|
||||
|
||||
@@ -167,6 +168,7 @@ class OverlayManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Chain to previous fetch (which may have assist mode logic)
|
||||
return originalFetch.apply(this, args);
|
||||
};
|
||||
|
||||
|
||||
@@ -1165,6 +1165,13 @@ class WPlaceUtilsManager {
|
||||
|
||||
try {
|
||||
console.log('🔄 Restoring overlay from saved data...');
|
||||
console.log('📊 Pixel data info:', {
|
||||
width: window.state.imageData.width,
|
||||
height: window.state.imageData.height,
|
||||
pixelCount: window.state.imageData.pixels?.length,
|
||||
firstPixels: window.state.imageData.pixels?.slice(0, 12), // First 3 pixels (RGBA)
|
||||
isProcessed: '⚠️ These should be PROCESSED pixels if saved after processing'
|
||||
});
|
||||
|
||||
// Recreate ImageBitmap from loaded pixel data (match old version exactly)
|
||||
const imageData = new ImageData(
|
||||
|
||||
@@ -68,6 +68,8 @@ Follow the exact same steps listed for Chrome above, using Kiwi Browser instead.
|
||||
- [x] Automatically farms droplets/levels
|
||||
|
||||
- [X] Artwork Extractor(copy-paste artworks)
|
||||
|
||||
- [x] Painting Assist
|
||||
|
||||
- [X] Quick Art mover feature
|
||||
|
||||
@@ -92,7 +94,7 @@ Follow the exact same steps listed for Chrome above, using Kiwi Browser instead.
|
||||
- [x] Works on mobile (via browsers like Kiwi) :P
|
||||
|
||||
<p align="center">
|
||||
<img src="https://i.imgur.com/5QYvb4w.png" alt="Script Demonstration"/>
|
||||
<img src="https://i.imgur.com/D6KsXQT.png" alt="Script Demonstration"/>
|
||||
</p>
|
||||
|
||||
📋┃To-do
|
||||
|
||||
Reference in new issue
Block a user