chore: delete old avatar sandbox files
This commit is contained in:
parent
0689cc3a9a
commit
ca5eb0829d
4 changed files with 578 additions and 1505 deletions
|
|
@ -1,618 +0,0 @@
|
||||||
let Utilities;
|
|
||||||
|
|
||||||
const Container = document.querySelector('.container.p-0.p-lg-5')
|
|
||||||
const ItemCache = {
|
|
||||||
24122: {
|
|
||||||
type: "hat",
|
|
||||||
accessoryType: "hat",
|
|
||||||
name: "Polytoria Cap",
|
|
||||||
price: 0,
|
|
||||||
creator: {
|
|
||||||
name: "Polytoria",
|
|
||||||
id: 1
|
|
||||||
},
|
|
||||||
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/RR0VPd5hX30Fx5APwRBGObotf1xD1DRT.png",
|
|
||||||
asset: "https://c0.ptacdn.com/assets/InBsL5bpJdp84ZPZGQMeHuyCBlo-uOv7.glb"
|
|
||||||
},
|
|
||||||
24118: {
|
|
||||||
type: "shirt",
|
|
||||||
name: "Green Polytoria Flannel",
|
|
||||||
price: 0,
|
|
||||||
creator: {
|
|
||||||
name: "Polytoria",
|
|
||||||
id: 1
|
|
||||||
},
|
|
||||||
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/s7l57JugjbZfWTKAQ0cqTohOBraRbX5E.png",
|
|
||||||
asset: "https://c0.ptacdn.com/assets/uWrrnFGwgNN5W171vqYTWY7E639rKiXK.png"
|
|
||||||
},
|
|
||||||
24123: {
|
|
||||||
type: "pants",
|
|
||||||
name: "Jeans",
|
|
||||||
price: 0,
|
|
||||||
creator: {
|
|
||||||
name: "Polytoria",
|
|
||||||
id: 1
|
|
||||||
},
|
|
||||||
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/anebTuFMLg8NKhRL3ab7hbzCfmcsFqGO.png",
|
|
||||||
asset: "https://c0.ptacdn.com/assets/HD6TFdXD8CaflRNmd84VCNyNsmTB0SH3.png"
|
|
||||||
},
|
|
||||||
37582: {
|
|
||||||
type: "torso",
|
|
||||||
name: "Slim Body",
|
|
||||||
price: 0,
|
|
||||||
creator: {
|
|
||||||
name: "Polytoria",
|
|
||||||
id: 1
|
|
||||||
},
|
|
||||||
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/f_k-ZN_xmA_ALZiJQanOKT-Y4qq5kI1b.png",
|
|
||||||
asset: "https://c0.ptacdn.com/assets/qoqZ2qPyaGvB3MLGgJZ6oLWTz-xxGo-8.glb"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let Avatar = {
|
|
||||||
useCharacter: true,
|
|
||||||
items: [24122],
|
|
||||||
shirt: 24118,
|
|
||||||
pants: 24123,
|
|
||||||
headColor: '#e0e0e0',
|
|
||||||
torsoColor: '#e0e0e0',
|
|
||||||
leftArmColor: '#e0e0e0',
|
|
||||||
rightArmColor: '#e0e0e0',
|
|
||||||
leftLegColor: '#e0e0e0',
|
|
||||||
rightLegColor: '#e0e0e0'
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Discovery */
|
|
||||||
let Page = 1
|
|
||||||
let PageCount = 1
|
|
||||||
let Search = ""
|
|
||||||
let Sort = "createdAt"
|
|
||||||
let Order = "desc"
|
|
||||||
let ShowOffsale = true
|
|
||||||
let TabSelected = "hat"
|
|
||||||
|
|
||||||
!(async () => {
|
|
||||||
Utilities = await import(chrome.runtime.getURL('resources/utils.js'));
|
|
||||||
Utilities = Utilities.default;
|
|
||||||
|
|
||||||
chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
|
|
||||||
Settings = result.PolyPlus_Settings || Utilities.DefaultSettings;
|
|
||||||
|
|
||||||
if (Settings.AvatarSandboxOn || 1 === 1) {
|
|
||||||
if (new URLSearchParams(window.location.search).has('sandbox')) {
|
|
||||||
document.title = 'Poly+ Avatar Sandbox'
|
|
||||||
PageLoad()
|
|
||||||
} else {
|
|
||||||
const SandboxButton = document.createElement('a');
|
|
||||||
SandboxButton.classList = 'btn btn-outline-success w-100 mt-3';
|
|
||||||
SandboxButton.href = '?sandbox=true';
|
|
||||||
SandboxButton.innerHTML = '<i class="fas fa-shirt"></i> Avatar Sandbox';
|
|
||||||
document.getElementById('cont-move').parentElement.appendChild(SandboxButton);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})();
|
|
||||||
|
|
||||||
async function PageLoad() {
|
|
||||||
const PageContents = (await ((await fetch(chrome.runtime.getURL('resources/avatar-sandbox.html'))).text()))
|
|
||||||
Container.innerHTML = PageContents
|
|
||||||
Utilities.InjectResource("registerTooltips")
|
|
||||||
|
|
||||||
IFrame = document.getElementById('viewFrame')
|
|
||||||
|
|
||||||
UpdateAvatar()
|
|
||||||
LoadItems()
|
|
||||||
|
|
||||||
const Tabs = document.getElementById('tabs')
|
|
||||||
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');
|
|
||||||
ItemSearch.previousElementSibling.value = ''
|
|
||||||
Page = 1;
|
|
||||||
Search = ""
|
|
||||||
LoadItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const ItemSearch = document.getElementById('search-btn')
|
|
||||||
ItemSearch.addEventListener('click', function(){
|
|
||||||
Search = ItemSearch.previousElementSibling.value
|
|
||||||
Page = 1
|
|
||||||
LoadItems()
|
|
||||||
})
|
|
||||||
|
|
||||||
const ItemSort = document.getElementById('item-sort')
|
|
||||||
ItemSort.addEventListener('change', function(){
|
|
||||||
Sort = ItemSort.options[ItemSort.selectedIndex].value
|
|
||||||
Page = 1
|
|
||||||
LoadItems()
|
|
||||||
})
|
|
||||||
|
|
||||||
const ItemOrder = document.getElementById('item-order')
|
|
||||||
ItemOrder.addEventListener('change', function(){
|
|
||||||
Order = ItemOrder.options[ItemOrder.selectedIndex].value
|
|
||||||
Page = 1
|
|
||||||
LoadItems()
|
|
||||||
})
|
|
||||||
|
|
||||||
/*
|
|
||||||
Public API does not have an offsale parameter
|
|
||||||
|
|
||||||
document.getElementById('show-offsale').addEventListener('change', function(){
|
|
||||||
ShowOffsale = !ShowOffsale
|
|
||||||
console.log(ShowOffsale)
|
|
||||||
Page = 1
|
|
||||||
LoadItems()
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Pagination is annoying
|
|
||||||
const First = document.getElementById('pagination-first');
|
|
||||||
const Prev = document.getElementById('pagination-prev');
|
|
||||||
const Next = document.getElementById('pagination-next');
|
|
||||||
const Last = document.getElementById('pagination-last');
|
|
||||||
|
|
||||||
if (Page > 0) {
|
|
||||||
Prev.parentElement.classList.remove('disabled');
|
|
||||||
First.parentElement.classList.remove('disabled');
|
|
||||||
} else {
|
|
||||||
Prev.parentElement.classList.add('disabled');
|
|
||||||
First.parentElement.classList.add('disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
First.addEventListener('click', function () {
|
|
||||||
if (Page > 1) {
|
|
||||||
Page = 1;
|
|
||||||
LoadItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Prev.addEventListener('click', function () {
|
|
||||||
if (Page > 1) {
|
|
||||||
Page--;
|
|
||||||
LoadItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Next.addEventListener('click', function () {
|
|
||||||
if (Page < PageCount) {
|
|
||||||
Page++;
|
|
||||||
LoadItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Last.addEventListener('click', function () {
|
|
||||||
if (Page < PageCount) {
|
|
||||||
Page = PageCount;
|
|
||||||
LoadItems();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ClearButton = document.getElementById('clear');
|
|
||||||
ClearButton.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();
|
|
||||||
});
|
|
||||||
|
|
||||||
const LoadMyselfButton = document.getElementById('myself');
|
|
||||||
LoadMyselfButton.addEventListener('click', function () {
|
|
||||||
LoadUser(JSON.parse(window.localStorage.getItem('p+account_info')).ID);
|
|
||||||
});
|
|
||||||
|
|
||||||
const JSONUploadButton = document.getElementById('jsonUpload');
|
|
||||||
JSONUploadButton.addEventListener('change', function () {
|
|
||||||
const Reader = new FileReader();
|
|
||||||
Reader.addEventListener('loadend', function () {
|
|
||||||
Avatar = JSON.parse(Reader.result);
|
|
||||||
UpdateAvatar();
|
|
||||||
|
|
||||||
JSONUploadButton.value = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
Reader.readAsText(JSONUploadButton.files[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const JSONSaveButton = document.getElementById('jsonSave');
|
|
||||||
JSONSaveButton.addEventListener('click', function () {
|
|
||||||
const 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);
|
|
||||||
});
|
|
||||||
|
|
||||||
const OpenInNewTabButton = document.getElementById('openNewTab');
|
|
||||||
OpenInNewTabButton.addEventListener('click', function () {
|
|
||||||
window.open(IFrame, "_blank")
|
|
||||||
});
|
|
||||||
|
|
||||||
const LoadAsset = document.getElementById('load-asset')
|
|
||||||
const LoadAssetType = document.getElementById('load-asset-type')
|
|
||||||
LoadAsset.addEventListener('click', function(){
|
|
||||||
const SelectedType = LoadAssetType.options[LoadAssetType.selectedIndex].value
|
|
||||||
|
|
||||||
if (SelectedType !== 'user') {
|
|
||||||
if (SelectedType === 'hat') {
|
|
||||||
Avatar.items.push(LoadAsset.previousElementSibling.value);
|
|
||||||
} else {
|
|
||||||
Avatar[SelectedType] = parseInt(LoadAsset.previousElementSibling.value)
|
|
||||||
}
|
|
||||||
UpdateAvatar();
|
|
||||||
} else {
|
|
||||||
LoadUser(LoadAsset.previousElementSibling.value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
document.getElementById('view-cache').addEventListener('click', function(){
|
|
||||||
console.log('Cache: ', ItemCache)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function UpdateAvatar() {
|
|
||||||
// Hats, Tools: https://api.polytoria.com/v1/assets/serve-mesh/ID
|
|
||||||
// or: https://api.polytoria.com/v1/assets/serve/ID/Asset
|
|
||||||
|
|
||||||
const FormattedAvatar = structuredClone(Avatar)
|
|
||||||
|
|
||||||
const AccessoryPromise = [...Avatar.items, Avatar.tool, Avatar.torso].filter((x) => x !== undefined && !x.toString().startsWith('http') && !x.toString().startsWith('data:')).map(async (x, index) => {
|
|
||||||
if (ItemCache[x] === undefined) {
|
|
||||||
const ItemDetails = (await (await fetch('https://api.polytoria.com/v1/store/' + x)).json())
|
|
||||||
ItemCache[x] = {
|
|
||||||
type: ItemDetails.type,
|
|
||||||
name: ItemDetails.name,
|
|
||||||
price: ItemDetails.price,
|
|
||||||
creator: {
|
|
||||||
name: ItemDetails.creator.name,
|
|
||||||
id: ItemDetails.creator.id
|
|
||||||
},
|
|
||||||
thumbnail: ItemDetails.thumbnail,
|
|
||||||
asset: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItemDetails.type === 'hat') {
|
|
||||||
ItemCache[x].accessoryType = ItemDetails.accessoryType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItemCache[x].asset === undefined) {
|
|
||||||
const MeshURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + x)).json())
|
|
||||||
if (MeshURL.success) {
|
|
||||||
ItemCache[x].asset = MeshURL.url
|
|
||||||
|
|
||||||
if (["mesh", "decal", "audio"].indexOf(ItemCache[x].type) !== -1) {
|
|
||||||
ItemCache[x].type = document.getElementById('load-asset-type').options[document.getElementById('load-asset-type').selectedIndex].value
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItemCache[x].type === 'hat') {
|
|
||||||
FormattedAvatar.items[index] = MeshURL.url
|
|
||||||
} else {
|
|
||||||
FormattedAvatar[ItemCache[x].type] = MeshURL.url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ItemCache[x].type === 'hat') {
|
|
||||||
FormattedAvatar.items[index] = ItemCache[x].asset
|
|
||||||
} else {
|
|
||||||
FormattedAvatar[ItemCache[x].type] = ItemCache[x].asset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const TexturePromise = [Avatar.shirt, Avatar.pants, Avatar.face].filter((x) => x !== undefined && !x.toString().startsWith('http') && !x.toString().startsWith('data:') && x !== undefined).map(async (x, index) => {
|
|
||||||
if (ItemCache[x] === undefined) {
|
|
||||||
const ItemDetails = (await (await fetch('https://api.polytoria.com/v1/store/' + x)).json())
|
|
||||||
ItemCache[x] = {
|
|
||||||
type: ItemDetails.type,
|
|
||||||
name: ItemDetails.name,
|
|
||||||
price: ItemDetails.price,
|
|
||||||
creator: {
|
|
||||||
name: ItemDetails.creator.name,
|
|
||||||
id: ItemDetails.creator.id
|
|
||||||
},
|
|
||||||
thumbnail: ItemDetails.thumbnail,
|
|
||||||
asset: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItemDetails.price === 0) {
|
|
||||||
if (ItemDetails.sales === 0) {
|
|
||||||
ItemCache[x].price = null
|
|
||||||
} else {
|
|
||||||
ItemCache[x].price = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItemCache[x].asset === undefined) {
|
|
||||||
const TextureURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve/' + x + '/Asset')).json())
|
|
||||||
if (TextureURL.success) {
|
|
||||||
ItemCache[x].asset = TextureURL.url
|
|
||||||
if (x === Avatar.shirt) {
|
|
||||||
FormattedAvatar.shirt = TextureURL.url
|
|
||||||
} else if (x === Avatar.pants) {
|
|
||||||
FormattedAvatar.pants = TextureURL.url
|
|
||||||
} else if (x === Avatar.face) {
|
|
||||||
FormattedAvatar.face = TextureURL.url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (x === Avatar.shirt) {
|
|
||||||
FormattedAvatar.shirt = ItemCache[x].asset
|
|
||||||
} else if (x === Avatar.pants) {
|
|
||||||
FormattedAvatar.pants = ItemCache[x].asset
|
|
||||||
} else if (x === Avatar.face) {
|
|
||||||
FormattedAvatar.face = ItemCache[x].asset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Avatar.face === undefined) {
|
|
||||||
FormattedAvatar.face = "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(AccessoryPromise)
|
|
||||||
await Promise.all(TexturePromise)
|
|
||||||
|
|
||||||
console.log('Real Avatar: ', Avatar)
|
|
||||||
console.log('Formatted: ', FormattedAvatar)
|
|
||||||
IFrame.addEventListener('load', function(){
|
|
||||||
IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + btoa(encodeURIComponent(JSON.stringify(FormattedAvatar)))
|
|
||||||
})
|
|
||||||
IFrame.src = 'about:blank'
|
|
||||||
|
|
||||||
UpdateBodyColors()
|
|
||||||
LoadWearing()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function LoadUser(id) {
|
|
||||||
fetch('https://api.polytoria.com/v1/users/' + id + '/avatar')
|
|
||||||
.then((response) => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network not ok');
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
Avatar.items = [];
|
|
||||||
|
|
||||||
data.assets.forEach((item) => {
|
|
||||||
if (ItemCache[item.id] === undefined) {
|
|
||||||
ItemCache[item.id] = {
|
|
||||||
type: item.type,
|
|
||||||
name: item.name,
|
|
||||||
price: null,
|
|
||||||
creator: null,
|
|
||||||
thumbnail: item.thumbnail,
|
|
||||||
asset: item.path
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type === 'hat' || item.type === 'tool' || item.type === 'torso') {
|
|
||||||
ItemCache[item.id].creator = {
|
|
||||||
id: 1,
|
|
||||||
name: "Polytoria"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type === 'hat') {
|
|
||||||
ItemCache[item.id].accessoryType = item.accessoryType
|
|
||||||
Avatar.items.push(item.id)
|
|
||||||
} else {
|
|
||||||
Avatar[item.type] = item.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function LoadItems() {
|
|
||||||
document.getElementById('inventory').innerHTML = ''
|
|
||||||
|
|
||||||
const Items = (await (await fetch('https://api.polytoria.com/v1/store?limit=12&order=' + Order + '&sort=' + Sort + '&showOffsale=' + ShowOffsale + '&types[]='+ TabSelected +'&search=' + Search + '&page=' + Page)).json())
|
|
||||||
PageCount = Items.pages
|
|
||||||
if (Page < PageCount) {
|
|
||||||
document.getElementById('pagination-next').classList.remove('disabled');
|
|
||||||
document.getElementById('pagination-last').classList.remove('disabled');
|
|
||||||
} else {
|
|
||||||
document.getElementById('pagination-next').classList.add('disabled');
|
|
||||||
document.getElementById('pagination-last').classList.add('disabled');
|
|
||||||
}
|
|
||||||
if (Page > 1 && PageCount > 1) {
|
|
||||||
console.log('aaa')
|
|
||||||
console.log(Page > 1, PageCount > 1)
|
|
||||||
document.getElementById('pagination-prev').classList.remove('disabled');
|
|
||||||
document.getElementById('pagination-first').classList.remove('disabled');
|
|
||||||
} else {
|
|
||||||
document.getElementById('pagination-prev').classList.add('disabled');
|
|
||||||
document.getElementById('pagination-first').classList.add('disabled');
|
|
||||||
}
|
|
||||||
document.getElementById('pagination-current').innerText = Page
|
|
||||||
Items.assets.forEach(item => {
|
|
||||||
const ItemColumn = document.createElement('div')
|
|
||||||
ItemColumn.classList = 'col-auto'
|
|
||||||
ItemColumn.innerHTML = `
|
|
||||||
<div style="max-width: 150px;">
|
|
||||||
<div class="card mb-2 avatar-item-container">
|
|
||||||
<div class="p-2">
|
|
||||||
<img src="${item.thumbnail}" class="img-fluid">
|
|
||||||
${ (item.type === 'hat') ? `
|
|
||||||
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
|
|
||||||
<span class="badge bg-secondary">${CleanAccessoryType(item.accessoryType)}</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/${item.id}" class="text-reset">
|
|
||||||
<h6 class="text-truncate mb-0">${item.name}</h6>
|
|
||||||
</a>
|
|
||||||
<small class="text-muted d-block text-truncate">
|
|
||||||
by <a href="/users/${ (["hat", "tool", "face", "torso"].indexOf(item.type) !== -1) ? '1' : item.creator.id }" class="text-reset">${ (["hat", "tool", "face", "torso"].indexOf(item.type) !== -1) ? 'Polytoria' : item.creator.name }</a>
|
|
||||||
</small>
|
|
||||||
<small style="font-size: 0.8rem;" class="d-block text-truncate mb-2
|
|
||||||
${ (item.price === 0) ? 'text-primary fw-bold">Free' : (item.price !== "???") ? 'text-success"><i class="pi mr-1">$</i> ' + item.price : 'text-muted">???</small>' }
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
document.getElementById('inventory').appendChild(ItemColumn)
|
|
||||||
|
|
||||||
ItemCache[item.id] = {
|
|
||||||
type: item.type,
|
|
||||||
name: item.name,
|
|
||||||
price: item.price,
|
|
||||||
creator: {
|
|
||||||
name: item.creator.name,
|
|
||||||
id: item.creator.id
|
|
||||||
},
|
|
||||||
thumbnail: item.thumbnail,
|
|
||||||
asset: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.price === 0) {
|
|
||||||
if (item.sales === 0) {
|
|
||||||
console.log("ITEM IS AWARD-ONLY!!! ", item)
|
|
||||||
ItemCache[item.id].price = null
|
|
||||||
} else {
|
|
||||||
ItemCache[item.id].price = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type === 'hat') {
|
|
||||||
ItemCache[item.id].accessoryType = item.accessoryType
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemColumn.getElementsByClassName('p-2')[0].addEventListener('click', function(){
|
|
||||||
WearAsset(item)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function LoadWearing() {
|
|
||||||
document.getElementById('wearing').innerHTML = '';
|
|
||||||
[...Avatar.items, Avatar.shirt, Avatar.pants, Avatar.torso].filter((x) => x !== undefined).forEach(id => {
|
|
||||||
const Cached = Object.values(ItemCache)[Object.keys(ItemCache).indexOf(id.toString())]
|
|
||||||
if (Cached !== undefined) {
|
|
||||||
if (Cached.creator === undefined || Cached.creator === null) {
|
|
||||||
Cached.creator = {
|
|
||||||
id: 1,
|
|
||||||
name: "-"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Cached.price === undefined || Cached.price === null) { Cached.price = "???" }
|
|
||||||
|
|
||||||
const ItemColumn = document.createElement('div')
|
|
||||||
ItemColumn.classList = 'col-auto'
|
|
||||||
ItemColumn.innerHTML = `
|
|
||||||
<div style="max-width: 150px;">
|
|
||||||
<div class="card mb-2 avatar-item-container">
|
|
||||||
<div class="p-2">
|
|
||||||
<img src="${Cached.thumbnail}" class="img-fluid">
|
|
||||||
${ (Cached.type === 'hat') ? `
|
|
||||||
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
|
|
||||||
<span class="badge bg-secondary">${CleanAccessoryType(Cached.accessoryType)}</span>
|
|
||||||
</span>
|
|
||||||
` : ''}
|
|
||||||
<button class="avatarAction btn btn-danger btn-sm position-absolute rounded-circle text-center" style="top: -10px; right: -16px; width: 32px; height: 32px; z-index: 1;"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="/store/${id}" class="text-reset">
|
|
||||||
<h6 class="text-truncate mb-0">${Cached.name}</h6>
|
|
||||||
</a>
|
|
||||||
<small class="text-muted d-block text-truncate">
|
|
||||||
by <a href="/users/${Cached.creator.id || "1"}" class="text-reset">${Cached.creator.name || "-"}</a>
|
|
||||||
</small>
|
|
||||||
<small style="font-size: 0.8rem;" class="d-block text-truncate mb-2
|
|
||||||
${ (Cached.price === 0) ? 'text-primary fw-bold">Free' : (Cached.price !== "???") ? 'text-success"><i class="pi mr-1">$</i> ' + Cached.price : 'text-muted">???</small>' }
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
document.getElementById('wearing').appendChild(ItemColumn)
|
|
||||||
|
|
||||||
ItemColumn.getElementsByClassName('p-2')[0].addEventListener('click', function(){
|
|
||||||
WearAsset(Cached)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function WearAsset(details) {
|
|
||||||
const ItemID = Object.keys(ItemCache)[Object.values(ItemCache).indexOf(details)]
|
|
||||||
if (Avatar[details.type] !== details.id && Avatar.items.indexOf(details.id) === -1) {
|
|
||||||
// Equip
|
|
||||||
if (details.type === 'hat') {
|
|
||||||
Avatar.items.push(details.id)
|
|
||||||
} else {
|
|
||||||
Avatar[details.type] = details.id
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Unequip
|
|
||||||
if (details.type === 'hat') {
|
|
||||||
Avatar.items.splice(Avatar.items.indexOf(ItemID), 1);
|
|
||||||
} else {
|
|
||||||
Avatar[details.type] = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAvatar()
|
|
||||||
LoadWearing()
|
|
||||||
}
|
|
||||||
|
|
||||||
function UpdateBodyColors() {
|
|
||||||
const BodyColors = {
|
|
||||||
head: Avatar.headColor,
|
|
||||||
torso: Avatar.torsoColor,
|
|
||||||
leftArm: Avatar.leftArmColor,
|
|
||||||
rightArm: Avatar.rightArmColor,
|
|
||||||
leftLeg: Avatar.leftLegColor,
|
|
||||||
rightLeg: Avatar.rightLegColor
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(BodyColors).forEach((elementID, i) => {
|
|
||||||
document.getElementById(elementID).style.backgroundColor = Object.values(BodyColors)[i]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function CleanAccessoryType(type) {
|
|
||||||
const CleanAccessoryTypes = {
|
|
||||||
hat: "Hat",
|
|
||||||
backAccessory: "Back Accessory",
|
|
||||||
faceAccessory: "Face Accessory",
|
|
||||||
headAttachment: "Head Attachment",
|
|
||||||
hair: "Hair",
|
|
||||||
neckAccessory: "Neck Accessory",
|
|
||||||
headCover: "Head Cover",
|
|
||||||
headAccessory: "Head Accessory"
|
|
||||||
}
|
|
||||||
return Object.values(CleanAccessoryTypes)[Object.keys(CleanAccessoryTypes).indexOf(type)] || "!!!"+type
|
|
||||||
}
|
|
||||||
845
js/account/avatar-sandbox.js
Executable file → Normal file
845
js/account/avatar-sandbox.js
Executable file → Normal file
|
|
@ -1,17 +1,58 @@
|
||||||
let PageContainer = document.querySelector('.container.p-0.p-lg-5');
|
let Utilities;
|
||||||
let ItemGrid;
|
|
||||||
let Wearing;
|
const Container = document.querySelector('.container.p-0.p-lg-5')
|
||||||
let Tabs;
|
const ItemCache = {
|
||||||
let IFrame;
|
24122: {
|
||||||
let TabSelected = 'hat';
|
type: "hat",
|
||||||
let Search;
|
accessoryType: "hat",
|
||||||
let Page = 1;
|
name: "Polytoria Cap",
|
||||||
|
price: 0,
|
||||||
|
creator: {
|
||||||
|
name: "Polytoria",
|
||||||
|
id: 1
|
||||||
|
},
|
||||||
|
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/RR0VPd5hX30Fx5APwRBGObotf1xD1DRT.png",
|
||||||
|
asset: "https://c0.ptacdn.com/assets/InBsL5bpJdp84ZPZGQMeHuyCBlo-uOv7.glb"
|
||||||
|
},
|
||||||
|
24118: {
|
||||||
|
type: "shirt",
|
||||||
|
name: "Green Polytoria Flannel",
|
||||||
|
price: 0,
|
||||||
|
creator: {
|
||||||
|
name: "Polytoria",
|
||||||
|
id: 1
|
||||||
|
},
|
||||||
|
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/s7l57JugjbZfWTKAQ0cqTohOBraRbX5E.png",
|
||||||
|
asset: "https://c0.ptacdn.com/assets/uWrrnFGwgNN5W171vqYTWY7E639rKiXK.png"
|
||||||
|
},
|
||||||
|
24123: {
|
||||||
|
type: "pants",
|
||||||
|
name: "Jeans",
|
||||||
|
price: 0,
|
||||||
|
creator: {
|
||||||
|
name: "Polytoria",
|
||||||
|
id: 1
|
||||||
|
},
|
||||||
|
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/anebTuFMLg8NKhRL3ab7hbzCfmcsFqGO.png",
|
||||||
|
asset: "https://c0.ptacdn.com/assets/HD6TFdXD8CaflRNmd84VCNyNsmTB0SH3.png"
|
||||||
|
},
|
||||||
|
37582: {
|
||||||
|
type: "torso",
|
||||||
|
name: "Slim Body",
|
||||||
|
price: 0,
|
||||||
|
creator: {
|
||||||
|
name: "Polytoria",
|
||||||
|
id: 1
|
||||||
|
},
|
||||||
|
thumbnail: "https://c0.ptacdn.com/thumbnails/assets/f_k-ZN_xmA_ALZiJQanOKT-Y4qq5kI1b.png",
|
||||||
|
asset: "https://c0.ptacdn.com/assets/qoqZ2qPyaGvB3MLGgJZ6oLWTz-xxGo-8.glb"
|
||||||
|
}
|
||||||
|
}
|
||||||
let Avatar = {
|
let Avatar = {
|
||||||
useCharacter: true,
|
useCharacter: true,
|
||||||
items: [],
|
items: [24122],
|
||||||
shirt: null,
|
shirt: 24118,
|
||||||
pants: null,
|
pants: 24123,
|
||||||
tool: {ID: -1, URL: null},
|
|
||||||
headColor: '#e0e0e0',
|
headColor: '#e0e0e0',
|
||||||
torsoColor: '#e0e0e0',
|
torsoColor: '#e0e0e0',
|
||||||
leftArmColor: '#e0e0e0',
|
leftArmColor: '#e0e0e0',
|
||||||
|
|
@ -19,44 +60,49 @@ let Avatar = {
|
||||||
leftLegColor: '#e0e0e0',
|
leftLegColor: '#e0e0e0',
|
||||||
rightLegColor: '#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') {
|
/* Discovery */
|
||||||
console.log('Avatar Sandbox!');
|
let Page = 1
|
||||||
|
let PageCount = 1
|
||||||
|
let Search = ""
|
||||||
|
let Sort = "createdAt"
|
||||||
|
let Order = "desc"
|
||||||
|
let ShowOffsale = true
|
||||||
|
let TabSelected = "hat"
|
||||||
|
|
||||||
LoadFile(chrome.runtime.getURL('resources/avatar-sandbox.html'), function (html) {
|
!(async () => {
|
||||||
PageContainer.innerHTML = html;
|
Utilities = await import(chrome.runtime.getURL('resources/utils.js'));
|
||||||
ItemGrid = document.getElementById('inventory');
|
Utilities = Utilities.default;
|
||||||
Wearing = document.getElementById('wearing');
|
|
||||||
Tabs = document.getElementById('tabs');
|
|
||||||
IFrame = document.getElementById('viewFrame');
|
|
||||||
|
|
||||||
Search = document.getElementById('item-search');
|
chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
|
||||||
Search.addEventListener('change', function () {
|
Settings = result.PolyPlus_Settings || Utilities.DefaultSettings;
|
||||||
RefreshItems();
|
|
||||||
});
|
|
||||||
|
|
||||||
UpdateAvatar();
|
if (Settings.AvatarSandboxOn || 1 === 1) {
|
||||||
RefreshItems();
|
if (new URLSearchParams(window.location.search).has('sandbox')) {
|
||||||
|
document.title = 'Poly+ Avatar Sandbox'
|
||||||
|
PageLoad()
|
||||||
|
} else {
|
||||||
|
const SandboxButton = document.createElement('a');
|
||||||
|
SandboxButton.classList = 'btn btn-outline-success w-100 mt-3';
|
||||||
|
SandboxButton.href = '?sandbox=true';
|
||||||
|
SandboxButton.innerHTML = '<i class="fas fa-shirt"></i> Avatar Sandbox';
|
||||||
|
document.getElementById('cont-move').parentElement.appendChild(SandboxButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})();
|
||||||
|
|
||||||
|
async function PageLoad() {
|
||||||
|
const PageContents = (await ((await fetch(chrome.runtime.getURL('resources/avatar-sandbox.html'))).text()))
|
||||||
|
Container.innerHTML = PageContents
|
||||||
|
Utilities.InjectResource("registerTooltips")
|
||||||
|
|
||||||
|
IFrame = document.getElementById('viewFrame')
|
||||||
|
|
||||||
|
UpdateAvatar()
|
||||||
|
LoadItems()
|
||||||
|
|
||||||
|
const Tabs = document.getElementById('tabs')
|
||||||
Array.from(Tabs.children).forEach((element) => {
|
Array.from(Tabs.children).forEach((element) => {
|
||||||
element.addEventListener('click', function () {
|
element.addEventListener('click', function () {
|
||||||
let Link = element.getElementsByTagName('a')[0];
|
let Link = element.getElementsByTagName('a')[0];
|
||||||
|
|
@ -64,20 +110,95 @@ if (new URLSearchParams(new URL(window.location).search).get('sandbox') === 'tru
|
||||||
Link.classList.add('active');
|
Link.classList.add('active');
|
||||||
Tabs.querySelector(`[data-tab="${TabSelected}"]`).classList.remove('active');
|
Tabs.querySelector(`[data-tab="${TabSelected}"]`).classList.remove('active');
|
||||||
TabSelected = Link.getAttribute('data-tab');
|
TabSelected = Link.getAttribute('data-tab');
|
||||||
|
ItemSearch.previousElementSibling.value = ''
|
||||||
Page = 1;
|
Page = 1;
|
||||||
RefreshItems();
|
Search = ""
|
||||||
|
LoadItems();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let Clear = document.getElementById('clear');
|
const ItemSearch = document.getElementById('search-btn')
|
||||||
Clear.addEventListener('click', function () {
|
ItemSearch.addEventListener('click', function(){
|
||||||
|
Search = ItemSearch.previousElementSibling.value
|
||||||
|
Page = 1
|
||||||
|
LoadItems()
|
||||||
|
})
|
||||||
|
|
||||||
|
const ItemSort = document.getElementById('item-sort')
|
||||||
|
ItemSort.addEventListener('change', function(){
|
||||||
|
Sort = ItemSort.options[ItemSort.selectedIndex].value
|
||||||
|
Page = 1
|
||||||
|
LoadItems()
|
||||||
|
})
|
||||||
|
|
||||||
|
const ItemOrder = document.getElementById('item-order')
|
||||||
|
ItemOrder.addEventListener('change', function(){
|
||||||
|
Order = ItemOrder.options[ItemOrder.selectedIndex].value
|
||||||
|
Page = 1
|
||||||
|
LoadItems()
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Public API does not have an offsale parameter
|
||||||
|
|
||||||
|
document.getElementById('show-offsale').addEventListener('change', function(){
|
||||||
|
ShowOffsale = !ShowOffsale
|
||||||
|
console.log(ShowOffsale)
|
||||||
|
Page = 1
|
||||||
|
LoadItems()
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Pagination is annoying
|
||||||
|
const First = document.getElementById('pagination-first');
|
||||||
|
const Prev = document.getElementById('pagination-prev');
|
||||||
|
const Next = document.getElementById('pagination-next');
|
||||||
|
const Last = document.getElementById('pagination-last');
|
||||||
|
|
||||||
|
if (Page > 0) {
|
||||||
|
Prev.parentElement.classList.remove('disabled');
|
||||||
|
First.parentElement.classList.remove('disabled');
|
||||||
|
} else {
|
||||||
|
Prev.parentElement.classList.add('disabled');
|
||||||
|
First.parentElement.classList.add('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
First.addEventListener('click', function () {
|
||||||
|
if (Page > 1) {
|
||||||
|
Page = 1;
|
||||||
|
LoadItems();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Prev.addEventListener('click', function () {
|
||||||
|
if (Page > 1) {
|
||||||
|
Page--;
|
||||||
|
LoadItems();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Next.addEventListener('click', function () {
|
||||||
|
if (Page < PageCount) {
|
||||||
|
Page++;
|
||||||
|
LoadItems();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Last.addEventListener('click', function () {
|
||||||
|
if (Page < PageCount) {
|
||||||
|
Page = PageCount;
|
||||||
|
LoadItems();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const ClearButton = document.getElementById('clear');
|
||||||
|
ClearButton.addEventListener('click', function () {
|
||||||
Avatar = {
|
Avatar = {
|
||||||
useCharacter: true,
|
useCharacter: true,
|
||||||
items: [],
|
items: [24122],
|
||||||
shirt: {ID: -1, URL: null},
|
shirt: 24118,
|
||||||
pants: {ID: -1, URL: null},
|
pants: 24123,
|
||||||
tool: {ID: -1, URL: null},
|
|
||||||
headColor: '#e0e0e0',
|
headColor: '#e0e0e0',
|
||||||
torsoColor: '#e0e0e0',
|
torsoColor: '#e0e0e0',
|
||||||
leftArmColor: '#e0e0e0',
|
leftArmColor: '#e0e0e0',
|
||||||
|
|
@ -88,25 +209,29 @@ if (new URLSearchParams(new URL(window.location).search).get('sandbox') === 'tru
|
||||||
UpdateAvatar();
|
UpdateAvatar();
|
||||||
});
|
});
|
||||||
|
|
||||||
let JSONUpload = document.getElementById('jsonUpload');
|
const LoadMyselfButton = document.getElementById('myself');
|
||||||
JSONUpload.addEventListener('change', function () {
|
LoadMyselfButton.addEventListener('click', function () {
|
||||||
let Reader = new FileReader();
|
LoadUser(JSON.parse(window.localStorage.getItem('p+account_info')).ID);
|
||||||
|
});
|
||||||
|
|
||||||
|
const JSONUploadButton = document.getElementById('jsonUpload');
|
||||||
|
JSONUploadButton.addEventListener('change', function () {
|
||||||
|
const Reader = new FileReader();
|
||||||
Reader.addEventListener('loadend', function () {
|
Reader.addEventListener('loadend', function () {
|
||||||
Avatar = JSON.parse(Reader.result);
|
Avatar = JSON.parse(Reader.result);
|
||||||
UpdateAvatar();
|
UpdateAvatar();
|
||||||
|
|
||||||
JSONUpload.value = '';
|
JSONUploadButton.value = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
Reader.readAsText(JSONUpload.files[0]);
|
Reader.readAsText(JSONUploadButton.files[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
let JSONSave = document.getElementById('jsonSave');
|
const JSONSaveButton = document.getElementById('jsonSave');
|
||||||
JSONSave.addEventListener('click', function () {
|
JSONSaveButton.addEventListener('click', function () {
|
||||||
FormatAvatar().then((FormattedAvatar) => {
|
const Download = document.createElement('a');
|
||||||
let Download = document.createElement('a');
|
|
||||||
Download.href = URL.createObjectURL(
|
Download.href = URL.createObjectURL(
|
||||||
new Blob([JSON.stringify(FormattedAvatar)], {
|
new Blob([JSON.stringify(Avatar)], {
|
||||||
type: 'application/json'
|
type: 'application/json'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -115,275 +240,379 @@ if (new URLSearchParams(new URL(window.location).search).get('sandbox') === 'tru
|
||||||
Download.click();
|
Download.click();
|
||||||
document.body.removeChild(Download);
|
document.body.removeChild(Download);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const OpenInNewTabButton = document.getElementById('openNewTab');
|
||||||
|
OpenInNewTabButton.addEventListener('click', function () {
|
||||||
|
window.open(IFrame, "_blank")
|
||||||
});
|
});
|
||||||
|
|
||||||
let OpenInNewTab = document.getElementById('openNewTab');
|
const LoadAsset = document.getElementById('load-asset')
|
||||||
OpenInNewTab.addEventListener('click', function () {
|
const LoadAssetType = document.getElementById('load-asset-type')
|
||||||
|
LoadAsset.addEventListener('click', function(){
|
||||||
|
const SelectedType = LoadAssetType.options[LoadAssetType.selectedIndex].value
|
||||||
|
|
||||||
|
if (SelectedType !== 'user') {
|
||||||
|
if (SelectedType === 'hat') {
|
||||||
|
Avatar.items.push(LoadAsset.previousElementSibling.value);
|
||||||
|
} else {
|
||||||
|
Avatar[SelectedType] = parseInt(LoadAsset.previousElementSibling.value)
|
||||||
|
}
|
||||||
UpdateAvatar();
|
UpdateAvatar();
|
||||||
});
|
} else {
|
||||||
});
|
LoadUser(LoadAsset.previousElementSibling.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
document.getElementById('view-cache').addEventListener('click', function(){
|
||||||
|
console.log('Cache: ', ItemCache)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateAvatar() {
|
async function UpdateAvatar() {
|
||||||
GenerateHash().then((hash) => {
|
// Hats, Tools: https://api.polytoria.com/v1/assets/serve-mesh/ID
|
||||||
|
// or: https://api.polytoria.com/v1/assets/serve/ID/Asset
|
||||||
|
|
||||||
|
const FormattedAvatar = structuredClone(Avatar)
|
||||||
|
|
||||||
|
const AccessoryPromise = [...Avatar.items, Avatar.tool, Avatar.torso].filter((x) => x !== undefined && !x.toString().startsWith('http') && !x.toString().startsWith('data:')).map(async (x, index) => {
|
||||||
|
if (ItemCache[x] === undefined) {
|
||||||
|
const ItemDetails = (await (await fetch('https://api.polytoria.com/v1/store/' + x)).json())
|
||||||
|
ItemCache[x] = {
|
||||||
|
type: ItemDetails.type,
|
||||||
|
name: ItemDetails.name,
|
||||||
|
price: ItemDetails.price,
|
||||||
|
creator: {
|
||||||
|
name: ItemDetails.creator.name,
|
||||||
|
id: ItemDetails.creator.id
|
||||||
|
},
|
||||||
|
thumbnail: ItemDetails.thumbnail,
|
||||||
|
asset: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemDetails.type === 'hat') {
|
||||||
|
ItemCache[x].accessoryType = ItemDetails.accessoryType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemCache[x].asset === undefined) {
|
||||||
|
const MeshURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + x)).json())
|
||||||
|
if (MeshURL.success) {
|
||||||
|
ItemCache[x].asset = MeshURL.url
|
||||||
|
|
||||||
|
if (["mesh", "decal", "audio"].indexOf(ItemCache[x].type) !== -1) {
|
||||||
|
ItemCache[x].type = document.getElementById('load-asset-type').options[document.getElementById('load-asset-type').selectedIndex].value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemCache[x].type === 'hat') {
|
||||||
|
FormattedAvatar.items[index] = MeshURL.url
|
||||||
|
} else {
|
||||||
|
FormattedAvatar[ItemCache[x].type] = MeshURL.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ItemCache[x].type === 'hat') {
|
||||||
|
FormattedAvatar.items[index] = ItemCache[x].asset
|
||||||
|
} else {
|
||||||
|
FormattedAvatar[ItemCache[x].type] = ItemCache[x].asset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const TexturePromise = [Avatar.shirt, Avatar.pants, Avatar.face].filter((x) => x !== undefined && !x.toString().startsWith('http') && !x.toString().startsWith('data:') && x !== undefined).map(async (x, index) => {
|
||||||
|
if (ItemCache[x] === undefined) {
|
||||||
|
const ItemDetails = (await (await fetch('https://api.polytoria.com/v1/store/' + x)).json())
|
||||||
|
ItemCache[x] = {
|
||||||
|
type: ItemDetails.type,
|
||||||
|
name: ItemDetails.name,
|
||||||
|
price: ItemDetails.price,
|
||||||
|
creator: {
|
||||||
|
name: ItemDetails.creator.name,
|
||||||
|
id: ItemDetails.creator.id
|
||||||
|
},
|
||||||
|
thumbnail: ItemDetails.thumbnail,
|
||||||
|
asset: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemDetails.price === 0) {
|
||||||
|
if (ItemDetails.sales === 0) {
|
||||||
|
ItemCache[x].price = null
|
||||||
|
} else {
|
||||||
|
ItemCache[x].price = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemCache[x].asset === undefined) {
|
||||||
|
const TextureURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve/' + x + '/Asset')).json())
|
||||||
|
if (TextureURL.success) {
|
||||||
|
ItemCache[x].asset = TextureURL.url
|
||||||
|
if (x === Avatar.shirt) {
|
||||||
|
FormattedAvatar.shirt = TextureURL.url
|
||||||
|
} else if (x === Avatar.pants) {
|
||||||
|
FormattedAvatar.pants = TextureURL.url
|
||||||
|
} else if (x === Avatar.face) {
|
||||||
|
FormattedAvatar.face = TextureURL.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (x === Avatar.shirt) {
|
||||||
|
FormattedAvatar.shirt = ItemCache[x].asset
|
||||||
|
} else if (x === Avatar.pants) {
|
||||||
|
FormattedAvatar.pants = ItemCache[x].asset
|
||||||
|
} else if (x === Avatar.face) {
|
||||||
|
FormattedAvatar.face = ItemCache[x].asset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Avatar.face === undefined) {
|
||||||
|
FormattedAvatar.face = "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(AccessoryPromise)
|
||||||
|
await Promise.all(TexturePromise)
|
||||||
|
|
||||||
|
console.log('Real Avatar: ', Avatar)
|
||||||
|
console.log('Formatted: ', FormattedAvatar)
|
||||||
IFrame.addEventListener('load', function(){
|
IFrame.addEventListener('load', function(){
|
||||||
IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + hash;
|
IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + btoa(encodeURIComponent(JSON.stringify(FormattedAvatar)))
|
||||||
});
|
})
|
||||||
IFrame.src = 'about:blank';
|
IFrame.src = 'about:blank'
|
||||||
});
|
|
||||||
|
UpdateBodyColors()
|
||||||
|
LoadWearing()
|
||||||
}
|
}
|
||||||
|
|
||||||
function LoadFile(path, callback) {
|
async function LoadUser(id) {
|
||||||
var xhr = new XMLHttpRequest();
|
fetch('https://api.polytoria.com/v1/users/' + id + '/avatar')
|
||||||
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) => {
|
.then((response) => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok');
|
throw new Error('Network not ok');
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
Avatar.items[i].URL = data.url;
|
Avatar.items = [];
|
||||||
LocalAvatar.items[i].URL = data.url;
|
|
||||||
})
|
data.assets.forEach((item) => {
|
||||||
.catch((error) => {
|
if (ItemCache[item.id] === undefined) {
|
||||||
console.error('Fetch error:', error);
|
ItemCache[item.id] = {
|
||||||
});
|
type: item.type,
|
||||||
|
name: item.name,
|
||||||
|
price: null,
|
||||||
|
creator: null,
|
||||||
|
thumbnail: item.thumbnail,
|
||||||
|
asset: item.path
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type === 'hat' || item.type === 'tool' || item.type === 'torso') {
|
||||||
|
ItemCache[item.id].creator = {
|
||||||
|
id: 1,
|
||||||
|
name: "Polytoria"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocalAvatar.tool && LocalAvatar.tool.ID !== -1 && LocalAvatar.tool.URL === null) {
|
if (item.type === 'hat') {
|
||||||
await fetch('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', LocalAvatar.tool.ID))
|
ItemCache[item.id].accessoryType = item.accessoryType
|
||||||
.then((response) => {
|
Avatar.items.push(item.id)
|
||||||
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 {
|
} else {
|
||||||
Avatar.items.splice(0, 1);
|
Avatar[item.type] = item.id
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
UpdateAvatar();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function CheckItemID(object, id) {
|
async function LoadItems() {
|
||||||
for (let i = 0; i < object.length; i++) {
|
document.getElementById('inventory').innerHTML = ''
|
||||||
if (object[i] === id || object[i].ID === id) {
|
|
||||||
console.log('Index: ' + i);
|
const Items = (await (await fetch('https://api.polytoria.com/v1/store?limit=12&order=' + Order + '&sort=' + Sort + '&showOffsale=' + ShowOffsale + '&types[]='+ TabSelected +'&search=' + Search + '&page=' + Page)).json())
|
||||||
return i;
|
PageCount = Items.pages
|
||||||
|
if (Page < PageCount) {
|
||||||
|
document.getElementById('pagination-next').classList.remove('disabled');
|
||||||
|
document.getElementById('pagination-last').classList.remove('disabled');
|
||||||
|
} else {
|
||||||
|
document.getElementById('pagination-next').classList.add('disabled');
|
||||||
|
document.getElementById('pagination-last').classList.add('disabled');
|
||||||
|
}
|
||||||
|
if (Page > 1 && PageCount > 1) {
|
||||||
|
console.log('aaa')
|
||||||
|
console.log(Page > 1, PageCount > 1)
|
||||||
|
document.getElementById('pagination-prev').classList.remove('disabled');
|
||||||
|
document.getElementById('pagination-first').classList.remove('disabled');
|
||||||
|
} else {
|
||||||
|
document.getElementById('pagination-prev').classList.add('disabled');
|
||||||
|
document.getElementById('pagination-first').classList.add('disabled');
|
||||||
|
}
|
||||||
|
document.getElementById('pagination-current').innerText = Page
|
||||||
|
Items.assets.forEach(item => {
|
||||||
|
const ItemColumn = document.createElement('div')
|
||||||
|
ItemColumn.classList = 'col-auto'
|
||||||
|
ItemColumn.innerHTML = `
|
||||||
|
<div style="max-width: 150px;">
|
||||||
|
<div class="card mb-2 avatar-item-container">
|
||||||
|
<div class="p-2">
|
||||||
|
<img src="${item.thumbnail}" class="img-fluid">
|
||||||
|
${ (item.type === 'hat') ? `
|
||||||
|
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
|
||||||
|
<span class="badge bg-secondary">${CleanAccessoryType(item.accessoryType)}</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/${item.id}" class="text-reset">
|
||||||
|
<h6 class="text-truncate mb-0">${item.name}</h6>
|
||||||
|
</a>
|
||||||
|
<small class="text-muted d-block text-truncate">
|
||||||
|
by <a href="/users/${ (["hat", "tool", "face", "torso"].indexOf(item.type) !== -1) ? '1' : item.creator.id }" class="text-reset">${ (["hat", "tool", "face", "torso"].indexOf(item.type) !== -1) ? 'Polytoria' : item.creator.name }</a>
|
||||||
|
</small>
|
||||||
|
<small style="font-size: 0.8rem;" class="d-block text-truncate mb-2
|
||||||
|
${ (item.price === 0) ? 'text-primary fw-bold">Free' : (item.price !== "???") ? 'text-success"><i class="pi mr-1">$</i> ' + item.price : 'text-muted">???</small>' }
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
document.getElementById('inventory').appendChild(ItemColumn)
|
||||||
|
|
||||||
|
ItemCache[item.id] = {
|
||||||
|
type: item.type,
|
||||||
|
name: item.name,
|
||||||
|
price: item.price,
|
||||||
|
creator: {
|
||||||
|
name: item.creator.name,
|
||||||
|
id: item.creator.id
|
||||||
|
},
|
||||||
|
thumbnail: item.thumbnail,
|
||||||
|
asset: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.price === 0) {
|
||||||
|
if (item.sales === 0) {
|
||||||
|
console.log("ITEM IS AWARD-ONLY!!! ", item)
|
||||||
|
ItemCache[item.id].price = null
|
||||||
|
} else {
|
||||||
|
ItemCache[item.id].price = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
|
if (item.type === 'hat') {
|
||||||
|
ItemCache[item.id].accessoryType = item.accessoryType
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemColumn.getElementsByClassName('p-2')[0].addEventListener('click', function(){
|
||||||
|
WearAsset(item)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function LoadWearing() {
|
||||||
|
document.getElementById('wearing').innerHTML = '';
|
||||||
|
[...Avatar.items, Avatar.shirt, Avatar.pants, Avatar.torso].filter((x) => x !== undefined).forEach(id => {
|
||||||
|
const Cached = Object.values(ItemCache)[Object.keys(ItemCache).indexOf(id.toString())]
|
||||||
|
if (Cached !== undefined) {
|
||||||
|
if (Cached.creator === undefined || Cached.creator === null) {
|
||||||
|
Cached.creator = {
|
||||||
|
id: 1,
|
||||||
|
name: "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cached.price === undefined || Cached.price === null) { Cached.price = "???" }
|
||||||
|
|
||||||
|
const ItemColumn = document.createElement('div')
|
||||||
|
ItemColumn.classList = 'col-auto'
|
||||||
|
ItemColumn.innerHTML = `
|
||||||
|
<div style="max-width: 150px;">
|
||||||
|
<div class="card mb-2 avatar-item-container">
|
||||||
|
<div class="p-2">
|
||||||
|
<img src="${Cached.thumbnail}" class="img-fluid">
|
||||||
|
${ (Cached.type === 'hat') ? `
|
||||||
|
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
|
||||||
|
<span class="badge bg-secondary">${CleanAccessoryType(Cached.accessoryType)}</span>
|
||||||
|
</span>
|
||||||
|
` : ''}
|
||||||
|
<button class="avatarAction btn btn-danger btn-sm position-absolute rounded-circle text-center" style="top: -10px; right: -16px; width: 32px; height: 32px; z-index: 1;"><i class="fas fa-minus"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="/store/${id}" class="text-reset">
|
||||||
|
<h6 class="text-truncate mb-0">${Cached.name}</h6>
|
||||||
|
</a>
|
||||||
|
<small class="text-muted d-block text-truncate">
|
||||||
|
by <a href="/users/${Cached.creator.id || "1"}" class="text-reset">${Cached.creator.name || "-"}</a>
|
||||||
|
</small>
|
||||||
|
<small style="font-size: 0.8rem;" class="d-block text-truncate mb-2
|
||||||
|
${ (Cached.price === 0) ? 'text-primary fw-bold">Free' : (Cached.price !== "???") ? 'text-success"><i class="pi mr-1">$</i> ' + Cached.price : 'text-muted">???</small>' }
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
document.getElementById('wearing').appendChild(ItemColumn)
|
||||||
|
|
||||||
|
ItemColumn.getElementsByClassName('p-2')[0].addEventListener('click', function(){
|
||||||
|
WearAsset(Cached)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function WearAsset(details) {
|
||||||
|
const ItemID = Object.keys(ItemCache)[Object.values(ItemCache).indexOf(details)]
|
||||||
|
if (Avatar[details.type] !== details.id && Avatar.items.indexOf(details.id) === -1) {
|
||||||
|
// Equip
|
||||||
|
if (details.type === 'hat') {
|
||||||
|
Avatar.items.push(details.id)
|
||||||
|
} else {
|
||||||
|
Avatar[details.type] = details.id
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unequip
|
||||||
|
if (details.type === 'hat') {
|
||||||
|
Avatar.items.splice(Avatar.items.indexOf(ItemID), 1);
|
||||||
|
} else {
|
||||||
|
Avatar[details.type] = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAvatar()
|
||||||
|
LoadWearing()
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdateBodyColors() {
|
||||||
|
const BodyColors = {
|
||||||
|
head: Avatar.headColor,
|
||||||
|
torso: Avatar.torsoColor,
|
||||||
|
leftArm: Avatar.leftArmColor,
|
||||||
|
rightArm: Avatar.rightArmColor,
|
||||||
|
leftLeg: Avatar.leftLegColor,
|
||||||
|
rightLeg: Avatar.rightLegColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(BodyColors).forEach((elementID, i) => {
|
||||||
|
document.getElementById(elementID).style.backgroundColor = Object.values(BodyColors)[i]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function CleanAccessoryType(type) {
|
||||||
|
const CleanAccessoryTypes = {
|
||||||
|
hat: "Hat",
|
||||||
|
backAccessory: "Back Accessory",
|
||||||
|
faceAccessory: "Face Accessory",
|
||||||
|
headAttachment: "Head Attachment",
|
||||||
|
hair: "Hair",
|
||||||
|
neckAccessory: "Neck Accessory",
|
||||||
|
headCover: "Head Cover",
|
||||||
|
headAccessory: "Head Accessory"
|
||||||
|
}
|
||||||
|
return Object.values(CleanAccessoryTypes)[Object.keys(CleanAccessoryTypes).indexOf(type)] || "!!!"+type
|
||||||
}
|
}
|
||||||
|
|
@ -1,538 +0,0 @@
|
||||||
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');
|
|
||||||
const LoadAssetType = document.getElementById('load-asset-type')
|
|
||||||
LoadAsset.addEventListener('click', async function () {
|
|
||||||
if (!LoadAsset.previousElementSibling.value.startsWith('http') && !LoadAsset.previousElementSibling.value.startsWith('data:')) {
|
|
||||||
if (LoadAssetType.options[LoadAssetType.selectedIndex].value === 'hat') {
|
|
||||||
Avatar.items.push((await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + LoadAsset.previousElementSibling.value)).json()).url);
|
|
||||||
} else {
|
|
||||||
Avatar[LoadAssetType.options[LoadAssetType.selectedIndex].value] = (await (await fetch('https://api.polytoria.com/v1/assets/serve/' + LoadAsset.previousElementSibling.value + '/Asset')).json()).url;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (LoadAssetType.options[LoadAssetType.selectedIndex].value === 'hat') {
|
|
||||||
Avatar.items.push(LoadAsset.previousElementSibling.value);
|
|
||||||
} else {
|
|
||||||
Avatar[LoadAssetType.options[LoadAssetType.selectedIndex].value] = LoadAsset.previousElementSibling.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UpdateAvatar();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const SandboxButton = document.createElement('a');
|
|
||||||
SandboxButton.classList = 'btn btn-outline-success w-100 mt-3';
|
|
||||||
SandboxButton.href = '?sandbox=true';
|
|
||||||
SandboxButton.innerHTML = '<i class="fas fa-shirt"></i> Avatar Sandbox';
|
|
||||||
document.getElementById('cont-move').parentElement.appendChild(SandboxButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
function UpdateAvatar() {
|
|
||||||
FormatAvatar().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 = `
|
|
||||||
<div style="max-width: 150px;">
|
|
||||||
<div class="card mb-2 avatar-item-container">
|
|
||||||
<div class="p-2">
|
|
||||||
<img src="${item.thumbnail}" class="img-fluid">
|
|
||||||
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
|
|
||||||
<span class="badge bg-secondary">${item.type.charAt(0).toUpperCase() + item.type.substring(1)}</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/${item.id}" class="text-reset">
|
|
||||||
<h6 class="text-truncate mb-0">${item.name}</h6>
|
|
||||||
</a>
|
|
||||||
<small class="text-muted d-block text-truncate">
|
|
||||||
by <a href="/users/${item.creator.id}" class="text-reset">${item.creator.name}</a>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
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
|
|
||||||
|
|
||||||
const meshPromises = Avatar.items.map(async (item, index) => {
|
|
||||||
if (typeof item === 'number') {
|
|
||||||
console.log(item);
|
|
||||||
FormattedAvatar.items[index] = await FetchMesh(item)
|
|
||||||
console.log('after url');
|
|
||||||
//Avatar.items[index] = URL
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Avatar.items.forEach(async (item, index) => {
|
|
||||||
if (typeof item === 'number') {
|
|
||||||
console.log(item);
|
|
||||||
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 && typeof FormattedAvatar.face === 'number') {
|
|
||||||
FormattedAvatar.face = await FetchAsset(FormattedAvatar.face);
|
|
||||||
} else if (FormattedAvatar.face === undefined) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(meshPromises)
|
|
||||||
|
|
||||||
console.log('Real Avatar: ', Avatar)
|
|
||||||
console.log('Formatted: ', FormattedAvatar)
|
|
||||||
console.log('URI: ', btoa(encodeURIComponent(JSON.stringify(FormattedAvatar))))
|
|
||||||
console.log('Fix: ', JSON.stringify(decodeURIComponent(atob(btoa(encodeURIComponent(JSON.stringify(FormattedAvatar)))))));
|
|
||||||
return btoa(encodeURIComponent(JSON.stringify(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 new Promise((resolve, reject) => {
|
|
||||||
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);
|
|
||||||
resolve(data.url);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log('Fetch error: ' + error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
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 = `
|
|
||||||
<div style="max-width: 150px;">
|
|
||||||
<div class="card mb-2 avatar-item-container">
|
|
||||||
<div class="p-2">
|
|
||||||
<img src="${item.thumbnail}" class="img-fluid">
|
|
||||||
<span class="position-absolute" style="top: 5px; left: 5px; z-index: 1;">
|
|
||||||
<span class="badge bg-secondary">${item.type.charAt(0).toUpperCase() + item.type.substring(1)}</span>
|
|
||||||
</span>
|
|
||||||
<button class="avatarAction btn btn-danger btn-sm position-absolute rounded-circle text-center" style="top: -10px; right: -16px; width: 32px; height: 32px; z-index: 1;"><i class="fas fa-minus"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="/store/${item.id}" class="text-reset">
|
|
||||||
<h6 class="text-truncate mb-0">${item.name}</h6>
|
|
||||||
</a>
|
|
||||||
<small class="text-muted d-block text-truncate">
|
|
||||||
by <a href="/users/${item.creator.id}" class="text-reset">${item.creator.name}</a>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
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.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -100,7 +100,7 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
"matches": ["https://polytoria.com/my/avatar*"],
|
"matches": ["https://polytoria.com/my/avatar*"],
|
||||||
"js": ["/js/account/avatar-sandbox-rewrite.js"]
|
"js": ["/js/account/avatar-sandbox.js"]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Reference in a new issue