const UserID = JSON.parse(window.localStorage.getItem('p+account_info')).ID; const BodyColors = [ '#f8f8f8', '#cdcdcd', '#111111', '#ff0000', '#a34b4b', '#ffc9c9', '#957977', '#c4281c', '#da867a', '#694028', '#cc8e69', '#a05f35', '#7c5c46', '#eab892', '#da8541', '#aa5500', '#ffcc99', '#e29b40', '#ffaf00', '#ffb000', '#d7c59a', '#f5cd30', '#fdea8d', '#e5e4df', '#c1be42', '#ffff00', '#ffffcc', '#a4bd47', '#7f8e64', '#a1c48c', '#3a7d15', '#4b974b', '#00ff00', '#ccffcc', '#27462d', '#287f47', '#789082', '#9ff3e9', '#12eed4', '#f2f3f3', '#00ffff', '#008f9c', '#04afec', '#80bbdb', '#b4d2e4', '#0d69ac', '#1b2a35', '#afddff', '#6e99ca', '#74869d', '#2154b9', '#002060', '#0000ff', '#b1a7ff', '#a3a2a5', '#6225d1', '#b480ff', '#8c5b9f', '#6b327c', '#aa00aa', '#635f62', '#ff00bf', '#ff66cc', '#e8bac8' ]; 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: [24122], shirt: 24118, pants: 24123, headColor: '#e0e0e0', torsoColor: '#e0e0e0', leftArmColor: '#e0e0e0', rightArmColor: '#e0e0e0', leftLegColor: '#e0e0e0', rightLegColor: '#e0e0e0' }; if (new URLSearchParams(window.location.search).has('sandbox')) { 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('onchange', function () { RefreshItems(); }); UpdateAvatar(); RefreshItems(); LoadWearing(); 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: [24122], shirt: 24118, pants: 24123, headColor: '#e0e0e0', torsoColor: '#e0e0e0', leftArmColor: '#e0e0e0', rightArmColor: '#e0e0e0', leftLegColor: '#e0e0e0', rightLegColor: '#e0e0e0' }; UpdateAvatar(); }); let Myself = document.getElementById('myself'); Myself.addEventListener('click', function () { LoadMyself(); }); 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 () { let Download = document.createElement('a'); Download.href = URL.createObjectURL( new Blob([JSON.stringify(Avatar)], { 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(); }); let LoadAsset = document.getElementById('load-asset'); LoadAsset.addEventListener('click', async function () { console.log('clickk'); const MeshURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + LoadAsset.previousElementSibling.value)).json()).url; Avatar.items.push(MeshURL); UpdateAvatar(); }); }); } else { const SandboxButton = document.createElement('a'); SandboxButton.classList = 'btn btn-outline-success w-100 mt-3'; SandboxButton.href = '?sandbox=true'; SandboxButton.innerHTML = ' Avatar Sandbox'; document.getElementById('cont-move').parentElement.appendChild(SandboxButton); } 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(data) { if (!data) { console.log('Data not provided'); let FormattedAvatar = await FormatAvatar(); return btoa(encodeURIComponent(JSON.stringify(FormattedAvatar))); } else { console.log('Data provided'); return btoa(encodeURIComponent(JSON.stringify(data))); } } 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.setAttribute('data-id', item.id); NewItemCard.classList = 'col-auto'; NewItemCard.innerHTML = `
`; NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function () { WearAsset(NewItemCard, item); }); ItemGrid.appendChild(NewItemCard); }); }) .catch((error) => { console.error('Fetch error:', error); }); } async function FormatAvatar() { const FormattedAvatar = structuredClone(Avatar); // Hats, Tools: https://api.polytoria.com/v1/assets/serve-mesh/:id // or: https://api.polytoria.com/v1/assets/serve/:id/Asset Avatar.items.forEach(async (item, index) => { if (typeof item === 'number') { console.log(item); await FetchMesh(item) .then((URL) => { console.log('URL: ' + URL); FormattedAvatar.items[index] = URL; }) .catch((error) => { throw new Error(error); }); console.log('after url'); //Avatar.items[index] = URL } }); if (typeof FormattedAvatar.tool === 'number') { console.log(FormattedAvatar.tool); FormattedAvatar.tool = await FetchMesh(FormattedAvatar.tool); } if (FormattedAvatar.face === undefined) { FormattedAvatar.face = 'https://c0.ptacdn.com/static/3dview/DefaultFace.png'; } if (!FormattedAvatar.face.startsWith('data:') && !FormattedAvatar.face.startsWith('http')) { if (FormattedAvatar.face && typeof FormattedAvatar.face === 'number') { FormattedAvatar.face = await FetchAsset(FormattedAvatar.face); } else { FormattedAvatar.face = 'https://c0.ptacdn.com/static/3dview/DefaultFace.png'; } } if (typeof FormattedAvatar.shirt === 'number') { FormattedAvatar.shirt = await FetchAsset(FormattedAvatar.shirt); } if (typeof FormattedAvatar.pants === 'number') { FormattedAvatar.pants = await FetchAsset(FormattedAvatar.pants); } console.log('Real Avatar: ', Avatar, 'Formatted: ', FormattedAvatar); return FormattedAvatar; } function LoadMyself() { fetch('https://api.polytoria.com/v1/users/:id/avatar'.replace(':id', UserID)) .then((response) => { if (!response.ok) { throw new Error('Network not ok'); } return response.json(); }) .then((data) => { Avatar.items = []; data.assets.forEach((item) => { switch (item.type) { case 'hat': Avatar.items.push(item.id); break; default: Avatar[item.type] = item.id; break; } }); Avatar.headColor = '#' + data.colors.head || '#cdcdcd'; Avatar.torsoColor = '#' + data.colors.torso || '#cdcdcd'; Avatar.leftArmColor = '#' + data.colors.leftArm || '#cdcdcd'; Avatar.rightArmColor = '#' + data.colors.rightArm || '#cdcdcd'; Avatar.leftLegColor = '#' + data.colors.leftLeg || '#cdcdcd'; Avatar.rightLegColor = '#' + data.colors.rightLeg || '#cdcdcd'; UpdateAvatar(); }) .catch((error) => { console.log(error); }); } function WearAsset(element, info) { if (Avatar.items.indexOf(info.id) === -1 && Avatar[info.type] !== info.id) { console.log('Equip', info); switch (info.type) { case 'hat': Avatar.items.push(info.id); break; default: Avatar[info.type] = info.id; break; } } else { console.log('unequip', info); switch (info.type) { case 'hat': Avatar.items.splice(Avatar.items.indexOf(info.id), 1); break; case 'face': Avatar.face = 'https://c0.ptacdn.com/static/3dview/DefaultFace.png'; break; default: Avatar[info.type] = undefined; break; } } const ToggleButton = element.getElementsByClassName('avatarAction')[0]; ToggleButton.classList.toggle('btn-success'); ToggleButton.classList.toggle('btn-danger'); ToggleButton.children[0].classList.toggle('fa-plus'); ToggleButton.children[0].classList.toggle('fa-minus'); const Duplicate = ItemGrid.querySelector(`[data-id="${info.id}"]`); if (Duplicate !== null && Duplicate !== element) { const DuplicateToggleButton = Duplicate.getElementsByClassName('avatarAction')[0]; DuplicateToggleButton.classList.toggle('btn-success'); DuplicateToggleButton.classList.toggle('btn-danger'); DuplicateToggleButton.children[0].classList.toggle('fa-plus'); DuplicateToggleButton.children[0].classList.toggle('fa-minus'); } LoadWearing(); UpdateAvatar(); } async function FetchMesh(id) { if (id === null) { return null; } console.log('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', id)); return fetch('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', id)) .then((response) => { if (!response.ok) { throw new Error('Network not ok'); } return response.json(); }) .then((data) => { console.log(data, 'finished', data.url); return data.url; }) .catch((error) => { console.log('Fetch error: ' + error); }); } async function FetchAsset(id) { if (id === null) { return null; } return fetch('https://api.polytoria.com/v1/assets/serve/:id/Asset'.replace(':id', id)) .then((response) => { if (!response.ok) { throw new Error('Network not ok'); } return response.json(); }) .then((data) => { return data.url; }) .catch((error) => { console.log('Fetch error: ' + error); }); } function LoadWearing() { const WearingItems = [...Avatar.items, Avatar.shirt, Avatar.pants, Avatar.face].filter((item) => item !== null && item !== undefined); Array.from(Wearing.children).forEach((element) => { const ItemID = element.getElementsByTagName('a')[0].href.split('/')[2]; if (!WearingItems.includes(ItemID)) { element.remove(); } }); WearingItems.forEach((item) => { const ExistingElement = Wearing.querySelector(`[data-itemid="${item}"]`); if (!ExistingElement) { fetch(`https://api.polytoria.com/v1/store/${item}`) .then((response) => { if (!response.ok) { throw new Error('Network not ok'); } return response.json(); }) .then((item) => { if (Wearing.innerHTML === 'No items to show.') { Wearing.innerHTML = ''; } let NewItemCard = document.createElement('div'); NewItemCard.setAttribute('data-id', item.id); NewItemCard.classList = 'col-auto'; NewItemCard.innerHTML = ` `; Wearing.appendChild(NewItemCard); NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function () { WearAsset(NewItemCard, item); }); }) .catch((error) => { console.log('Fetch error: ' + error); }); } }); if (Array.from(Wearing.children).length === 0) { Wearing.innerHTML = 'No items to show.'; } }