mirror of
https://github.com/tiennm99/WPlace-AutoBOT.git
synced 2026-10-14 00:16:30 +00:00
🔥NEW UPDATE
✅ Add AutoSave ✅ Add SaveData ✅Add LoadData Join discord https://discord.gg/gkuUzq2vN5
This commit is contained in:
1 parent
6149b834e5
commit
c8d49a49a2
2 files changed
+299
-1
No files matched your search
+261
-1
@@ -56,6 +56,14 @@
|
||||
paintingPaused: "⏸️ Pintura pausada na posição X: {x}, Y: {y}",
|
||||
captchaNeeded:
|
||||
"❗ Token CAPTCHA necessário. Pinte um pixel manualmente para continuar.",
|
||||
saveData: "Salvar Progresso",
|
||||
loadData: "Carregar Progresso",
|
||||
autoSaved: "✅ Progresso salvo automaticamente",
|
||||
dataLoaded: "✅ Progresso carregado com sucesso",
|
||||
noSavedData: "❌ Nenhum progresso salvo encontrado",
|
||||
savedDataFound: "✅ Progresso salvo encontrado! Carregar para continuar?",
|
||||
savedDate: "Salvo em: {date}",
|
||||
clickLoadToContinue: "Clique em 'Carregar Progresso' para continuar.",
|
||||
},
|
||||
en: {
|
||||
title: "WPlace Auto-Image",
|
||||
@@ -93,6 +101,14 @@
|
||||
paintingPaused: "⏸️ Painting paused at position X: {x}, Y: {y}",
|
||||
captchaNeeded:
|
||||
"❗ CAPTCHA token needed. Paint one pixel manually to continue.",
|
||||
saveData: "Save Progress",
|
||||
loadData: "Load Progress",
|
||||
autoSaved: "✅ Progress saved automatically",
|
||||
dataLoaded: "✅ Progress loaded successfully",
|
||||
noSavedData: "❌ No saved progress found",
|
||||
savedDataFound: "✅ Saved progress found! Load to continue?",
|
||||
savedDate: "Saved on: {date}",
|
||||
clickLoadToContinue: "Click 'Load Progress' to continue.",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -224,6 +240,149 @@
|
||||
return result;
|
||||
},
|
||||
|
||||
// Save/Load Progress Functions
|
||||
saveProgress: () => {
|
||||
try {
|
||||
const progressData = {
|
||||
version: "1.0",
|
||||
timestamp: Date.now(),
|
||||
state: {
|
||||
imageLoaded: state.imageLoaded,
|
||||
totalPixels: state.totalPixels,
|
||||
paintedPixels: state.paintedPixels,
|
||||
lastPosition: state.lastPosition,
|
||||
startPosition: state.startPosition,
|
||||
region: state.region,
|
||||
paintedMap: state.paintedMap,
|
||||
imageData: state.imageData,
|
||||
availableColors: state.availableColors,
|
||||
colorsChecked: state.colorsChecked,
|
||||
language: state.language
|
||||
}
|
||||
};
|
||||
|
||||
localStorage.setItem('wplace-auto-image-progress', JSON.stringify(progressData));
|
||||
console.log('✅ Progress saved successfully');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ Error saving progress:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
loadProgress: () => {
|
||||
try {
|
||||
const savedData = localStorage.getItem('wplace-auto-image-progress');
|
||||
if (!savedData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const progressData = JSON.parse(savedData);
|
||||
|
||||
// Validate data structure
|
||||
if (!progressData.version || !progressData.state) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return progressData;
|
||||
} catch (error) {
|
||||
console.error('❌ Error loading progress:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
restoreProgress: (progressData) => {
|
||||
try {
|
||||
const savedState = progressData.state;
|
||||
|
||||
// Restore state
|
||||
state.imageLoaded = savedState.imageLoaded;
|
||||
state.totalPixels = savedState.totalPixels;
|
||||
state.paintedPixels = savedState.paintedPixels;
|
||||
state.lastPosition = savedState.lastPosition || { x: 0, y: 0 };
|
||||
state.startPosition = savedState.startPosition;
|
||||
state.region = savedState.region;
|
||||
state.paintedMap = savedState.paintedMap;
|
||||
state.imageData = savedState.imageData;
|
||||
state.availableColors = savedState.availableColors;
|
||||
state.language = savedState.language;
|
||||
state.colorsChecked = savedState.availableColors && savedState.availableColors.length > 0;
|
||||
|
||||
// Update UI to reflect restored state
|
||||
if (state.imageLoaded) {
|
||||
const initBotBtn = document.querySelector("#initBotBtn");
|
||||
const uploadBtn = document.querySelector("#uploadBtn");
|
||||
const resizeBtn = document.querySelector("#resizeBtn");
|
||||
const selectPosBtn = document.querySelector("#selectPosBtn");
|
||||
const startBtn = document.querySelector("#startBtn");
|
||||
const saveBtn = document.querySelector("#saveBtn");
|
||||
const progressBar = document.querySelector("#progressBar");
|
||||
|
||||
// Show/hide appropriate buttons based on state
|
||||
if (state.colorsChecked) {
|
||||
initBotBtn.style.display = "none";
|
||||
uploadBtn.disabled = false;
|
||||
selectPosBtn.disabled = false;
|
||||
} else {
|
||||
initBotBtn.style.display = "block";
|
||||
uploadBtn.disabled = true;
|
||||
selectPosBtn.disabled = true;
|
||||
}
|
||||
|
||||
resizeBtn.disabled = false;
|
||||
saveBtn.disabled = false;
|
||||
|
||||
if (state.startPosition && state.region) {
|
||||
selectPosBtn.disabled = false;
|
||||
startBtn.disabled = false;
|
||||
}
|
||||
|
||||
// Update progress bar
|
||||
const progress = state.totalPixels > 0 ? Math.round((state.paintedPixels / state.totalPixels) * 100) : 0;
|
||||
progressBar.style.width = `${progress}%`;
|
||||
|
||||
// Update status message based on progress
|
||||
if (state.paintedPixels > 0) {
|
||||
if (state.lastPosition.x > 0 || state.lastPosition.y > 0) {
|
||||
updateUI("paintingPaused", "warning", {
|
||||
x: state.lastPosition.x,
|
||||
y: state.lastPosition.y
|
||||
});
|
||||
} else {
|
||||
updateUI("paintingProgress", "default", {
|
||||
painted: state.paintedPixels,
|
||||
total: state.totalPixels,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
updateUI("imageLoaded", "success", { count: state.totalPixels });
|
||||
}
|
||||
}
|
||||
|
||||
// Update stats to show current progress
|
||||
updateStats();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ Error restoring progress:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
clearProgress: () => {
|
||||
try {
|
||||
localStorage.removeItem('wplace-auto-image-progress');
|
||||
console.log('✅ Progress data cleared');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ Error clearing progress:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
hasSavedProgress: () => {
|
||||
return localStorage.getItem('wplace-auto-image-progress') !== null;
|
||||
},
|
||||
|
||||
showAlert: (message, type = "info") => {
|
||||
const alert = document.createElement("div");
|
||||
alert.style.position = "fixed";
|
||||
@@ -686,6 +845,14 @@
|
||||
<i class="fas fa-stop"></i>
|
||||
<span>${Utils.t("stopPainting")}</span>
|
||||
</button>
|
||||
<button id="saveBtn" class="wplace-btn wplace-btn-primary" disabled>
|
||||
<i class="fas fa-save"></i>
|
||||
<span>${Utils.t("saveData")}</span>
|
||||
</button>
|
||||
<button id="loadBtn" class="wplace-btn wplace-btn-primary">
|
||||
<i class="fas fa-folder-open"></i>
|
||||
<span>${Utils.t("loadData")}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="wplace-progress">
|
||||
@@ -787,6 +954,8 @@
|
||||
const selectPosBtn = container.querySelector("#selectPosBtn");
|
||||
const startBtn = container.querySelector("#startBtn");
|
||||
const stopBtn = container.querySelector("#stopBtn");
|
||||
const saveBtn = container.querySelector("#saveBtn");
|
||||
const loadBtn = container.querySelector("#loadBtn");
|
||||
const minimizeBtn = container.querySelector("#minimizeBtn");
|
||||
const statusText = container.querySelector("#statusText");
|
||||
const progressBar = container.querySelector("#progressBar");
|
||||
@@ -1031,6 +1200,7 @@
|
||||
state.lastPosition = { x: 0, y: 0 };
|
||||
|
||||
resizeBtn.disabled = false;
|
||||
saveBtn.disabled = false;
|
||||
|
||||
if (state.startPosition) {
|
||||
startBtn.disabled = false;
|
||||
@@ -1136,6 +1306,7 @@
|
||||
uploadBtn.disabled = true;
|
||||
selectPosBtn.disabled = true;
|
||||
resizeBtn.disabled = true;
|
||||
saveBtn.disabled = true;
|
||||
|
||||
updateUI("startPaintingMsg", "success");
|
||||
|
||||
@@ -1146,6 +1317,7 @@
|
||||
} finally {
|
||||
state.running = false;
|
||||
stopBtn.disabled = true;
|
||||
saveBtn.disabled = false;
|
||||
|
||||
if (!state.stopFlag) {
|
||||
startBtn.disabled = true;
|
||||
@@ -1163,7 +1335,86 @@
|
||||
state.running = false;
|
||||
stopBtn.disabled = true;
|
||||
updateUI("paintingStopped", "warning");
|
||||
|
||||
// Auto save when stopping
|
||||
if (state.imageLoaded && state.paintedPixels > 0) {
|
||||
Utils.saveProgress();
|
||||
Utils.showAlert(Utils.t("autoSaved"), "success");
|
||||
}
|
||||
});
|
||||
|
||||
saveBtn.addEventListener("click", () => {
|
||||
if (!state.imageLoaded) {
|
||||
Utils.showAlert(Utils.t("missingRequirements"), "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const success = Utils.saveProgress();
|
||||
if (success) {
|
||||
updateUI("autoSaved", "success");
|
||||
Utils.showAlert(Utils.t("autoSaved"), "success");
|
||||
} else {
|
||||
Utils.showAlert("❌ Erro ao salvar progresso", "error");
|
||||
}
|
||||
});
|
||||
|
||||
loadBtn.addEventListener("click", () => {
|
||||
const savedData = Utils.loadProgress();
|
||||
if (!savedData) {
|
||||
updateUI("noSavedData", "warning");
|
||||
Utils.showAlert(Utils.t("noSavedData"), "warning");
|
||||
return;
|
||||
}
|
||||
|
||||
// Show confirmation dialog
|
||||
const confirmLoad = confirm(
|
||||
`${Utils.t("savedDataFound")}\n\n` +
|
||||
`Saved: ${new Date(savedData.timestamp).toLocaleString()}\n` +
|
||||
`Progress: ${savedData.state.paintedPixels}/${savedData.state.totalPixels} pixels`
|
||||
);
|
||||
|
||||
if (confirmLoad) {
|
||||
const success = Utils.restoreProgress(savedData);
|
||||
if (success) {
|
||||
updateUI("dataLoaded", "success");
|
||||
Utils.showAlert(Utils.t("dataLoaded"), "success");
|
||||
|
||||
// Enable appropriate buttons
|
||||
saveBtn.disabled = false;
|
||||
|
||||
// Show init button if colors not checked yet
|
||||
if (!state.colorsChecked) {
|
||||
initBotBtn.style.display = "block";
|
||||
}
|
||||
|
||||
if (state.imageLoaded && state.startPosition && state.region && state.colorsChecked) {
|
||||
startBtn.disabled = false;
|
||||
}
|
||||
} else {
|
||||
Utils.showAlert("❌ Erro ao carregar progresso", "error");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Check for saved progress on startup
|
||||
const checkSavedProgress = () => {
|
||||
const savedData = Utils.loadProgress();
|
||||
if (savedData && savedData.state.paintedPixels > 0) {
|
||||
const savedDate = new Date(savedData.timestamp).toLocaleString();
|
||||
const progress = Math.round((savedData.state.paintedPixels / savedData.state.totalPixels) * 100);
|
||||
|
||||
Utils.showAlert(
|
||||
`${Utils.t("savedDataFound")}\n\n` +
|
||||
`Saved: ${savedDate}\n` +
|
||||
`Progress: ${savedData.state.paintedPixels}/${savedData.state.totalPixels} pixels (${progress}%)\n` +
|
||||
`${Utils.t("clickLoadToContinue")}`,
|
||||
"info"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Check for saved progress after a short delay to let UI settle
|
||||
setTimeout(checkSavedProgress, 1000);
|
||||
}
|
||||
|
||||
async function processImage() {
|
||||
@@ -1240,6 +1491,11 @@
|
||||
painted: state.paintedPixels,
|
||||
total: state.totalPixels,
|
||||
});
|
||||
|
||||
// Auto-save progress every 50 pixels
|
||||
if (state.paintedPixels % 50 === 0) {
|
||||
Utils.saveProgress();
|
||||
}
|
||||
}
|
||||
|
||||
pixelBatch = [];
|
||||
@@ -1275,10 +1531,14 @@
|
||||
|
||||
if (state.stopFlag) {
|
||||
updateUI("paintingStopped", "warning");
|
||||
// Save progress when stopped
|
||||
Utils.saveProgress();
|
||||
} else {
|
||||
updateUI("paintingComplete", "success", { count: state.paintedPixels });
|
||||
state.lastPosition = { x: 0, y: 0 };
|
||||
state.paintedMap = null;
|
||||
// Clear saved data when completed
|
||||
Utils.clearProgress();
|
||||
}
|
||||
|
||||
updateStats();
|
||||
@@ -1331,4 +1591,4 @@
|
||||
}
|
||||
|
||||
createUI();
|
||||
})();
|
||||
})();
|
||||
@@ -0,0 +1,38 @@
|
||||
# Test Save/Load Progress Feature
|
||||
|
||||
## Các tính năng đã thêm:
|
||||
|
||||
### Auto-Image.js:
|
||||
1. **Save Progress** - Nút lưu tiến độ thủ công
|
||||
2. **Load Progress** - Nút khôi phục tiến độ
|
||||
3. **Auto Save** - Tự động lưu mỗi 50 pixels và khi dừng
|
||||
4. **Smart UI Restore** - Khôi phục UI đúng trạng thái trước khi dừng
|
||||
5. **Progress Notification** - Thông báo khi khởi động nếu có progress đã lưu
|
||||
|
||||
### Cách sử dụng:
|
||||
|
||||
1. **Upload ảnh và chọn vị trí** như bình thường
|
||||
2. **Bắt đầu painting** - script sẽ tự động lưu tiến độ
|
||||
3. **Dừng script** khi cần - tiến độ sẽ được lưu tự động
|
||||
4. **Khởi động lại script** - sẽ có thông báo nếu có tiến độ đã lưu
|
||||
5. **Click "Load Progress"** để tiếp tục từ vị trí đã dừng
|
||||
6. **UI sẽ hiển thị** đúng trạng thái như trước khi dừng (progress bar, pixels painted, vị trí, etc.)
|
||||
|
||||
### Dữ liệu được lưu:
|
||||
- Thông tin ảnh và pixels
|
||||
- Vị trí hiện tại trong painting
|
||||
- Số pixels đã paint
|
||||
- Map các pixels đã paint (để tránh paint lại)
|
||||
- Vị trí bắt đầu và region
|
||||
- Màu sắc available
|
||||
- Ngôn ngữ đã chọn
|
||||
|
||||
### Auto Save:
|
||||
- Mỗi 50 pixels được paint
|
||||
- Khi user dừng script (Stop button)
|
||||
- Clear progress khi hoàn thành painting
|
||||
|
||||
### Thông báo:
|
||||
- Tiếng Việt và English support
|
||||
- Hiển thị thời gian lưu và tiến độ
|
||||
- Xác nhận trước khi load
|
||||
Reference in new issue
Block a user