let PageContainer = document.querySelector('.container.p-0.p-lg-5') let ItemGrid; let Wearing; let Tabs; let IFrame; let TabSelected = 'hat' let Search; let Page = 1 let Avatar = { "useCharacter": true, "items": [], "shirt": null, "pants": null, "tool": {ID: -1, URL: null}, "headColor": "#e0e0e0", "torsoColor": "#e0e0e0", "leftArmColor": "#e0e0e0", "rightArmColor": "#e0e0e0", "leftLegColor": "#e0e0e0", "rightLegColor": "#e0e0e0" } let ItemCardContents = `
` if (new URLSearchParams(new URL(window.location).search).get('sandbox') === 'true') { console.log('Avatar Sandbox!') LoadFile(chrome.runtime.getURL('resources/avatar-sandbox.html'), function(html){ PageContainer.innerHTML = html ItemGrid = document.getElementById('inventory') Wearing = document.getElementById('wearing') Tabs = document.getElementById('tabs') IFrame = document.getElementById('viewFrame') Search = document.getElementById('item-search') Search.addEventListener('change', function(){ RefreshItems() }); UpdateAvatar() RefreshItems() Array.from(Tabs.children).forEach(element => { element.addEventListener('click', function(){ let Link = element.getElementsByTagName('a')[0] if (!(Link.classList.contains('active'))) { Link.classList.add('active') Tabs.querySelector(`[data-tab="${TabSelected}"]`).classList.remove('active') TabSelected = Link.getAttribute('data-tab') Page = 1 RefreshItems() } }); }); let Clear = document.getElementById('clear') Clear.addEventListener('click', function(){ Avatar = { "useCharacter": true, "items": [], "shirt": {ID: -1, URL: null}, "pants": {ID: -1, URL: null}, "tool": {ID: -1, URL: null}, "headColor": "#e0e0e0", "torsoColor": "#e0e0e0", "leftArmColor": "#e0e0e0", "rightArmColor": "#e0e0e0", "leftLegColor": "#e0e0e0", "rightLegColor": "#e0e0e0" } UpdateAvatar() }); let JSONUpload = document.getElementById('jsonUpload') JSONUpload.addEventListener('change', function(){ let Reader = new FileReader() Reader.addEventListener('loadend', function(){ Avatar = JSON.parse(Reader.result) UpdateAvatar() JSONUpload.value = "" }); Reader.readAsText(JSONUpload.files[0]) }); let JSONSave = document.getElementById('jsonSave') JSONSave.addEventListener('click', function(){ FormatAvatar().then(FormattedAvatar => { let Download = document.createElement('a') Download.href = URL.createObjectURL(new Blob([JSON.stringify(FormattedAvatar)], { type: "application/json" })); Download.setAttribute('download', 'AvatarSandbox.json') document.body.appendChild(Download) Download.click() document.body.removeChild(Download) }); }); let OpenInNewTab = document.getElementById('openNewTab') OpenInNewTab.addEventListener('click', function(){ UpdateAvatar() }); }); } function UpdateAvatar() { GenerateHash() .then(hash => { IFrame.addEventListener('load', function () { IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + hash; }); IFrame.src = 'about:blank'; }); } function LoadFile(path, callback) { var xhr = new XMLHttpRequest(); xhr.onload = function () { return callback(this.responseText); } xhr.open("GET", path, true); xhr.send(); } async function GenerateHash() { let FormattedAvatar = await FormatAvatar() for (let i = 0; i < FormattedAvatar.items.length; i++) { FormattedAvatar.items[i] = FormattedAvatar.items[i].URL } if (FormattedAvatar.shirt) { FormattedAvatar.shirt = FormattedAvatar.shirt.URL } if (FormattedAvatar.pants) { FormattedAvatar.pants = FormattedAvatar.pants.URL } FormattedAvatar.face = FormattedAvatar.face.URL if (FormattedAvatar.tool) { FormattedAvatar.tool = FormattedAvatar.tool.URL } console.log('Formatted Avatar: ', FormattedAvatar) console.log('Real Avatar: ', Avatar) return btoa(encodeURIComponent(JSON.stringify(FormattedAvatar))) } async function FormatAvatar() { let LocalAvatar = structuredClone(Avatar) if (!LocalAvatar.face) { LocalAvatar.face = {ID: -1, URL: "https://c0.ptacdn.com/static/3dview/DefaultFace.png"} } for (let i = 0; i < LocalAvatar.items.length; i++) { if (LocalAvatar.items[i].URL === null) { await fetch("https://api.polytoria.com/v1/assets/serve-mesh/:id".replace(':id', LocalAvatar.items[i].ID)) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Avatar.items[i].URL = data.url LocalAvatar.items[i].URL = data.url }) .catch(error => { console.error('Fetch error:', error); }); } } if (LocalAvatar.tool && LocalAvatar.tool.ID !== -1 && LocalAvatar.tool.URL === null) { await fetch("https://api.polytoria.com/v1/assets/serve-mesh/:id".replace(':id', LocalAvatar.tool.ID)) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Avatar.tool.URL = data.url LocalAvatar.tool.URL = data.url }) .catch(error => { console.error('Fetch error:', error); }); } if (LocalAvatar.face.ID !== -1 && LocalAvatar.face.URL === null) { await fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', LocalAvatar.face.ID)) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Avatar.face.URL = data.url LocalAvatar.face.URL = data.url }) .catch(error => { console.error('Fetch error:', error); }); } if (LocalAvatar.shirt && LocalAvatar.shirt.ID !== -1 && LocalAvatar.shirt.URL === null) { await fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', LocalAvatar.shirt.ID)) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Avatar.shirt.URL = data.url LocalAvatar.shirt.URL = data.url }) .catch(error => { console.error('Fetch error:', error); }); } if (LocalAvatar.pants && LocalAvatar.pants.ID !== -1 && LocalAvatar.pants.URL === null) { await fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', LocalAvatar.pants.ID)) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Avatar.pants.URL = data.url LocalAvatar.pants.URL = data.url }) .catch(error => { console.error('Fetch error:', error); }); } return LocalAvatar } function RefreshItems() { fetch(`https://api.polytoria.com/v1/store?search=${Search.value}&types%5B%5D=${TabSelected}&sort=createdAt&order=desc&page=${Page}&limit=12`) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Array.from(ItemGrid.children).forEach(element => {element.remove()}); data = data.assets data.forEach(item => { let NewItemCard = document.createElement('div') NewItemCard.classList = 'col-auto' NewItemCard.innerHTML = ItemCardContents.replace(':ItemName', item.name).replace().replace(':ItemID', item.id).replace(':ItemType', item.type.replace(item.type.charAt(0), item.type.charAt(0).toUpperCase())).replace(':CreatorName', item.creator.name).replace(':CreatorID', item.creator.id).replace(':ItemThumbnail', item.thumbnail) NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function(){ WearAsset(NewItemCard, item.name, {Name: item.creator.name, ID: item.creator.id}, item.id, item.type, item.thumbnail) }); ItemGrid.appendChild(NewItemCard) }); }) .catch(error => { console.error('Fetch error:', error); }); } function WearAsset(element, name, creator, id, type, thumbnail) { switch (type) { case 'hat': let Index = CheckItemID(Avatar.items, id) if (Index === -1) { if (Avatar.items.length !== 3) { Avatar.items.push({Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail}) Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } else { Avatar.items.splice(0, 1) Avatar.items.push({Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail}) if (TabSelected === type) { console.log('tab is', TabSelected, type) ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } } } else { console.log('remove') Avatar.items.splice(Index, 1) if (TabSelected === type) { console.log('tab is', TabSelected, type) ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } } break case 'face': if (Avatar.face && Avatar.face.ID !== id) { Avatar.face = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail} Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } else { Avatar.face = {Name: "Default Face", Creator: {Name: "Polytoria", ID: 1}, ID: -1, URL: "https://c0.ptacdn.com/static/3dview/DefaultFace.png", Thumbnail: "https://c0.ptacdn.com/static/3dview/DefaultFace.png"} if (TabSelected === type) { console.log('tab is', TabSelected, type) ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } } break case 'tool': if (Avatar.tool && Avatar.tool.ID !== id) { Avatar.tool = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail} Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } else { Avatar.tool = null if (TabSelected === type) { console.log('tab is', TabSelected, type) ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } } break case 'shirt': if (Avatar.shirt.ID !== id) { Avatar.shirt = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail} Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } else { Avatar.shirt = null if (TabSelected === type) { console.log('tab is', TabSelected, type) ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } } break case 'pants': if (Avatar.pants.ID !== id) { Avatar.pants = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail} Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } else { Avatar.pants = null if (TabSelected === type) { console.log('tab is', TabSelected, type) ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`)) } } break } UpdateAvatar() } function CheckItemID(object, id) { for (let i = 0; i < object.length; i++) { if (object[i] === id || object[i].ID === id) { console.log('Index: ' + i) return i } } return -1 }