This repository has been archived on 2026-01-04. You can view files and clone it, but cannot push or open issues or pull requests.
polyplus/js/account/avatar-sandbox.js
2024-05-27 22:04:23 +00:00

389 lines
12 KiB
JavaScript
Executable file

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 = `
<div style="max-width: 150px;">
<div class="card mb-2 avatar-item-container">
<div class="p-2">
<img src=":ItemThumbnail" class="img-fluid">
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
<span class="badge bg-secondary">:ItemType</span>
</span>
<button class="avatarAction btn btn-success btn-sm position-absolute rounded-circle text-center" style="top: -10px; right: -16px; width: 32px; height: 32px; z-index: 1;"><i class="fas fa-plus"></i></button>
</div>
</div>
<a href="/store/:ItemID" class="text-reset">
<h6 class="text-truncate mb-0"> :ItemName</h6>
</a>
<small class="text-muted d-block text-truncate">
by <a href="/users/:CreatorID" class="text-reset">:CreatorName</a>
</small>
</div>
`;
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;
}