267 lines
9.3 KiB
JavaScript
267 lines
9.3 KiB
JavaScript
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 = '<div class="loading-spinner">Loading skins...</div>';
|
|
}
|
|
|
|
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 = '<h4>Colors</h4><div id="colorOptions"></div>';
|
|
fragment.appendChild(colorSelector);
|
|
|
|
const hatSelector = document.createElement('div');
|
|
hatSelector.id = 'hatSelector';
|
|
hatSelector.className = 'skin-section';
|
|
hatSelector.innerHTML = '<h4>Hats</h4><div id="hatOptions"></div>';
|
|
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 = '<p>No colors unlocked yet</p>';
|
|
if (!hasHats) hatOptions.innerHTML = '<p>No hats unlocked yet</p>';
|
|
|
|
// 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 = `<p class="no-skins-message">${message}</p>`;
|
|
} else {
|
|
console.error('skinCustomization element not found');
|
|
}
|
|
}
|
|
|
|
|
|
// Call this function when the customization tab is opened
|
|
function onCustomizationTabOpen() {
|
|
loadSkinOptions();
|
|
} |