mirror of
https://github.com/amiayweb/Hytale-F2P.git
synced 2026-02-26 10:11:47 -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:
@@ -194,27 +194,81 @@ window.switchProfile = async (id) => {
|
||||
export async function launch() {
|
||||
if (isDownloading || (playBtn && playBtn.disabled)) return;
|
||||
|
||||
let playerName = 'Player';
|
||||
if (window.SettingsAPI && window.SettingsAPI.getCurrentPlayerName) {
|
||||
playerName = window.SettingsAPI.getCurrentPlayerName();
|
||||
} else if (playerNameInput && playerNameInput.value.trim()) {
|
||||
playerName = playerNameInput.value.trim();
|
||||
// ==========================================================================
|
||||
// STEP 1: Check launch readiness from backend (single source of truth)
|
||||
// ==========================================================================
|
||||
let launchState = null;
|
||||
let playerName = null;
|
||||
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.checkLaunchReady) {
|
||||
launchState = await window.electronAPI.checkLaunchReady();
|
||||
playerName = launchState?.username;
|
||||
} else if (window.electronAPI && window.electronAPI.loadUsername) {
|
||||
// Fallback to loadUsername if checkLaunchReady not available
|
||||
playerName = await window.electronAPI.loadUsername();
|
||||
launchState = { ready: !!playerName, hasUsername: !!playerName, username: playerName, issues: [] };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Launcher] Error checking launch readiness:', error);
|
||||
}
|
||||
|
||||
let javaPath = '';
|
||||
if (window.SettingsAPI && window.SettingsAPI.getCurrentJavaPath) {
|
||||
javaPath = window.SettingsAPI.getCurrentJavaPath();
|
||||
// Validate launch readiness
|
||||
if (!launchState?.ready || !playerName) {
|
||||
const issues = launchState?.issues || ['No username configured'];
|
||||
const errorMsg = window.i18n
|
||||
? window.i18n.t('errors.noUsername')
|
||||
: 'Please set your username in Settings before playing.';
|
||||
|
||||
console.error('[Launcher] Launch blocked:', issues.join(', '));
|
||||
|
||||
// Show error to user
|
||||
if (window.LauncherUI && window.LauncherUI.showError) {
|
||||
window.LauncherUI.showError(errorMsg);
|
||||
} else {
|
||||
alert(errorMsg);
|
||||
}
|
||||
|
||||
// Navigate to settings if possible
|
||||
if (window.LauncherUI && window.LauncherUI.showPage) {
|
||||
window.LauncherUI.showPage('settings-page');
|
||||
window.LauncherUI.setActiveNav('settings');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Warn if using default 'Player' name (shouldn't happen with new logic, but keep as safety)
|
||||
if (playerName === 'Player') {
|
||||
console.warn('[Launcher] Warning: Using default username "Player"');
|
||||
}
|
||||
|
||||
console.log(`[Launcher] Launching game for: "${playerName}"`);
|
||||
|
||||
// ==========================================================================
|
||||
// STEP 2: Load other settings from backend
|
||||
// ==========================================================================
|
||||
let javaPath = '';
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.loadJavaPath) {
|
||||
javaPath = await window.electronAPI.loadJavaPath() || '';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Launcher] Error loading Java path:', error);
|
||||
}
|
||||
|
||||
let gpuPreference = 'auto';
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.loadGpuPreference) {
|
||||
gpuPreference = await window.electronAPI.loadGpuPreference();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading GPU preference:', error);
|
||||
console.error('[Launcher] Error loading GPU preference:', error);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// STEP 3: Start launch process
|
||||
// ==========================================================================
|
||||
if (window.LauncherUI) window.LauncherUI.showProgress();
|
||||
isDownloading = true;
|
||||
if (playBtn) {
|
||||
@@ -227,8 +281,9 @@ export async function launch() {
|
||||
if (window.LauncherUI) window.LauncherUI.updateProgress({ message: startingMsg });
|
||||
|
||||
if (window.electronAPI && window.electronAPI.launchGame) {
|
||||
// Pass playerName from config - backend will validate again
|
||||
const result = await window.electronAPI.launchGame(playerName, javaPath, '', gpuPreference);
|
||||
|
||||
|
||||
isDownloading = false;
|
||||
|
||||
if (window.LauncherUI) {
|
||||
@@ -243,7 +298,35 @@ export async function launch() {
|
||||
}, 500);
|
||||
}
|
||||
} else {
|
||||
console.error('Launch failed:', result.error);
|
||||
console.error('[Launcher] Launch failed:', result.error);
|
||||
|
||||
// Handle specific error cases
|
||||
if (result.needsUsername) {
|
||||
const errorMsg = window.i18n
|
||||
? window.i18n.t('errors.noUsername')
|
||||
: 'Please set your username in Settings before playing.';
|
||||
|
||||
if (window.LauncherUI && window.LauncherUI.showError) {
|
||||
window.LauncherUI.showError(errorMsg);
|
||||
} else {
|
||||
alert(errorMsg);
|
||||
}
|
||||
|
||||
// Navigate to settings
|
||||
if (window.LauncherUI && window.LauncherUI.showPage) {
|
||||
window.LauncherUI.showPage('settings-page');
|
||||
window.LauncherUI.setActiveNav('settings');
|
||||
}
|
||||
} else if (result.error) {
|
||||
// Show generic error
|
||||
const errorMsg = window.i18n
|
||||
? window.i18n.t('errors.launchFailed').replace('{error}', result.error)
|
||||
: `Launch failed: ${result.error}`;
|
||||
|
||||
if (window.LauncherUI && window.LauncherUI.showError) {
|
||||
window.LauncherUI.showError(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isDownloading = false;
|
||||
@@ -260,7 +343,13 @@ export async function launch() {
|
||||
window.LauncherUI.hideProgress();
|
||||
}
|
||||
resetPlayButton();
|
||||
console.error('Launch error:', error);
|
||||
console.error('[Launcher] Launch error:', error);
|
||||
|
||||
// Show error to user
|
||||
const errorMsg = error.message || 'Unknown launch error';
|
||||
if (window.LauncherUI && window.LauncherUI.showError) {
|
||||
window.LauncherUI.showError(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -446,10 +446,27 @@ async function savePlayerName() {
|
||||
return;
|
||||
}
|
||||
|
||||
await window.electronAPI.saveUsername(playerName);
|
||||
const result = await window.electronAPI.saveUsername(playerName);
|
||||
|
||||
// Check if save was successful
|
||||
if (result && result.success === false) {
|
||||
console.error('[Settings] Failed to save username:', result.error);
|
||||
const errorMsg = window.i18n
|
||||
? window.i18n.t('notifications.playerNameSaveFailed')
|
||||
: `Failed to save player name: ${result.error || 'Unknown error'}`;
|
||||
showNotification(errorMsg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const successMsg = window.i18n ? window.i18n.t('notifications.playerNameSaved') : 'Player name saved successfully';
|
||||
showNotification(successMsg, 'success');
|
||||
|
||||
// Refresh UUID display since it may have changed for the new username
|
||||
await loadCurrentUuid();
|
||||
|
||||
// Also refresh the UUID list to update which entry is marked as current
|
||||
await loadAllUuids();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error saving player name:', error);
|
||||
const errorMsg = window.i18n ? window.i18n.t('notifications.playerNameSaveFailed') : 'Failed to save player name';
|
||||
@@ -573,11 +590,26 @@ export function getCurrentJavaPath() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get current player name from UI input
|
||||
* Returns null if no name is set (caller must handle this)
|
||||
* NOTE: launcher.js now loads username directly from backend config
|
||||
* This function is used for display purposes only
|
||||
*/
|
||||
export function getCurrentPlayerName() {
|
||||
if (settingsPlayerName && settingsPlayerName.value.trim()) {
|
||||
return settingsPlayerName.value.trim();
|
||||
}
|
||||
return 'Player';
|
||||
// Return null instead of 'Player' - caller must handle missing username
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current player name with fallback for display purposes only
|
||||
* DO NOT use this for launching game - use backend loadUsername() instead
|
||||
*/
|
||||
export function getCurrentPlayerNameForDisplay() {
|
||||
return getCurrentPlayerName() || 'Player';
|
||||
}
|
||||
|
||||
window.openGameLocation = openGameLocation;
|
||||
@@ -587,6 +619,7 @@ document.addEventListener('DOMContentLoaded', initSettings);
|
||||
window.SettingsAPI = {
|
||||
getCurrentJavaPath,
|
||||
getCurrentPlayerName,
|
||||
getCurrentPlayerNameForDisplay,
|
||||
reloadBranch: loadVersionBranch
|
||||
};
|
||||
|
||||
@@ -729,6 +762,9 @@ async function loadAllUuids() {
|
||||
</div>
|
||||
<div class="uuid-item-actions">
|
||||
${mapping.isCurrent ? '<div class="uuid-item-current-badge">Current</div>' : ''}
|
||||
${!mapping.isCurrent ? `<button class="uuid-item-btn switch" onclick="switchToUsername('${escapeHtml(mapping.username)}')" title="Switch to this identity">
|
||||
<i class="fas fa-user-check"></i>
|
||||
</button>` : ''}
|
||||
<button class="uuid-item-btn copy" onclick="copyUuid('${mapping.uuid}')" title="Copy UUID">
|
||||
<i class="fas fa-copy"></i>
|
||||
</button>
|
||||
@@ -813,7 +849,17 @@ async function setCustomUuid() {
|
||||
async function performSetCustomUuid(uuid) {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.setUuidForUser) {
|
||||
const username = getCurrentPlayerName();
|
||||
// IMPORTANT: Use saved username from config, not unsaved DOM input
|
||||
// This prevents setting UUID for wrong user if username field was edited but not saved
|
||||
let username = null;
|
||||
if (window.electronAPI.loadUsername) {
|
||||
username = await window.electronAPI.loadUsername();
|
||||
}
|
||||
if (!username) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.noUsername') : 'No username configured. Please save your username first.';
|
||||
showNotification(msg, 'error');
|
||||
return;
|
||||
}
|
||||
const result = await window.electronAPI.setUuidForUser(username, uuid);
|
||||
|
||||
if (result.success) {
|
||||
@@ -850,6 +896,73 @@ window.copyUuid = async function (uuid) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch to a different username/UUID identity
|
||||
* This changes the active username to use that username's UUID
|
||||
*/
|
||||
window.switchToUsername = async function (username) {
|
||||
try {
|
||||
const message = window.i18n
|
||||
? window.i18n.t('confirm.switchUsernameMessage').replace('{username}', username)
|
||||
: `Switch to username "${username}"? This will change your active player identity.`;
|
||||
const title = window.i18n ? window.i18n.t('confirm.switchUsernameTitle') : 'Switch Identity';
|
||||
const confirmBtn = window.i18n ? window.i18n.t('confirm.switchUsernameButton') : 'Switch';
|
||||
const cancelBtn = window.i18n ? window.i18n.t('common.cancel') : 'Cancel';
|
||||
|
||||
showCustomConfirm(
|
||||
message,
|
||||
title,
|
||||
async () => {
|
||||
await performSwitchToUsername(username);
|
||||
},
|
||||
null,
|
||||
confirmBtn,
|
||||
cancelBtn
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in switchToUsername:', error);
|
||||
const msg = window.i18n ? window.i18n.t('notifications.switchUsernameFailed') : 'Failed to switch username';
|
||||
showNotification(msg, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
async function performSwitchToUsername(username) {
|
||||
try {
|
||||
if (!window.electronAPI || !window.electronAPI.saveUsername) {
|
||||
throw new Error('API not available');
|
||||
}
|
||||
|
||||
const result = await window.electronAPI.saveUsername(username);
|
||||
|
||||
if (result && result.success === false) {
|
||||
throw new Error(result.error || 'Failed to save username');
|
||||
}
|
||||
|
||||
// Update the username input field
|
||||
if (settingsPlayerName) {
|
||||
settingsPlayerName.value = username;
|
||||
}
|
||||
|
||||
// Refresh the current UUID display
|
||||
await loadCurrentUuid();
|
||||
|
||||
// Refresh the UUID list to show new "Current" badge
|
||||
await loadAllUuids();
|
||||
|
||||
const msg = window.i18n
|
||||
? window.i18n.t('notifications.switchUsernameSuccess').replace('{username}', username)
|
||||
: `Switched to "${username}" successfully!`;
|
||||
showNotification(msg, 'success');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error switching username:', error);
|
||||
const msg = window.i18n
|
||||
? window.i18n.t('notifications.switchUsernameFailed')
|
||||
: `Failed to switch username: ${error.message}`;
|
||||
showNotification(msg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
window.deleteUuid = async function (username) {
|
||||
try {
|
||||
const message = window.i18n ? window.i18n.t('confirm.deleteUuidMessage').replace('{username}', username) : `Are you sure you want to delete the UUID for "${username}"? This action cannot be undone.`;
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Mod konnte nicht gelöscht werden: {error}",
|
||||
"modsModNotFound": "Mod-Informationen nicht gefunden",
|
||||
"hwAccelSaved": "Hardware-Beschleunigungseinstellung gespeichert",
|
||||
"hwAccelSaveFailed": "Hardware-Beschleunigungseinstellung konnte nicht gespeichert werden"
|
||||
"hwAccelSaveFailed": "Hardware-Beschleunigungseinstellung konnte nicht gespeichert werden",
|
||||
"noUsername": "Kein Benutzername konfiguriert. Bitte speichere zuerst deinen Benutzernamen.",
|
||||
"switchUsernameSuccess": "Erfolgreich zu \"{username}\" gewechselt!",
|
||||
"switchUsernameFailed": "Benutzername konnte nicht gewechselt werden",
|
||||
"playerNameTooLong": "Spielername darf maximal 16 Zeichen haben"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Aktion bestätigen",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Löschen",
|
||||
"uninstallGameTitle": "Spiel deinstallieren",
|
||||
"uninstallGameMessage": "Möchtest du Hytale wirklich deinstallieren? Alle Spieldateien werden gelöscht.",
|
||||
"uninstallGameButton": "Deinstallieren"
|
||||
"uninstallGameButton": "Deinstallieren",
|
||||
"switchUsernameTitle": "Identität wechseln",
|
||||
"switchUsernameMessage": "Zu Benutzername \"{username}\" wechseln? Dies ändert deine aktuelle Spieleridentität.",
|
||||
"switchUsernameButton": "Wechseln"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Initialisiere...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Failed to delete mod: {error}",
|
||||
"modsModNotFound": "Mod information not found",
|
||||
"hwAccelSaved": "Hardware acceleration setting saved",
|
||||
"hwAccelSaveFailed": "Failed to save hardware acceleration setting"
|
||||
"hwAccelSaveFailed": "Failed to save hardware acceleration setting",
|
||||
"noUsername": "No username configured. Please save your username first.",
|
||||
"switchUsernameSuccess": "Switched to \"{username}\" successfully!",
|
||||
"switchUsernameFailed": "Failed to switch username",
|
||||
"playerNameTooLong": "Player name must be 16 characters or less"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Confirm action",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Delete",
|
||||
"uninstallGameTitle": "Uninstall game",
|
||||
"uninstallGameMessage": "Are you sure you want to uninstall Hytale? All game files will be deleted.",
|
||||
"uninstallGameButton": "Uninstall"
|
||||
"uninstallGameButton": "Uninstall",
|
||||
"switchUsernameTitle": "Switch Identity",
|
||||
"switchUsernameMessage": "Switch to username \"{username}\"? This will change your current player identity.",
|
||||
"switchUsernameButton": "Switch"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Initializing...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Error al eliminar mod: {error}",
|
||||
"modsModNotFound": "Información del mod no encontrada",
|
||||
"hwAccelSaved": "Configuración de aceleración por hardware guardada",
|
||||
"hwAccelSaveFailed": "Error al guardar la configuración de aceleración por hardware"
|
||||
"hwAccelSaveFailed": "Error al guardar la configuración de aceleración por hardware",
|
||||
"noUsername": "No hay nombre de usuario configurado. Por favor, guarda tu nombre de usuario primero.",
|
||||
"switchUsernameSuccess": "¡Cambiado a \"{username}\" con éxito!",
|
||||
"switchUsernameFailed": "Error al cambiar nombre de usuario",
|
||||
"playerNameTooLong": "El nombre del jugador debe tener 16 caracteres o menos"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Confirmar acción",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Eliminar",
|
||||
"uninstallGameTitle": "Desinstalar juego",
|
||||
"uninstallGameMessage": "¿Estás seguro de que quieres desinstalar Hytale? Se eliminarán todos los archivos del juego.",
|
||||
"uninstallGameButton": "Desinstalar"
|
||||
"uninstallGameButton": "Desinstalar",
|
||||
"switchUsernameTitle": "Cambiar identidad",
|
||||
"switchUsernameMessage": "¿Cambiar al nombre de usuario \"{username}\"? Esto cambiará tu identidad de jugador actual.",
|
||||
"switchUsernameButton": "Cambiar"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Inicializando...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Échec de la suppression du mod: {error}",
|
||||
"modsModNotFound": "Informations du mod introuvables",
|
||||
"hwAccelSaved": "Paramètre d'accélération matérielle sauvegardé",
|
||||
"hwAccelSaveFailed": "Échec de la sauvegarde du paramètre d'accélération matérielle"
|
||||
"hwAccelSaveFailed": "Échec de la sauvegarde du paramètre d'accélération matérielle",
|
||||
"noUsername": "Aucun nom d'utilisateur configuré. Veuillez d'abord enregistrer votre nom d'utilisateur.",
|
||||
"switchUsernameSuccess": "Basculé vers \"{username}\" avec succès!",
|
||||
"switchUsernameFailed": "Échec du changement de nom d'utilisateur",
|
||||
"playerNameTooLong": "Le nom du joueur doit comporter 16 caractères ou moins"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Confirmer l'action",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Supprimer",
|
||||
"uninstallGameTitle": "Désinstaller le jeu",
|
||||
"uninstallGameMessage": "Êtes-vous sûr de vouloir désinstaller Hytale? Tous les fichiers du jeu seront supprimés.",
|
||||
"uninstallGameButton": "Désinstaller"
|
||||
"uninstallGameButton": "Désinstaller",
|
||||
"switchUsernameTitle": "Changer d'identité",
|
||||
"switchUsernameMessage": "Basculer vers le nom d'utilisateur \"{username}\"? Cela changera votre identité de joueur actuelle.",
|
||||
"switchUsernameButton": "Changer"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Initialisation...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Gagal menghapus mod: {error}",
|
||||
"modsModNotFound": "Informasi mod tidak ditemukan",
|
||||
"hwAccelSaved": "Pengaturan akselerasi perangkat keras disimpan",
|
||||
"hwAccelSaveFailed": "Gagal menyimpan pengaturan akselerasi perangkat keras"
|
||||
"hwAccelSaveFailed": "Gagal menyimpan pengaturan akselerasi perangkat keras",
|
||||
"noUsername": "Nama pengguna belum dikonfigurasi. Silakan simpan nama pengguna terlebih dahulu.",
|
||||
"switchUsernameSuccess": "Berhasil beralih ke \"{username}\"!",
|
||||
"switchUsernameFailed": "Gagal beralih nama pengguna",
|
||||
"playerNameTooLong": "Nama pemain harus 16 karakter atau kurang"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Konfirmasi tindakan",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Hapus",
|
||||
"uninstallGameTitle": "Hapus instalasi game",
|
||||
"uninstallGameMessage": "Apakah kamu yakin ingin menghapus instalasi Hytale? Semua file game akan dihapus.",
|
||||
"uninstallGameButton": "Hapus Instalasi"
|
||||
"uninstallGameButton": "Hapus Instalasi",
|
||||
"switchUsernameTitle": "Ganti Identitas",
|
||||
"switchUsernameMessage": "Beralih ke nama pengguna \"{username}\"? Ini akan mengubah identitas pemain saat ini.",
|
||||
"switchUsernameButton": "Ganti"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Menginisialisasi...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Nie udało się usunąć moda: {error}",
|
||||
"modsModNotFound": "Nie znaleziono informacji o modzie",
|
||||
"hwAccelSaved": "Zapisano ustawienie przyspieszenia sprzętowego",
|
||||
"hwAccelSaveFailed": "Nie udało się zapisać ustawienia przyspieszenia sprzętowego"
|
||||
"hwAccelSaveFailed": "Nie udało się zapisać ustawienia przyspieszenia sprzętowego",
|
||||
"noUsername": "Nie skonfigurowano nazwy użytkownika. Najpierw zapisz swoją nazwę użytkownika.",
|
||||
"switchUsernameSuccess": "Pomyślnie przełączono na \"{username}\"!",
|
||||
"switchUsernameFailed": "Nie udało się przełączyć nazwy użytkownika",
|
||||
"playerNameTooLong": "Nazwa gracza musi mieć 16 znaków lub mniej"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Potwierdź działanie",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Usuń",
|
||||
"uninstallGameTitle": "Odinstaluj grę",
|
||||
"uninstallGameMessage": "Czy na pewno chcesz odinstalować Hytale? Wszystkie pliki gry zostaną usunięte.",
|
||||
"uninstallGameButton": "Odinstaluj"
|
||||
"uninstallGameButton": "Odinstaluj",
|
||||
"switchUsernameTitle": "Zmień tożsamość",
|
||||
"switchUsernameMessage": "Przełączyć na nazwę użytkownika \"{username}\"? To zmieni Twoją aktualną tożsamość gracza.",
|
||||
"switchUsernameButton": "Przełącz"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Inicjalizacja...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Falha ao excluir mod: {error}",
|
||||
"modsModNotFound": "Informações do mod não encontradas",
|
||||
"hwAccelSaved": "Configuração de aceleração de hardware salva",
|
||||
"hwAccelSaveFailed": "Falha ao salvar configuração de aceleração de hardware"
|
||||
"hwAccelSaveFailed": "Falha ao salvar configuração de aceleração de hardware",
|
||||
"noUsername": "Nenhum nome de usuário configurado. Por favor, salve seu nome de usuário primeiro.",
|
||||
"switchUsernameSuccess": "Alterado para \"{username}\" com sucesso!",
|
||||
"switchUsernameFailed": "Falha ao trocar nome de usuário",
|
||||
"playerNameTooLong": "O nome do jogador deve ter 16 caracteres ou menos"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Confirmar ação",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Excluir",
|
||||
"uninstallGameTitle": "Desinstalar jogo",
|
||||
"uninstallGameMessage": "Tem certeza de que deseja desinstalar Hytale? Todos os arquivos do jogo serão excluídos.",
|
||||
"uninstallGameButton": "Desinstalar"
|
||||
"uninstallGameButton": "Desinstalar",
|
||||
"switchUsernameTitle": "Trocar Identidade",
|
||||
"switchUsernameMessage": "Trocar para o nome de usuário \"{username}\"? Isso mudará sua identidade de jogador atual.",
|
||||
"switchUsernameButton": "Trocar"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Inicializando...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Не получилось удалить мод: {error}",
|
||||
"modsModNotFound": "Информация по моду не найдена",
|
||||
"hwAccelSaved": "Настройка аппаратного ускорения сохранена!",
|
||||
"hwAccelSaveFailed": "Не удалось сохранить настройку аппаратного ускорения"
|
||||
"hwAccelSaveFailed": "Не удалось сохранить настройку аппаратного ускорения",
|
||||
"noUsername": "Имя пользователя не настроено. Пожалуйста, сначала сохраните имя пользователя.",
|
||||
"switchUsernameSuccess": "Успешно переключено на \"{username}\"!",
|
||||
"switchUsernameFailed": "Не удалось переключить имя пользователя",
|
||||
"playerNameTooLong": "Имя игрока должно быть не более 16 символов"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Подтвердить действие",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Удалить",
|
||||
"uninstallGameTitle": "Удалить игру",
|
||||
"uninstallGameMessage": "Вы уверены, что хотите удалить Hytale? Все данные игры будут безвозвратно удалены!",
|
||||
"uninstallGameButton": "Удалить"
|
||||
"uninstallGameButton": "Удалить",
|
||||
"switchUsernameTitle": "Сменить личность",
|
||||
"switchUsernameMessage": "Переключиться на имя пользователя \"{username}\"? Это изменит вашу текущую личность игрока.",
|
||||
"switchUsernameButton": "Переключить"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Инициализация...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Misslyckades med att ta bort modd: {error}",
|
||||
"modsModNotFound": "Moddinformation hittades inte",
|
||||
"hwAccelSaved": "Hårdvaruaccelerationsinställning sparad",
|
||||
"hwAccelSaveFailed": "Misslyckades med att spara hårdvaruaccelerationsinställning"
|
||||
"hwAccelSaveFailed": "Misslyckades med att spara hårdvaruaccelerationsinställning",
|
||||
"noUsername": "Inget användarnamn konfigurerat. Vänligen spara ditt användarnamn först.",
|
||||
"switchUsernameSuccess": "Bytte till \"{username}\" framgångsrikt!",
|
||||
"switchUsernameFailed": "Misslyckades med att byta användarnamn",
|
||||
"playerNameTooLong": "Spelarnamnet måste vara 16 tecken eller mindre"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Bekräfta åtgärd",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Ta bort",
|
||||
"uninstallGameTitle": "Avinstallera spel",
|
||||
"uninstallGameMessage": "Är du säker på att du vill avinstallera Hytale? Alla spelfiler kommer att tas bort.",
|
||||
"uninstallGameButton": "Avinstallera"
|
||||
"uninstallGameButton": "Avinstallera",
|
||||
"switchUsernameTitle": "Byt identitet",
|
||||
"switchUsernameMessage": "Byta till användarnamn \"{username}\"? Detta kommer att ändra din nuvarande spelaridentitet.",
|
||||
"switchUsernameButton": "Byt"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Initierar...",
|
||||
|
||||
@@ -211,7 +211,11 @@
|
||||
"modsDeleteFailed": "Mod silinemedi: {error}",
|
||||
"modsModNotFound": "Mod bilgileri bulunamadı",
|
||||
"hwAccelSaved": "Donanım hızlandırma ayarı kaydedildi",
|
||||
"hwAccelSaveFailed": "Donanım hızlandırma ayarı kaydedilemedi"
|
||||
"hwAccelSaveFailed": "Donanım hızlandırma ayarı kaydedilemedi",
|
||||
"noUsername": "Kullanıcı adı yapılandırılmadı. Lütfen önce kullanıcı adınızı kaydedin.",
|
||||
"switchUsernameSuccess": "\"{username}\" adına başarıyla geçildi!",
|
||||
"switchUsernameFailed": "Kullanıcı adı değiştirilemedi",
|
||||
"playerNameTooLong": "Oyuncu adı 16 karakter veya daha az olmalıdır"
|
||||
},
|
||||
"confirm": {
|
||||
"defaultTitle": "Eylemi onayla",
|
||||
@@ -226,7 +230,10 @@
|
||||
"deleteUuidButton": "Sil",
|
||||
"uninstallGameTitle": "Oyunu kaldır",
|
||||
"uninstallGameMessage": "Hytale'yi kaldırmak istediğinizden emin misiniz? Tüm oyun dosyaları silinecektir.",
|
||||
"uninstallGameButton": "Kaldır"
|
||||
"uninstallGameButton": "Kaldır",
|
||||
"switchUsernameTitle": "Kimlik Değiştir",
|
||||
"switchUsernameMessage": "\"{username}\" kullanıcı adına geçilsin mi? Bu mevcut oyuncu kimliğinizi değiştirecektir.",
|
||||
"switchUsernameButton": "Değiştir"
|
||||
},
|
||||
"progress": {
|
||||
"initializing": "Başlatılıyor...",
|
||||
|
||||
@@ -5236,6 +5236,21 @@ select.settings-input option {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0.5px;
|
||||
-webkit-user-select: text !important;
|
||||
-moz-user-select: text !important;
|
||||
-ms-user-select: text !important;
|
||||
user-select: text !important;
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
|
||||
/* Ensure all input fields allow text selection and paste */
|
||||
input[type="text"].uuid-input,
|
||||
#customUuidInput {
|
||||
-webkit-user-select: text !important;
|
||||
-moz-user-select: text !important;
|
||||
-ms-user-select: text !important;
|
||||
user-select: text !important;
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
|
||||
.uuid-btn {
|
||||
@@ -5623,6 +5638,12 @@ select.settings-input option {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.uuid-item-btn.switch:hover {
|
||||
background: rgba(59, 130, 246, 0.2);
|
||||
border-color: rgba(59, 130, 246, 0.4);
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.uuid-modal-content {
|
||||
width: 95vw;
|
||||
|
||||
Reference in New Issue
Block a user