diff --git a/Auto-Image.js b/Auto-Image.js index c9f3e42..3b12d07 100644 --- a/Auto-Image.js +++ b/Auto-Image.js @@ -1064,8 +1064,6 @@ resizeSettings: null, originalImage: null, resizeIgnoreMask: null, - antiGriefEnabled: false, - _antiGriefTimer: null, } let _updateResizePreview = () => { }; @@ -2492,16 +2490,10 @@ // Update overlay button state const toggleOverlayBtn = document.getElementById('toggleOverlayBtn'); - const antiGriefBtn = document.getElementById('antiGriefBtn'); if (toggleOverlayBtn) { toggleOverlayBtn.disabled = false; toggleOverlayBtn.classList.add('active'); } - const antiGriefBtn2 = document.getElementById('antiGriefBtn'); - if (antiGriefBtn2) antiGriefBtn2.disabled = false; - if (antiGriefBtn) { - antiGriefBtn.disabled = false; - } console.log('Overlay restored from data'); return true; @@ -2684,147 +2676,11 @@ return bestId } - + // UI UPDATE FUNCTIONS (declared early to avoid reference errors) let updateUI = () => { } let updateStats = () => { } let updateDataButtons = () => { } - async function startAntiGrief() { - stopAntiGrief(); - if (!state.imageLoaded || !state.startPosition || !state.region) return; - state.antiGriefEnabled = true; - const antiGriefBtn = document.getElementById('antiGriefBtn'); - if (antiGriefBtn) { - antiGriefBtn.disabled = false; - antiGriefBtn.classList.add('active'); - antiGriefBtn.setAttribute('aria-pressed', 'true'); - } - - const defendOnce = async () => { - if (!state.antiGriefEnabled) return; - if (!state.imageLoaded || !state.startPosition || !state.region) return; - if (state.running) return; // skip while painting is running - try { - // Ensure we have latest tile caches to read colors - if (overlayManager && overlayManager.imageBitmap && overlayManager.startCoords) { - await overlayManager.processImageIntoChunks(); - } - - const { width, height, pixels } = state.imageData; - const mask = (state.resizeIgnoreMask && state.resizeIgnoreMask.length === width * height) ? state.resizeIgnoreMask : null; - const { x: startX, y: startY } = state.startPosition; - const { x: regionX, y: regionY } = state.region; - - const tileSize = 1000; - let totalMismatches = 0; - - for (let localY = 0; localY < height && state.antiGriefEnabled; localY++) { - const absY = startY + localY; - const adderY = Math.floor(absY / tileSize); - const pixelY = absY % tileSize; - let currentRegionX = null, currentRegionY = regionY + adderY; - let batch = null; - - for (let localX = 0; localX < width && state.antiGriefEnabled; localX++) { - const pixIndex = (localY * width + localX); - if (mask && mask[pixIndex]) continue; - const idx = pixIndex * 4; - const r = pixels[idx], g = pixels[idx + 1], b = pixels[idx + 2], a = pixels[idx + 3]; - const tThresh = state.customTransparencyThreshold || CONFIG.TRANSPARENCY_THRESHOLD; - if (a < tThresh) continue; - if (!state.paintWhitePixels && Utils.isWhitePixel(r, g, b)) continue; - - const absX = startX + localX; - const adderX = Math.floor(absX / tileSize); - const pixelX = absX % tileSize; - - const regionTileX = regionX + adderX; - const regionTileY = regionY + adderY; - - if (currentRegionX === null) currentRegionX = regionTileX; - if (regionTileX !== currentRegionX) { - if (batch && batch.pixels.length > 0) { - const ok = await sendBatchWithRetry(batch.pixels, batch.regionX, batch.regionY); - if (ok) { - state.currentCharges = Math.max(0, state.currentCharges - batch.pixels.length); - } - } - batch = null; - currentRegionX = regionTileX; - } - - let existing = null; - try { - existing = await overlayManager.getTilePixelColor(regionTileX, regionTileY, pixelX, pixelY); - } catch (_) {} - if (!existing) continue; - const [er, eg, eb] = existing; - - // Desired palette color - const desiredId = findClosestColor([r, g, b], state.availableColors); - const existingId = findClosestColor([er, eg, eb], state.availableColors); - if (desiredId === existingId) continue; // already correct - - // Initialize batch for this region - if (!batch) batch = { regionX: regionTileX, regionY: regionTileY, pixels: [] }; - batch.pixels.push({ x: pixelX, y: pixelY, color: desiredId }); - totalMismatches++; - - if (batch.pixels.length >= Math.max(1, Math.floor(state.currentCharges))) { - await ensureToken(); - const ok = await sendBatchWithRetry(batch.pixels, batch.regionX, batch.regionY); - if (ok) { - state.currentCharges = Math.max(0, state.currentCharges - batch.pixels.length); - } - batch.pixels = []; - - while (state.currentCharges < Math.max(1, state.cooldownChargeThreshold) && state.antiGriefEnabled && !state.running) { - const { charges, cooldown } = await WPlaceService.getCharges(); - state.currentCharges = Math.floor(charges); - state.cooldown = cooldown; - if (state.currentCharges >= state.cooldownChargeThreshold) break; - await Utils.sleep(Math.max(1000, cooldown)); - } - } - } - - // Flush the row's last batch - if (batch && batch.pixels.length > 0 && state.antiGriefEnabled) { - await ensureToken(); - const ok = await sendBatchWithRetry(batch.pixels, batch.regionX, batch.regionY); - if (ok) { - state.currentCharges = Math.max(0, state.currentCharges - batch.pixels.length); - } - } - } - - if (totalMismatches > 0) { - console.log(`🛡️ Anti-Grief repainted ${totalMismatches} pixels.`); - } - } catch (e) { - console.warn('Anti-Grief iteration failed:', e); - } finally { - try { await updateStats(); } catch {} - } - }; - - await defendOnce(); - state._antiGriefTimer = setInterval(defendOnce, 30000); - } - - function stopAntiGrief() { - state.antiGriefEnabled = false; - if (state._antiGriefTimer) { - clearInterval(state._antiGriefTimer); - state._antiGriefTimer = null; - } - const antiGriefBtn = document.getElementById('antiGriefBtn'); - if (antiGriefBtn) { - antiGriefBtn.classList.remove('active'); - antiGriefBtn.setAttribute('aria-pressed', 'false'); - } - } - function updateActiveColorPalette() { state.activeColorPalette = []; const activeSwatches = document.querySelectorAll('.wplace-color-swatch.active'); @@ -2846,7 +2702,7 @@ const swatches = document.querySelectorAll('.wplace-color-swatch'); if (swatches) { swatches.forEach(swatch => { - + // Only toggle colors that are available or if we're showing unavailable colors const isUnavailable = swatch.classList.contains('unavailable'); if (!isUnavailable || showingUnavailable) { // Don't try to select unavailable colors @@ -2864,9 +2720,10 @@ const showAllToggle = container.querySelector('#showAllColorsToggle'); if (!colorsContainer) return; - + // Use already captured colors from state (captured during upload) + // Don't re-fetch colors here, use what was captured when user clicked upload if (!state.availableColors || state.availableColors.length === 0) { - + // If no colors have been captured yet, show message colorsContainer.innerHTML = '