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-sandbox2.js
StarManTheGamer ff6c26cb0a Revert "chore: format code with Prettier"
This reverts commit cc39111694.
2024-05-27 17:16:58 -05:00

488 lines
No EOL
17 KiB
JavaScript
Executable file

const UserID = JSON.parse(window.localStorage.getItem('p+account_info')).ID
const BodyColors = [
"#f8f8f8",
"#cdcdcd",
"#111111",
"#ff0000",
"#a34b4b",
"#ffc9c9",
"#957977",
"#c4281c",
"#da867a",
"#694028",
"#cc8e69",
"#a05f35",
"#7c5c46",
"#eab892",
"#da8541",
"#aa5500",
"#ffcc99",
"#e29b40",
"#ffaf00",
"#ffb000",
"#d7c59a",
"#f5cd30",
"#fdea8d",
"#e5e4df",
"#c1be42",
"#ffff00",
"#ffffcc",
"#a4bd47",
"#7f8e64",
"#a1c48c",
"#3a7d15",
"#4b974b",
"#00ff00",
"#ccffcc",
"#27462d",
"#287f47",
"#789082",
"#9ff3e9",
"#12eed4",
"#f2f3f3",
"#00ffff",
"#008f9c",
"#04afec",
"#80bbdb",
"#b4d2e4",
"#0d69ac",
"#1b2a35",
"#afddff",
"#6e99ca",
"#74869d",
"#2154b9",
"#002060",
"#0000ff",
"#b1a7ff",
"#a3a2a5",
"#6225d1",
"#b480ff",
"#8c5b9f",
"#6b327c",
"#aa00aa",
"#635f62",
"#ff00bf",
"#ff66cc",
"#e8bac8"
]
let PageContainer = document.querySelector('.container.p-0.p-lg-5')
let ItemGrid;
let Wearing;
let Tabs;
let IFrame;
let TabSelected = 'hat'
let Search;
let Page = 1
let Avatar = {
"useCharacter": true,
"items": [
24122
],
"shirt": 24118,
"pants": 24123,
"headColor": "#e0e0e0",
"torsoColor": "#e0e0e0",
"leftArmColor": "#e0e0e0",
"rightArmColor": "#e0e0e0",
"leftLegColor": "#e0e0e0",
"rightLegColor": "#e0e0e0"
}
if (new URLSearchParams(window.location.search).has('sandbox')) {
console.log('Avatar Sandbox!')
LoadFile(chrome.runtime.getURL('resources/avatar-sandbox.html'), function(html){
PageContainer.innerHTML = html
ItemGrid = document.getElementById('inventory')
Wearing = document.getElementById('wearing')
Tabs = document.getElementById('tabs')
IFrame = document.getElementById('viewFrame')
Search = document.getElementById('item-search')
Search.addEventListener('onchange', function(){
RefreshItems()
});
UpdateAvatar()
RefreshItems()
LoadWearing()
Array.from(Tabs.children).forEach(element => {
element.addEventListener('click', function(){
let Link = element.getElementsByTagName('a')[0]
if (!(Link.classList.contains('active'))) {
Link.classList.add('active')
Tabs.querySelector(`[data-tab="${TabSelected}"]`).classList.remove('active')
TabSelected = Link.getAttribute('data-tab')
Page = 1
RefreshItems()
}
});
});
let Clear = document.getElementById('clear')
Clear.addEventListener('click', function(){
Avatar = {
"useCharacter": true,
"items": [
24122
],
"shirt": 24118,
"pants": 24123,
"headColor": "#e0e0e0",
"torsoColor": "#e0e0e0",
"leftArmColor": "#e0e0e0",
"rightArmColor": "#e0e0e0",
"leftLegColor": "#e0e0e0",
"rightLegColor": "#e0e0e0"
}
UpdateAvatar()
});
let Myself = document.getElementById('myself')
Myself.addEventListener('click', function(){
LoadMyself()
});
let JSONUpload = document.getElementById('jsonUpload')
JSONUpload.addEventListener('change', function(){
let Reader = new FileReader()
Reader.addEventListener('loadend', function(){
Avatar = JSON.parse(Reader.result)
UpdateAvatar()
JSONUpload.value = ""
});
Reader.readAsText(JSONUpload.files[0])
});
let JSONSave = document.getElementById('jsonSave')
JSONSave.addEventListener('click', function(){
let Download = document.createElement('a')
Download.href = URL.createObjectURL(new Blob([JSON.stringify(Avatar)], {
type: "application/json"
}));
Download.setAttribute('download', 'AvatarSandbox.json')
document.body.appendChild(Download)
Download.click()
document.body.removeChild(Download)
});
let OpenInNewTab = document.getElementById('openNewTab')
OpenInNewTab.addEventListener('click', function(){
UpdateAvatar()
});
let LoadAsset = document.getElementById('load-asset')
LoadAsset.addEventListener('click', async function(){
console.log('clickk')
const MeshURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + LoadAsset.previousElementSibling.value)).json()).url
Avatar.items.push(MeshURL)
UpdateAvatar()
})
});
} else {
const SandboxButton = document.createElement('a')
SandboxButton.classList = 'btn btn-outline-success w-100 mt-3'
SandboxButton.href = '?sandbox=true'
SandboxButton.innerHTML = '<i class="fas fa-shirt"></i> Avatar Sandbox'
document.getElementById('cont-move').parentElement.appendChild(SandboxButton)
}
function UpdateAvatar() {
GenerateHash()
.then(hash => {
IFrame.addEventListener('load', function () {
IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + hash;
});
IFrame.src = 'about:blank';
});
}
function LoadFile(path, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () { return callback(this.responseText); }
xhr.open("GET", path, true);
xhr.send();
}
async function GenerateHash(data) {
if (!data) {
console.log('Data not provided')
let FormattedAvatar = await FormatAvatar()
return btoa(encodeURIComponent(JSON.stringify(FormattedAvatar)))
} else {
console.log('Data provided')
return btoa(encodeURIComponent(JSON.stringify(data)))
}
}
function RefreshItems() {
fetch(`https://api.polytoria.com/v1/store?search=${Search.value}&types%5B%5D=${TabSelected}&sort=createdAt&order=desc&page=${Page}&limit=12`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
Array.from(ItemGrid.children).forEach(element => {element.remove()});
data = data.assets
data.forEach(item => {
let NewItemCard = document.createElement('div')
NewItemCard.setAttribute('data-id', item.id)
NewItemCard.classList = 'col-auto'
NewItemCard.innerHTML = `
<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
Avatar.items.forEach(async (item, index) => {
if (typeof(item) === 'number') {
console.log(item)
await FetchMesh(item)
.then(URL => {
console.log('URL: ' + URL)
FormattedAvatar.items[index] = URL
})
.catch(error => {
throw new Error(error)
});
console.log('after url')
//Avatar.items[index] = URL
}
});
if (typeof(FormattedAvatar.tool) === 'number') {console.log(FormattedAvatar.tool); FormattedAvatar.tool = await FetchMesh(FormattedAvatar.tool)}
if (FormattedAvatar.face && typeof(FormattedAvatar.face) === 'number') {
FormattedAvatar.face = await FetchAsset(FormattedAvatar.face)
} else {
FormattedAvatar.face = "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
}
if (typeof(FormattedAvatar.shirt) === 'number') {FormattedAvatar.shirt = await FetchAsset(FormattedAvatar.shirt)}
if (typeof(FormattedAvatar.pants) === 'number') {FormattedAvatar.pants = await FetchAsset(FormattedAvatar.pants)}
console.log('Real Avatar: ', Avatar, 'Formatted: ', FormattedAvatar)
return FormattedAvatar
}
function LoadMyself() {
fetch('https://api.polytoria.com/v1/users/:id/avatar'.replace(':id', UserID))
.then(response => {
if (!response.ok) {
throw new Error('Network not ok')
}
return response.json()
})
.then(data => {
Avatar.items = []
data.assets.forEach(item => {
switch(item.type) {
case 'hat':
Avatar.items.push(item.id)
break
default:
Avatar[item.type] = item.id
break
}
});
Avatar.headColor = '#' + data.colors.head || '#cdcdcd'
Avatar.torsoColor = '#' + data.colors.torso || '#cdcdcd'
Avatar.leftArmColor = '#' + data.colors.leftArm || '#cdcdcd'
Avatar.rightArmColor = '#' + data.colors.rightArm || '#cdcdcd'
Avatar.leftLegColor = '#' + data.colors.leftLeg || '#cdcdcd'
Avatar.rightLegColor = '#' + data.colors.rightLeg || '#cdcdcd'
UpdateAvatar()
})
.catch(error => {
console.log(error)
});
}
function WearAsset(element, info) {
if (Avatar.items.indexOf(info.id) === -1 && Avatar[info.type] !== info.id) {
console.log('Equip', info)
switch(info.type) {
case 'hat':
Avatar.items.push(info.id)
break
default:
Avatar[info.type] = info.id
break
}
} else {
console.log('unequip', info)
switch(info.type) {
case 'hat':
Avatar.items.splice(Avatar.items.indexOf(info.id), 1)
break
case 'face':
Avatar.face = "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
break
default:
Avatar[info.type] = undefined
break
}
}
const ToggleButton = element.getElementsByClassName('avatarAction')[0]
ToggleButton.classList.toggle('btn-success')
ToggleButton.classList.toggle('btn-danger')
ToggleButton.children[0].classList.toggle('fa-plus')
ToggleButton.children[0].classList.toggle('fa-minus')
const Duplicate = ItemGrid.querySelector(`[data-id="${info.id}"]`)
if (Duplicate !== null && Duplicate !== element) {
const DuplicateToggleButton = Duplicate.getElementsByClassName('avatarAction')[0]
DuplicateToggleButton.classList.toggle('btn-success')
DuplicateToggleButton.classList.toggle('btn-danger')
DuplicateToggleButton.children[0].classList.toggle('fa-plus')
DuplicateToggleButton.children[0].classList.toggle('fa-minus')
}
LoadWearing()
UpdateAvatar()
}
async function FetchMesh(id) {
if (id === null) {return null}
console.log('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', id))
return fetch('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', id))
.then(response => {
if (!response.ok) {
throw new Error('Network not ok')
}
return response.json()
})
.then(data => {
console.log(data, 'finished', data.url)
return data.url
})
.catch(error => {
console.log('Fetch error: ' + error)
});
}
async function FetchAsset(id) {
if (id === null) {return null}
return fetch('https://api.polytoria.com/v1/assets/serve/:id/Asset'.replace(':id', id))
.then(response => {
if (!response.ok) {
throw new Error('Network not ok')
}
return response.json()
})
.then(data => {
return data.url
})
.catch(error => {
console.log('Fetch error: ' + error)
});
}
function LoadWearing() {
const WearingItems = [
...Avatar.items,
Avatar.shirt,
Avatar.pants,
Avatar.face
].filter(item => item !== null && item !== undefined);
Array.from(Wearing.children).forEach(element => {
const ItemID = element.getElementsByTagName('a')[0].href.split('/')[2]
if (!WearingItems.includes(ItemID)) {
element.remove();
}
});
WearingItems.forEach(item => {
const ExistingElement = Wearing.querySelector(`[data-itemid="${item}"]`);
if (!ExistingElement) {
fetch(`https://api.polytoria.com/v1/store/${item}`)
.then(response => {
if (!response.ok) {
throw new Error('Network not ok');
}
return response.json();
})
.then(item => {
if (Wearing.innerHTML === 'No items to show.') {
Wearing.innerHTML = ''
}
let NewItemCard = document.createElement('div');
NewItemCard.setAttribute('data-id', item.id)
NewItemCard.classList = 'col-auto';
NewItemCard.innerHTML = `
<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.'
}
}