mirror of
https://github.com/amiayweb/Hytale-F2P.git
synced 2026-02-26 13:51:46 -03:00
fix: comprehensive UUID/username persistence bug fixes (#252)
* fix: comprehensive UUID/username persistence bug fixes Major fixes for UUID/skin reset issues that caused players to lose cosmetics: Core fixes: - Username rename now preserves UUID (atomic rename, not new identity) - Atomic config writes with backup/recovery system - Case-insensitive UUID lookup with case-preserving storage - Pre-launch validation blocks play if no username configured - Removed saveUsername calls from launch/install flows UUID Modal fixes: - Fixed isCurrent badge showing on wrong user - Added switch identity button to change between saved usernames - Fixed custom UUID input using unsaved DOM username - UUID list now refreshes when player name changes - Enabled copy/paste in custom UUID input field UI/UX improvements: - Added translation keys for switch username functionality - CSS user-select fix for UUID input fields - Allowed Ctrl+V/C/X/A shortcuts in Electron Files: config.js, gameLauncher.js, gameManager.js, playerManager.js, launcher.js, settings.js, main.js, preload.js, style.css, en.json See UUID_BUGS_FIX_PLAN.md for detailed bug list (18 bugs, 16 fixed) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(i18n): add switch username translations to all locales Added translation keys for username switching functionality: - notifications.noUsername - notifications.switchUsernameSuccess - notifications.switchUsernameFailed - notifications.playerNameTooLong - confirm.switchUsernameTitle - confirm.switchUsernameMessage - confirm.switchUsernameButton Languages updated: de-DE, es-ES, fr-FR, id-ID, pl-PL, pt-BR, ru-RU, sv-SE, tr-TR Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: move UUID_BUGS_FIX_PLAN.md to docs folder * docs: update UUID_BUGS_FIX_PLAN with complete fix details --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,32 +3,117 @@ const path = require('path');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { PLAYER_ID_FILE, APP_DIR } = require('../core/paths');
|
||||
|
||||
function getOrCreatePlayerId() {
|
||||
try {
|
||||
if (!fs.existsSync(APP_DIR)) {
|
||||
fs.mkdirSync(APP_DIR, { recursive: true });
|
||||
}
|
||||
/**
|
||||
* DEPRECATED: This file is kept for backward compatibility.
|
||||
*
|
||||
* The primary UUID system is now in config.js using userUuids.
|
||||
* This player_id.json system was a separate UUID storage that could
|
||||
* cause desync issues.
|
||||
*
|
||||
* New code should use config.js functions:
|
||||
* - getUuidForUser(username) - Get/create UUID for a username
|
||||
* - getCurrentUuid() - Get current user's UUID
|
||||
* - setUuidForUser(username, uuid) - Set UUID for a user
|
||||
*
|
||||
* This function is kept for migration purposes only.
|
||||
*/
|
||||
|
||||
if (fs.existsSync(PLAYER_ID_FILE)) {
|
||||
const data = JSON.parse(fs.readFileSync(PLAYER_ID_FILE, 'utf8'));
|
||||
if (data.playerId) {
|
||||
return data.playerId;
|
||||
/**
|
||||
* Get or create a legacy player ID
|
||||
* NOTE: This is DEPRECATED - use config.js getUuidForUser() instead
|
||||
*
|
||||
* FIXED: No longer returns random UUID on error - throws instead
|
||||
*/
|
||||
function getOrCreatePlayerId() {
|
||||
const maxRetries = 3;
|
||||
let lastError;
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
if (!fs.existsSync(APP_DIR)) {
|
||||
fs.mkdirSync(APP_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
if (fs.existsSync(PLAYER_ID_FILE)) {
|
||||
const data = fs.readFileSync(PLAYER_ID_FILE, 'utf8');
|
||||
if (data.trim()) {
|
||||
const parsed = JSON.parse(data);
|
||||
if (parsed.playerId) {
|
||||
return parsed.playerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No existing ID - create new one atomically
|
||||
const newPlayerId = uuidv4();
|
||||
const tempFile = PLAYER_ID_FILE + '.tmp';
|
||||
const playerData = {
|
||||
playerId: newPlayerId,
|
||||
createdAt: new Date().toISOString(),
|
||||
note: 'DEPRECATED: This file is for legacy compatibility. UUID is now stored in config.json userUuids.'
|
||||
};
|
||||
|
||||
// Write to temp file first
|
||||
fs.writeFileSync(tempFile, JSON.stringify(playerData, null, 2));
|
||||
|
||||
// Atomic rename
|
||||
fs.renameSync(tempFile, PLAYER_ID_FILE);
|
||||
|
||||
console.log(`[PlayerManager] Created new legacy player ID: ${newPlayerId}`);
|
||||
return newPlayerId;
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
console.error(`[PlayerManager] Attempt ${attempt}/${maxRetries} failed:`, error.message);
|
||||
|
||||
if (attempt < maxRetries) {
|
||||
// Small delay before retry
|
||||
const delay = attempt * 100;
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < delay) {
|
||||
// Busy wait
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newPlayerId = uuidv4();
|
||||
fs.writeFileSync(PLAYER_ID_FILE, JSON.stringify({
|
||||
playerId: newPlayerId,
|
||||
createdAt: new Date().toISOString()
|
||||
}, null, 2));
|
||||
// FIXED: Do NOT return random UUID - throw error instead
|
||||
// Returning random UUID was causing silent identity loss
|
||||
console.error('[PlayerManager] CRITICAL: Failed to get/create player ID after all retries');
|
||||
throw new Error(`Failed to manage player ID: ${lastError.message}`);
|
||||
}
|
||||
|
||||
return newPlayerId;
|
||||
/**
|
||||
* Migrate legacy player_id.json to config.json userUuids
|
||||
* Call this during app startup
|
||||
*/
|
||||
function migrateLegacyPlayerId() {
|
||||
try {
|
||||
if (!fs.existsSync(PLAYER_ID_FILE)) {
|
||||
return null; // No legacy file to migrate
|
||||
}
|
||||
|
||||
const data = JSON.parse(fs.readFileSync(PLAYER_ID_FILE, 'utf8'));
|
||||
if (!data.playerId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(`[PlayerManager] Found legacy player_id.json with ID: ${data.playerId}`);
|
||||
|
||||
// Mark file as migrated by renaming
|
||||
const migratedFile = PLAYER_ID_FILE + '.migrated';
|
||||
if (!fs.existsSync(migratedFile)) {
|
||||
fs.renameSync(PLAYER_ID_FILE, migratedFile);
|
||||
console.log('[PlayerManager] Legacy player_id.json marked as migrated');
|
||||
}
|
||||
|
||||
return data.playerId;
|
||||
} catch (error) {
|
||||
console.error('Error managing player ID:', error);
|
||||
return uuidv4();
|
||||
console.error('[PlayerManager] Error during legacy migration:', error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getOrCreatePlayerId
|
||||
getOrCreatePlayerId,
|
||||
migrateLegacyPlayerId
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user