mirror of
https://git.sanhost.net/sanasol/hytale-f2p
synced 2026-02-26 10:31:47 -03:00
* 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>
120 lines
3.5 KiB
JavaScript
120 lines
3.5 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const { v4: uuidv4 } = require('uuid');
|
|
const { PLAYER_ID_FILE, APP_DIR } = require('../core/paths');
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
|
|
/**
|
|
* 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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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}`);
|
|
}
|
|
|
|
/**
|
|
* 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('[PlayerManager] Error during legacy migration:', error.message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getOrCreatePlayerId,
|
|
migrateLegacyPlayerId
|
|
};
|