@ -11236,7 +11236,8 @@
// Check if user has a character
try {
const hasCharResponse = await fetch('/api/user/has-character', {
headers: { 'Authorization': `Bearer ${token}` }
headers: { 'Authorization': `Bearer ${token}` },
cache: 'no-store'
});
if (hasCharResponse.ok) {
@ -11253,17 +11254,18 @@
console.error('Failed to check character status:', e);
}
// Try to load character from server
// Try to load character from server (always fetch fresh, never use cache)
try {
const response = await fetch('/api/user/rpg-stats', {
headers: { 'Authorization': `Bearer ${token}` }
headers: { 'Authorization': `Bearer ${token}` },
cache: 'no-store' // Force fresh fetch, bypass all caches
});
if (response.ok) {
const serverStats = await response.json();
if (serverStats & & serverStats.name) {
playerStats = serverStats;
console.log('Loaded RPG stats from server:', playerStats);
console.log('Loaded RPG stats from server (fresh) :', playerStats);
// Mark that we've loaded from server - safe to save now
statsLoadedFromServer = true;
@ -11325,7 +11327,8 @@
try {
const response = await fetch('/api/user/rpg-stats', {
headers: { 'Authorization': `Bearer ${token}` }
headers: { 'Authorization': `Bearer ${token}` },
cache: 'no-store'
});
if (response.ok) {
@ -12470,6 +12473,57 @@
}
});
// Also save on pagehide (more reliable on mobile)
window.addEventListener('pagehide', () => {
if (playerStats & & statsLoadedFromServer) {
const token = localStorage.getItem('accessToken');
if (token) {
navigator.sendBeacon('/api/user/rpg-stats-beacon', new Blob([JSON.stringify({
token: token,
stats: playerStats
})], { type: 'application/json' }));
}
}
});
// Refresh stats from server when page becomes visible (switching tabs/apps)
document.addEventListener('visibilitychange', async () => {
if (document.visibilityState === 'visible' & & currentUser & & statsLoadedFromServer) {
console.log('[SYNC] Page visible - refreshing stats from server...');
const token = localStorage.getItem('accessToken');
if (!token) return;
try {
const response = await fetch('/api/user/rpg-stats', {
headers: { 'Authorization': `Bearer ${token}` },
cache: 'no-store' // Force fresh fetch
});
if (response.ok) {
const serverStats = await response.json();
if (serverStats & & serverStats.name) {
// Check if server has newer data
const serverVersion = serverStats.dataVersion || 0;
const localVersion = playerStats?.dataVersion || 0;
if (serverVersion > localVersion) {
console.log(`[SYNC] Server has newer data (v${serverVersion} > v${localVersion}), updating...`);
playerStats = serverStats;
localStorage.setItem('hikemap_rpg_stats', JSON.stringify(playerStats));
updateRpgHud();
updateHomeBaseMarker();
updateStatus('Stats synced from server', 'info');
} else {
console.log(`[SYNC] Local data is current (v${localVersion})`);
}
}
}
} catch (e) {
console.error('[SYNC] Failed to refresh stats:', e);
}
}
});
// Note: startAutoSave() is now called in initializePlayerStats() after server data loads
// This prevents auto-save from running before we have valid server data