const SKIN_CACHE_KEY = 'cachedSkins';
const SELECTED_SKINS_CACHE_KEY = 'cachedSelectedSkins';
const SKIN_CACHE_TIMESTAMP_KEY = 'skinCacheTimestamp';
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
let loadSkinsDebounceTimer;
function loadSkinOptions() {
if (!currentUser) {
displayNoSkinsMessage("Please sign in to view and select skins.");
return;
}
clearTimeout(loadSkinsDebounceTimer);
loadSkinsDebounceTimer = setTimeout(() => {
const cachedSkins = localStorage.getItem(SKIN_CACHE_KEY);
const cachedSelectedSkins = localStorage.getItem(SELECTED_SKINS_CACHE_KEY);
const cacheTimestamp = localStorage.getItem(SKIN_CACHE_TIMESTAMP_KEY);
const currentTime = Date.now();
if (cachedSkins && cachedSelectedSkins && cacheTimestamp && (currentTime - parseInt(cacheTimestamp) < CACHE_DURATION)) {
console.log('Using cached skins and selected skins');
displayUnlockedSkins(JSON.parse(cachedSkins), JSON.parse(cachedSelectedSkins));
} else {
fetchAndCacheSkins();
}
}, 300);
}
function fetchAndCacheSkins() {
const skinCustomization = document.getElementById('skinCustomization');
// if (skinCustomization) {
// skinCustomization.innerHTML = '
Loading skins...
';
// }
const cachedEtag = localStorage.getItem('skinCacheEtag');
const headers = {
'Content-Type': 'application/json',
};
if (cachedEtag) {
headers['If-None-Match'] = cachedEtag;
}
Promise.all([
fetch('/get-unlocked-skins', {
method: 'POST',
headers: headers,
body: JSON.stringify({ username: currentUser }),
}),
fetch('/get-player-skin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: currentUser }),
})
])
.then(([unlockedResponse, selectedResponse]) => {
return Promise.all([
handleUnlockedSkinsResponse(unlockedResponse),
handleSelectedSkinsResponse(selectedResponse)
]);
})
.then(([unlockedSkins, selectedSkins]) => {
displayUnlockedSkins(unlockedSkins, selectedSkins);
})
.catch(error => {
console.error('Error loading skin options:', error);
displayNoSkinsMessage("An error occurred while loading skins. Please try again later.");
});
}
function handleUnlockedSkinsResponse(response) {
if (response.status === 304) {
console.log('Server returned 304 for unlocked skins, using cached data');
return JSON.parse(localStorage.getItem(SKIN_CACHE_KEY));
}
if (!response.ok) {
throw new Error('Network response was not ok for unlocked skins');
}
const newEtag = response.headers.get('ETag');
if (newEtag) {
localStorage.setItem('skinCacheEtag', newEtag);
}
return response.json().then(data => {
localStorage.setItem(SKIN_CACHE_KEY, JSON.stringify(data.skins));
localStorage.setItem(SKIN_CACHE_TIMESTAMP_KEY, Date.now().toString());
return data.skins;
});
}
function handleSelectedSkinsResponse(response) {
if (!response.ok) {
throw new Error('Network response was not ok for selected skins');
}
return response.json().then(data => {
localStorage.setItem(SELECTED_SKINS_CACHE_KEY, JSON.stringify(data));
return data;
});
}
function selectSkin(skinType, skinId, element) {
if (!currentUser) {
console.log('No user logged in');
return;
}
fetch(`/select-skin`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username: currentUser, skin_type: skinType, skin_id: skinId }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
if (data.success) {
console.log('Skin selected successfully');
// Remove 'selected' class from all skin options of the same type
const options = document.querySelectorAll(`#${skinType}Options .skin-option`);
options.forEach(option => option.classList.remove('selected'));
// Add 'selected' class to the clicked element
element.classList.add('selected');
// Update the local cache
updateLocalSelectedSkinCache(skinType, {
name: element.getAttribute('title').split(' (')[0],
value: skinType === 'color' ? element.style.backgroundColor : element.style.backgroundImage,
effect: element.classList.contains('glow-effect') ? 'glow' : null
});
loadPlayerSkin(currentUser);
} else {
console.error('Failed to select skin:', data.error);
}
})
.catch(error => {
console.error('Error selecting skin:', error);
});
}
function updateLocalSelectedSkinCache(skinType, skinData) {
const cachedSelectedSkins = JSON.parse(localStorage.getItem(SELECTED_SKINS_CACHE_KEY) || '{}');
cachedSelectedSkins[skinType] = skinData;
localStorage.setItem(SELECTED_SKINS_CACHE_KEY, JSON.stringify(cachedSelectedSkins));
}
function updateSkinCache(skinType, skinId) {
const cachedSkins = JSON.parse(localStorage.getItem(SKIN_CACHE_KEY) || '[]');
const updatedSkins = cachedSkins.map(skin => {
if (skin.type === skinType) {
return { ...skin, id: skinId };
}
return skin;
});
localStorage.setItem(SKIN_CACHE_KEY, JSON.stringify(updatedSkins));
}
function displayUnlockedSkins(skins, selectedSkins) {
const skinCustomization = document.getElementById('skinCustomization');
if (!skinCustomization) {
console.error('skinCustomization element not found');
return;
}
// Create a document fragment to build the new content
const fragment = document.createDocumentFragment();
const colorSelector = document.createElement('div');
colorSelector.id = 'colorSelector';
colorSelector.className = 'skin-section';
colorSelector.innerHTML = 'Colors
';
fragment.appendChild(colorSelector);
const hatSelector = document.createElement('div');
hatSelector.id = 'hatSelector';
hatSelector.className = 'skin-section';
hatSelector.innerHTML = 'Hats
';
fragment.appendChild(hatSelector);
// Append the fragment to skinCustomization
skinCustomization.innerHTML = '';
skinCustomization.appendChild(fragment);
const colorOptions = document.getElementById('colorOptions');
const hatOptions = document.getElementById('hatOptions');
let hasColors = false;
let hasHats = false;
skins.forEach(skin => {
const optionElement = document.createElement('div');
optionElement.classList.add('skin-option');
optionElement.setAttribute('data-skin-id', skin.id);
optionElement.setAttribute('title', `${skin.name} (${skin.rarity})`);
if (selectedSkins[skin.type] && selectedSkins[skin.type].name === skin.name) {
optionElement.classList.add('selected');
}
switch (skin.type) {
case 'color':
optionElement.style.backgroundColor = skin.value;
if (skin.effect === 'glow') {
optionElement.classList.add('glow-effect');
}
colorOptions.appendChild(optionElement);
hasColors = true;
break;
case 'hat':
optionElement.style.backgroundImage = `url(${skin.value})`;
hatOptions.appendChild(optionElement);
hasHats = true;
break;
}
optionElement.addEventListener('click', () => selectSkin(skin.type, skin.id, optionElement));
});
if (selectedSkins.color && !hasColors) {
const defaultColorElement = document.createElement('div');
defaultColorElement.classList.add('skin-option', 'selected');
defaultColorElement.style.backgroundColor = selectedSkins.color.value;
defaultColorElement.setAttribute('title', selectedSkins.color.name);
colorOptions.appendChild(defaultColorElement);
hasColors = true;
}
if (!hasColors) colorOptions.innerHTML = 'No colors unlocked yet
';
if (!hasHats) hatOptions.innerHTML = 'No hats unlocked yet
';
// Fade in the skin sections
setTimeout(() => {
document.getElementById('colorSelector').classList.add('loaded');
document.getElementById('hatSelector').classList.add('loaded');
}, 50);
if (!hasColors && !hasHats) {
displayNoSkinsMessage("You haven't unlocked any skins yet. Keep playing to earn skins!");
}
}
function displayNoSkinsMessage(message) {
const skinCustomization = document.getElementById('skinCustomization');
if (skinCustomization) {
skinCustomization.innerHTML = `${message}
`;
} else {
console.error('skinCustomization element not found');
}
}
// Call this function when the customization tab is opened
function onCustomizationTabOpen() {
loadSkinOptions();
}