diff --git a/Auto-Image.js b/Auto-Image.js
index b0a0885..dd309f6 100644
--- a/Auto-Image.js
+++ b/Auto-Image.js
@@ -31,8 +31,7 @@
OPACITY_DEFAULT: 0.2,
BLUE_MARBLE_DEFAULT: false,
ditheringEnabled: false,
- },
- // --- START: Color data from colour-converter.js ---
+ }, // --- START: Color data from colour-converter.js ---
// New color structure with proper ID mapping
COLOR_MAP: {
0: { id: 1, name: 'Black', rgb: { r: 0, g: 0, b: 0 } },
@@ -99,8 +98,7 @@
61: { id: 59, name: 'Slate', rgb: { r: 109, g: 117, b: 141 } },
62: { id: 60, name: 'Light Slate', rgb: { r: 179, g: 185, b: 209 } },
63: { id: 0, name: 'Transparent', rgb: null },
- },
- // --- END: Color data ---
+ }, // --- END: Color data ---
// Optimized CSS Classes for reuse
CSS_CLASSES: {
BUTTON_PRIMARY: `
@@ -329,7 +327,9 @@
) {
loadedTranslations[language] = translations;
console.log(
- `📚 Loaded ${language} translations successfully from CDN (${Object.keys(translations).length} keys)`
+ `📚 Loaded ${language} translations successfully from CDN (${
+ Object.keys(translations).length
+ } keys)`
);
return translations;
} else {
@@ -1295,7 +1295,7 @@
dynamicSleep: async function (getRemainingMsFn, interval = 500) {
let remaining = getRemainingMsFn();
- while (remaining > 0) {
+ while (remaining > 100) {
await this.sleep(Math.min(interval, remaining));
remaining = getRemainingMsFn();
}
@@ -1320,12 +1320,7 @@
if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;
if (minutes > 0) return `${minutes}m ${seconds}s`;
return `${seconds}s`;
- }, // Turnstile Generator Integration - Optimized with widget reuse and proper cleanup
- turnstileLoaded: false,
- _turnstileContainer: null,
- _turnstileOverlay: null,
- _turnstileWidgetId: null,
- _lastSitekey: null,
+ },
/**
* Calculate the range of tile coordinates (in region space) that cover a given image area.
@@ -1356,7 +1351,12 @@
endTileX: startRegionX + Math.floor((endPixelX - 1) / tileSize),
endTileY: startRegionY + Math.floor((endPixelY - 1) / tileSize),
};
- },
+ }, // Turnstile Generator Integration - Optimized with widget reuse and proper cleanup
+ turnstileLoaded: false,
+ _turnstileContainer: null,
+ _turnstileOverlay: null,
+ _turnstileWidgetId: null,
+ _lastSitekey: null,
async loadTurnstile() {
// If Turnstile is already present, just resolve.
@@ -2872,7 +2872,7 @@
const shouldRepeat = now - (state._lastChargesNotifyAt || 0) >= repeatMs;
if (shouldEdge || shouldRepeat) {
const msg = Utils.t('chargesReadyMessage', {
- current: Math.floor(state.currentCharges),
+ current: state.currentCharges,
max: state.maxCharges,
threshold: state.cooldownChargeThreshold,
});
@@ -2977,7 +2977,9 @@
// 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 = `
${Utils.t('uploadImageFirst')}
`;
+ colorsContainer.innerHTML = `${Utils.t(
+ 'uploadImageFirst'
+ )}
`;
return;
}
@@ -3349,7 +3351,9 @@
🖼️ Image Management
-
-
+
${Utils.t('loadData')}
@@ -3421,7 +3427,9 @@
${Utils.t('saveToFile')}
-
+
${Utils.t('loadFromFile')}
@@ -3442,7 +3450,9 @@
${Utils.t('paintingStats')}
@@ -3778,15 +3790,21 @@
@@ -3974,11 +3996,19 @@
${Utils.t('paintTransparentPixels')}
-
+
-
-
${Utils.t('fit')}
-
${Utils.t('hundred')}
+
+
${Utils.t('fit')}
+
${Utils.t('hundred')}
@@ -4897,20 +4927,29 @@
const elapsed = Date.now() - startTime;
const remainingMs = Math.max(0, (max - current) * cooldownMs - elapsed);
- let timeText = Utils.msToTimeText(remainingMs);
+ const timeText = Utils.msToTimeText(remainingMs);
- const chargesGained = Math.ceil(elapsed / cooldownMs);
- const currentCharges = Math.min(current + chargesGained, max);
+ // total charges including elapsed time
+ const chargesGained = elapsed / cooldownMs;
+ const rawCharges = current + chargesGained;
+ const cappedCharges = Math.min(rawCharges, max);
- state.currentCharges = Math.floor(currentCharges);
+ // rounding with 0.95 threshold
+ let displayCharges;
+ const fraction = cappedCharges - Math.floor(cappedCharges);
+ if (fraction >= 0.95) {
+ displayCharges = Math.ceil(cappedCharges);
+ } else {
+ displayCharges = Math.floor(cappedCharges);
+ }
+
+ state.currentCharges = displayCharges;
const chargesEl = document.getElementById('wplace-stat-charges-value');
const secondsInMinute = Math.ceil(remainingMs / 1000) % 60;
if (chargesEl && (secondsInMinute === 0 || secondsInMinute === 30)) {
- chargesEl.innerHTML = `
${Math.floor(
- state.currentCharges
- )} / ${state.maxCharges}`;
+ chargesEl.innerHTML = `
${state.currentCharges} / ${state.maxCharges}`;
}
- if (currentCharges >= max) {
+ if (state.currentCharges >= max) {
fullChargeEl.innerHTML = `
FULL`;
clearInterval(state.fullChargeInterval);
state.fullChargeInterval = null;
@@ -5003,7 +5042,10 @@
colorSwatchesHTML = state.availableColors
.map((color) => {
const rgbString = `rgb(${color.rgb.join(',')})`;
- return `
`;
+ return `
`;
})
.join('');
}
@@ -5021,7 +5063,7 @@
${Utils.t('charges')}
- ${Math.floor(state.currentCharges)} / ${state.maxCharges}
+ ${state.currentCharges} / ${state.maxCharges}
@@ -5036,7 +5078,10 @@
state.colorsChecked
? `
-
${Utils.t('availableColors', { count: state.availableColors.length })}
+
${Utils.t(
+ 'availableColors',
+ { count: state.availableColors.length }
+ )}
${colorSwatchesHTML}
@@ -6483,11 +6528,9 @@
if (state.chargesThresholdInterval) {
clearInterval(state.chargesThresholdInterval);
}
- updateUI('startPaintingMsg', 'success');
return; // Threshold already reached
}
- const current = state.fullChargeData ? state.fullChargeData.current : state.currentCharges;
const timeText = Utils.msToTimeText(remainingMs);
updateUI(
@@ -6495,7 +6538,7 @@
'warning',
{
threshold,
- current: Math.floor(current),
+ current: state.currentCharges,
time: timeText,
},
true
@@ -6671,6 +6714,10 @@
});
state.currentCharges -= batchSize;
updateStats();
+ updateUI('paintingProgress', 'default', {
+ painted: state.paintedPixels,
+ total: state.totalPixels,
+ });
Utils.performSmartSave();
if (CONFIG.PAINTING_SPEED_ENABLED && state.paintingSpeed > 0 && batchSize > 0) {
@@ -6793,6 +6840,7 @@
clearInterval(state.chargesThresholdInterval);
}
updateUI('paintingPaused', 'warning', { x, y });
+ // noinspection UnnecessaryLabelOnBreakStatementJS
break outerLoop;
}
@@ -6848,6 +6896,7 @@
console.error(`❌ Batch failed permanently after retries. Stopping painting.`);
state.stopFlag = true;
updateUI('paintingBatchFailed', 'error');
+ // noinspection UnnecessaryLabelOnBreakStatementJS
break outerLoop;
}
}
@@ -6884,16 +6933,21 @@
continue;
}
console.debug(
- `[COMPARE] Pixel at 📍 (${pixelX}, ${pixelY}) in region (${regionX + adderX}, ${regionY + adderY})\n` +
+ `[COMPARE] Pixel at 📍 (${pixelX}, ${pixelY}) in region (${
+ regionX + adderX
+ }, ${regionY + adderY})\n` +
` ├── Current color: rgb(${er}, ${eg}, ${eb}) (id: ${existingColor.id})\n` +
` ├── Target color: rgb(${targetPixelInfo.r}, ${targetPixelInfo.g}, ${targetPixelInfo.b}) (id: ${targetColorId})\n` +
- ` └── Status: ${isMatch ? '✅ Already painted → SKIP' : '🔴 Needs paint → PAINT'}\n`
+ ` └── Status: ${
+ isMatch ? '✅ Already painted → SKIP' : '🔴 Needs paint → PAINT'
+ }\n`
);
}
} catch (e) {
console.error(`[DEBUG] Error checking existing pixel at (${pixelX}, ${pixelY}):`, e);
updateUI('paintingPixelCheckFailed', 'error', { x: pixelX, y: pixelY });
state.stopFlag = true;
+ // noinspection UnnecessaryLabelOnBreakStatementJS
break outerLoop;
}
@@ -6919,6 +6973,7 @@
console.error(`❌ Batch failed permanently after retries. Stopping painting.`);
state.stopFlag = true;
updateUI('paintingBatchFailed', 'error');
+ // noinspection UnnecessaryLabelOnBreakStatementJS
break outerLoop;
}
@@ -6927,21 +6982,23 @@
while (state.currentCharges < state.cooldownChargeThreshold && !state.stopFlag) {
await updateStats();
+
if (state.currentCharges >= state.cooldownChargeThreshold) {
NotificationManager.maybeNotifyChargesReached(true);
break;
}
- saveBtn.disabled = false;
startChargesThresholdTicker();
-
Utils.performSmartSave();
- await Utils.dynamicSleep(() => getRemainingMsToThreshold(state.cooldownChargeThreshold));
+ await Utils.dynamicSleep(
+ () => getRemainingMsToThreshold(state.cooldownChargeThreshold),
+ 1000
+ );
}
- if (!state.stopFlag) saveBtn.disabled = true;
if (state.stopFlag) {
+ // noinspection UnnecessaryLabelOnBreakStatementJS
break outerLoop;
}
}
@@ -7014,7 +7071,7 @@
}
// Always limit by available charges
- const maxAllowed = Math.floor(state.currentCharges);
+ const maxAllowed = state.currentCharges;
const finalBatchSize = Math.min(targetBatchSize, maxAllowed);
return finalBatchSize;