diff --git a/css/settings.css b/css/settings.css new file mode 100644 index 0000000..53c126b --- /dev/null +++ b/css/settings.css @@ -0,0 +1,176 @@ +html, +body, +#page { + background: #202020; + color: #fff; +} + +#page { + margin-top: 7.5rem; + width: 65%; + margin-right: auto; + margin-left: auto; + margin-bottom: 3.5rem; +} + +h1 { + font-size: 4.6rem; + /*color: rgb(48, 48, 48);*/ +} + +h1 span.indent { + border-left: 10px solid rgb(48, 48, 48); + margin-right: 15px; +} + +h1 span.highlight { + color: red; +} + +h2 { + color: rgb(48, 48, 48); +} + +h2 span.indent { + border-left: 7.5px solid rgb(48, 48, 48); + margin-right: 15px; +} + +.setting-container:not(:last-child) { + margin-bottom: 20px; +} + +.setting-container .title { + font-size: 1.4rem; + font-weight: lighter; +} + +.setting-container .desc { + color: rgb(120, 120, 120); +} + +.goback { + color: rgb(120, 120, 120); + text-decoration: none; +} + +dialog { + background-color: #080808; + color: #c4c4c4; + border: 1px solid #3bafff; + border-radius: 10px; +} + +.input-group-text { + background-color: #000; + border-color: #000; + color: #fff; +} + +label { + font-size: 0.8rem; + margin-bottom: 2.75px; +} + +dialog::backdrop { + background-color: rgba(0, 0, 0, 0.73); +} + +dialog .modal-header p { + margin-bottom: 0px; + color: #fff; +} + +dialog .modal-body p:first-child { + font-size: 0.9rem; +} + +.setting-container .indicator { + border-radius: 5rem; + display: inline-block; + cursor: default; +} + +.setting-container.enabled .indicator { + background-color: #007bff; +} + +.setting-container.disabled .indicator { + background-color: orangered; +} + +.toggle-btn { + float: right; + width: 100px; +} + +.limited-time { + background: transparent; + border-color: transparent; + box-shadow: -3px -3px 15px 0 rgba(255, 116, 16, 0.25) inset, 3px 3px 15px 0 rgba(205, 96, 255, 0.25) inset; +} + +.limited-time * { + position: relative; + z-index: 2; +} + +.limited-time .row { + --bs-gutter-x: 10px; +} + +.limited-time .indicator { + height: 100%; +} + +.limited-time .desc { + margin-bottom: 10px; + width: 85%; +} + +.limited-time-tag { + font-size: 0.7rem; + color: rgba(255, 116, 16, 0.25); + + -webkit-animation: LimitedTimeTag 5s ease infinite alternate; + -moz-animation: LimitedTimeTag 5s ease infinite alternate; + animation: LimitedTimeTag 5s ease infinite alternate; +} + +.limited-time::before { + content: ''; + position: absolute; + inset: 0; + padding: 3px; + background: + linear-gradient( + 45deg, + rgba(255, 116, 16, 1), + rgba(205, 96, 255, 1) + ); + -webkit-mask: + linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + display: block; + border-radius: inherit; +} + +@-webkit-keyframes LimitedTimeTag { + 0%{color:rgba(255, 116, 16, 1);} + 50%{color:rgba(23, 107, 233, 1);} + 100%{color:rgba(205, 96, 255, 1);} +} + +@-moz-keyframes LimitedTimeTag { + 0%{color:rgba(255, 116, 16, 1);} + 50%{color:rgba(23, 107, 233, 1);} + 100%{color:rgba(205, 96, 255, 1);} +} + +@keyframes LimitedTimeTag { + 0%{color:rgba(255, 116, 16, 1);} + 50%{color:rgba(23, 107, 233, 1);} + 100%{color:rgba(205, 96, 255, 1);} +} \ No newline at end of file diff --git a/css/specific.css b/css/specific.css index 663fa0c..420cb0b 100755 --- a/css/specific.css +++ b/css/specific.css @@ -20,6 +20,10 @@ body[data-URL^='/create/'] .col.d-flex.align-content-between.flex-wrap { text-overflow: ellipsis !important; } +#servers-tabpane .card { + margin-bottom: 10px; +} + /* ------------------------------------------ */ /* @@ -56,3 +60,35 @@ body:has(.polyplus-modal[open]) { } /* ------------------------------------------ */ + + +/* + EVENT PLACE CARD HIGHLIGHT ANIMATION + CSS BY @Dragonism ON POLYTORIA +*/ + +.event-card { + background-size: 200% 200% !important; + + -webkit-animation: EventPlace 5s ease infinite; + -moz-animation: EventPlace 5s ease infinite; + animation: EventPlace 5s ease infinite; +} + +@-webkit-keyframes EventPlace { + 0%{background-position:10% 0%} + 50%{background-position:91% 100%} + 100%{background-position:10% 0%} +} + +@-moz-keyframes EventPlace { + 0%{background-position:10% 0%} + 50%{background-position:91% 100%} + 100%{background-position:10% 0%} +} + +@keyframes EventPlace { + 0%{background-position:10% 0%} + 50%{background-position:91% 100%} + 100%{background-position:10% 0%} +} \ No newline at end of file diff --git a/js/account/home.js b/js/account/home.js index 44a6644..992247c 100755 --- a/js/account/home.js +++ b/js/account/home.js @@ -65,7 +65,7 @@ var FriendContainer = document.querySelector('.card:has(.friendsPopup) .card-bod let NewContainer = document.createElement('div'); NewContainer.style.display = 'none'; -NewContainer.classList = 'card card-dash mcard'; +NewContainer.classList = 'card card-dash mcard mb-3'; NewContainer.style.animationDelay = '0.18s'; NewContainer.innerHTML = ContainerElement; @@ -87,7 +87,7 @@ FriendContainer.prepend(BestFriendsContainer); async function Update() { chrome.storage.sync.get(['PolyPlus_PinnedGames'], function (result) { - PinnedGamesData = result.PolyPlus_PinnedGames || []; + PinnedGamesData = result.PolyPlus_PinnedGames.toSorted((a, b) => b - a) || []; if (Settings.PinnedGamesOn === true) { PinnedGames(); @@ -123,7 +123,7 @@ function PinnedGames() { NewTitle.style.display = ''; } - PinnedGamesData.forEach((element) => { + for (let element of PinnedGamesData) { fetch('https://api.polytoria.com/v1/places/' + element) .then((response) => response.json()) .then((data) => { @@ -148,7 +148,7 @@ function PinnedGames() { .catch((error) => { console.error('Error:', error); }); - }); + } } function BestFriends() { @@ -180,8 +180,13 @@ function BestFriends() { } var SecondaryColumn = document.getElementsByClassName('col-lg-8')[0]; -SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[0]); -SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[0]); +if (document.getElementsByClassName('home-event-container')[0] === undefined) { + SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[0]); + SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[0]); +} else { + SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[1]); + SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[1]); +} async function IRLPrice() { (async () => { diff --git a/js/account/outfit-overwrite.js b/js/account/outfit-overwrite.js new file mode 100644 index 0000000..e69de29 diff --git a/js/account/profile.js b/js/account/profile.js index 7eee982..fd4f4a9 100755 --- a/js/account/profile.js +++ b/js/account/profile.js @@ -6,6 +6,7 @@ var Settings; var BestFriends; let FavoriteBtn; let CalculateButton; +let AvatarIFrame; let Utilities; @@ -18,6 +19,34 @@ if (Username) { chrome.storage.sync.get(['PolyPlus_Settings'], function (result) { Settings = result.PolyPlus_Settings || {}; + const InfoColumns = document.getElementById('user-stats-card'); + const UserIDRow = document.createElement('div') + UserIDRow.classList = 'mb-1' + UserIDRow.innerHTML = ` + Player ID + + ${UserID} + + ` + InfoColumns.children[0].insertBefore(UserIDRow, InfoColumns.children[0].children[1]); + + const CopyButton = UserIDRow.getElementsByTagName('a')[0] + CopyButton.addEventListener('click', function(){ + navigator.clipboard + .writeText(UserID) + .then(() => { + CopyButton.classList.add('text-success') + CopyButton.children[0].classList = 'fa-duotone fa-circle-check' + CopyButton.children[0].style.marginLeft = '3px' + + setTimeout(() => { + CopyButton.classList.remove('text-success') + CopyButton.children[0].classList = 'fad fa-copy' + CopyButton.children[0].style.marginLeft = '5px' + }, 1500); + }) + }) + if (Settings.IRLPriceWithCurrency && Settings.IRLPriceWithCurrency.Enabled === true) { IRLPrice(); } @@ -49,10 +78,55 @@ if (Username) { } }); } + + /* + + + + */ + + AvatarIFrame = document.getElementById('user-avatar-card').getElementsByTagName('iframe')[0] + if (Settings.AvatarDimensionToggleOn === true || 1 === 1) { + const AvatarCard = document.getElementById('user-avatar-card') + const ToggleButton = document.createElement('button') + ToggleButton.classList = 'btn btn-primary btn-sm 3dviewtoggler isactive' + ToggleButton.style = 'position: absolute; right: 15px; margin: 10px;' + ToggleButton.innerHTML = '' + AvatarCard.children[0].insertBefore(ToggleButton, AvatarIFrame) + + ToggleButton.addEventListener('click', async function(){ + if (ToggleButton.children[0].classList.contains('fa-image')) { + if (document.getElementById('polyplus-2davatar')) { + AvatarIFrame.style.display = 'none' + document.getElementById('polyplus-2davatar').style.display = 'block' + ToggleButton.children[0].classList = 'toggleIcn fad fa-360-degrees' + } else { + const AvatarImage = document.createElement('img') + AvatarImage.id = 'polyplus-2davatar' + AvatarImage.width = AvatarIFrame.offsetWidth + AvatarImage.height = AvatarIFrame.offsetHeight + + const UserDetails = (await (await fetch('https://api.polytoria.com/v1/users/' + UserID)).json()) + AvatarImage.src = UserDetails.thumbnail.avatar + + AvatarIFrame.style.display = 'none' + AvatarCard.children[0].insertBefore(AvatarImage, AvatarCard.getElementsByClassName('user-badges')[0]) + + ToggleButton.children[0].classList = 'toggleIcn fad fa-360-degrees' + } + } else { + document.getElementById('polyplus-2davatar').style.display = 'none' + AvatarIFrame.style.display = 'block' + ToggleButton.children[0].classList = 'toggleIcn fad fa-image' + } + }) + } }); })(); - const AvatarIFrame = document.querySelector('[src^="/ptstatic"]'); + if (AvatarIFrame === null) { + AvatarIFrame = document.getElementById('user-avatar-card').getElementsByTagName('iframe')[0] + } const DropdownMenu = document.getElementsByClassName('dropdown-menu dropdown-menu-right')[0]; const CopyItem = document.createElement('a'); diff --git a/js/background.js b/js/background.js index 3a2ede9..738f63e 100755 --- a/js/background.js +++ b/js/background.js @@ -78,9 +78,12 @@ const DefaultSettings = { Banners: true, Rectangles: true }, - UploadMultipleDecals: true + UploadMultipleDecals: true, + GD_ServerBalanceOn: true, + AvatarDimensionToggleOn: true } +// ON EXTENSION INSTALL / RELOAD chrome.runtime.onInstalled.addListener(() => { chrome.storage.sync.get(['PolyPlus_Settings'], function(result){ const MergedSettings = MergeObjects((result.PolyPlus_Settings || DefaultSettings), DefaultSettings) @@ -90,6 +93,23 @@ chrome.runtime.onInstalled.addListener(() => { }) }); +chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { + if (request.action === 'reload') { + chrome.runtime.reload(); + } else if (request.action === 'sweetalert2') { + chrome.tabs.query({ active: true, currentWindow: true }, function(tabs){ + console.log([request.icon, request.title, request.text]) + chrome.scripting + .executeScript({ + target: {tabId: tabs[0].id}, + func: OpenSweetAlert2Modal, + // would have just let it pass thru the object for sweetalert2 - but probably not a good idea lol + args: [request.icon, request.title, request.text] + }) + }) + } +}); + // WHEN CLICKING ON EXTENSION ICON OPEN THE SETTINGS PAGE chrome.action.onClicked.addListener((tab) => { chrome.tabs.create({active: true, url: SettingsURL}); @@ -168,7 +188,9 @@ chrome.contextMenus.removeAll(function () { title: 'Run Update Notifier', id: 'PolyPlus-RunUpdateNotifier', contexts: ['all'], - documentUrlPatterns: ['https://polytoria.com/my/settings/polyplus*'] + documentUrlPatterns: [ + 'https://polytoria.com/my/settings/polyplus*' + ] }); // COPY ASSET ID CONTEXT MENU ITEM REGISTRATION @@ -177,7 +199,13 @@ chrome.contextMenus.removeAll(function () { id: 'PolyPlus-CopyID', contexts: ['link'], documentUrlPatterns: ['https://polytoria.com/*', SettingsURL], - targetUrlPatterns: ['https://polytoria.com/places/**', 'https://polytoria.com/users/**', 'https://polytoria.com/u/**', 'https://polytoria.com/store/**', 'https://polytoria.com/guilds/**'] + targetUrlPatterns: [ + 'https://polytoria.com/places/**', + 'https://polytoria.com/users/**', + 'https://polytoria.com/u/**', + 'https://polytoria.com/store/**', + 'https://polytoria.com/guilds/**' + ] }); // COPY AVATAR HASH CONTEXT MENU ITEM REGISTRATION @@ -186,7 +214,9 @@ chrome.contextMenus.removeAll(function () { id: 'PolyPlus-CopyAvatarHash', contexts: ['image'], documentUrlPatterns: ['https://polytoria.com/*', SettingsURL], - targetUrlPatterns: ['https://c0.ptacdn.com/thumbnails/avatars/**', 'https://c0.ptacdn.com/thumbnails/avatars/**'] + targetUrlPatterns: [ + 'https://c0.ptacdn.com/thumbnails/avatars/**' + ] }); }); @@ -236,18 +266,18 @@ chrome.tabs.onActivated.addListener(function (info){ }); function CheckIfScriptApplies(url) { - return Manifest.content_scripts.forEach(script => { - COMMENT - if (matchesUrl(script.matches, url)) { - return true - } - + const matches = Manifest.content_scripts.map(script => { script.matches.forEach(match => { - if (url.startsWith(match.replaceAll('*', ''))) { + console.log(url, match, url.startsWith(match)) + if (url.startsWith(match)) { return true - } + } else { + return false + } }) }) + + return matches } function matchesUrl(patterns, url) { @@ -260,11 +290,8 @@ function matchesUrl(patterns, url) { function CopyAssetID(id) { navigator.clipboard .writeText(id) - .then(() => { - alert('Successfully copied ID!'); - }) - .catch(() => { - alert('Failure to copy ID.'); + .catch((err) => { + alert('Failure to copy ID.', err); }); } @@ -279,6 +306,15 @@ function CopyAvatarHash(hash) { }); } +function OpenSweetAlert2Modal(icon, title, text) { + console.log(window, window.Swal, window.bootstrap) + window.Swal.fire({ + icon: icon, + title: title, + text: text + }) +} + // MergeObjects function was written by ChatGPT cause I was lazy and it was awhile ago function MergeObjects(obj1, obj2) { var mergedObj = {}; @@ -296,10 +332,4 @@ function MergeObjects(obj1, obj2) { } return mergedObj; -} - -chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { - if (request.action === 'reload') { - chrome.runtime.reload(); - } -}); \ No newline at end of file +} \ No newline at end of file diff --git a/js/library-download.js b/js/library-download.js index 432e761..021fea5 100644 --- a/js/library-download.js +++ b/js/library-download.js @@ -2,7 +2,7 @@ const AssetID = window.location.pathname.split('/')[2]; const LibraryType = document.querySelectorAll('ol a')[1].innerText.toLowerCase(); const LibraryTypes = ['model', 'audio', 'decal', 'mesh', 'shirt', 'pant']; -if (LibraryTypes.filter((x) => !LibraryTypes.some(element => element.startsWith(LibraryType))).length > 0) { +if (LibraryTypes.some(element => element.startsWith(LibraryType))) { chrome.storage.sync.get(['PolyPlus_Settings'], async function (result) { Settings = result.PolyPlus_Settings || {}; diff --git a/js/places/place-edit.js b/js/places/place-edit.js index cc3b323..0fc7339 100755 --- a/js/places/place-edit.js +++ b/js/places/place-edit.js @@ -35,28 +35,16 @@ async function ActivityToggle() { ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate'; DIV.appendChild(ActivityBtn); - ActivityBtn.addEventListener('click', function () { - fetch(`https://polytoria.com/api/places/${PlaceID}/toggle-active`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value - } - }) - .then((response) => { - if (!response.ok) { - throw new Error('Network not ok ' + response.status); - } - return response.json(); - }) - .then((data) => { - Status = data.isActive; - ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate'; - ActivityBtn.classList = 'btn ' + (Status === true ? 'btn-danger' : 'btn-success'); - }) - .catch((error) => { - console.log(error); - }); + ActivityBtn.addEventListener('click', async function () { + const Toggle = (await (await fetch(`https://polytoria.com/api/places/${PlaceID}/toggle-active`,{ method: 'POST' })).json()) + console.log(Toggle) + if (Toggle.success) { + Status = data.isActive; + ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate'; + ActivityBtn.classList = 'btn ' + (Status === true ? 'btn-danger' : 'btn-success'); + } else { + chrome.runtime.sendMessage({ action: "sweetalert2", icon: "error", title: "Error", text: Toggle.message }); + } }); } @@ -93,7 +81,6 @@ function RequestGameProfile() { } async function CopyOwnedPlace() { - console.log('ran function'); if (PlaceData === null) { PlaceData = await fetch('https://api.polytoria.com/v1/places/' + PlaceID); PlaceData = await PlaceData.json(); @@ -122,11 +109,6 @@ async function CopyOwnedPlace() { let CreatorToken = await fetch('https://polytoria.com/api/places/edit', { method: 'POST', - /* - headers: { - 'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value - }, - */ body: JSON.stringify({placeID: PlaceID}) }); CreatorToken = await CreatorToken.json(); @@ -144,7 +126,6 @@ async function CopyOwnedPlace() { return response.blob(); }) .then((data) => { - //const JSONBlob = new Blob([data], {type: "application/xml"}) const DownloadURL = URL.createObjectURL(data); const Link = document.createElement('a'); diff --git a/js/places/place-view.js b/js/places/place-view.js index b0ec5d7..bbaf081 100644 --- a/js/places/place-view.js +++ b/js/places/place-view.js @@ -50,6 +50,10 @@ const Gamepasses = Array.from(GamepassesTab.getElementsByClassName('card')) || [ Utilities = await import(chrome.runtime.getURL('resources/utils.js')); Utilities = Utilities.default; + if (Settings.GD_ServerBalanceOn && PlaceID === '9656') { + TheGreatDivide() + } + if (Settings.PinnedGamesOn === true) { PinnedGames(); } @@ -426,7 +430,7 @@ async function PlaceRevenue() { const ResultText = document.createElement('li'); ResultText.classList = 'fw-normal text-success'; ResultText.style.letterSpacing = '0px'; - ResultText.innerHTML = ` ~` + Revenue.toLocaleString(); + ResultText.innerHTML = ` ~` + Revenue.toLocaleString() + ' '; CalculateRevenueButton.remove(); InfoColumns[1].appendChild(ResultText); @@ -513,3 +517,36 @@ function GetAchievementDifficulty(percent) { return 'Impossible'; } } + +// Temp Feature for The Great Divide event +async function TheGreatDivide() { + const Team = (await (await fetch('https://api.polytoria.com/v1/users/' + UserID + '/greatdivide')).json()).team + if (Team !== undefined) { + const Servers = Array.from(document.getElementById('servers-tabpane').children) + + Servers.forEach(server => { + const TeamCounts = { + phantoms: server.getElementsByClassName('border-phantoms').length, + cobras: server.getElementsByClassName('border-cobras').length + } + + let Enemy = "cobras" + if (Team === "cobras") { Enemy = "phantoms" } + + if (TeamCounts[Team] < TeamCounts[Enemy]) { + console.log(server.getElementsByTagName('button')[0]) + const UnbalancedText = document.createElement('p') + UnbalancedText.classList = 'mb-2' + UnbalancedText.style.fontSize = '0.7rem' + UnbalancedText.style.color = 'orange' + UnbalancedText.innerHTML = `*Potentially Unbalanced ` + + const ServerInfoColumn = server.getElementsByClassName('col-3')[0] + ServerInfoColumn.children[0].style.marginBottom = '0px' + ServerInfoColumn.insertBefore(UnbalancedText, ServerInfoColumn.children[1]) + + Utilities.InjectResource("registerTooltips") + } + }) + } +} \ No newline at end of file diff --git a/js/sitewide.js b/js/sitewide.js index 3b34069..d54f586 100755 --- a/js/sitewide.js +++ b/js/sitewide.js @@ -112,12 +112,11 @@ let Theme = ``; } }); - const combination = "reload"; let currentCombination = ""; document.addEventListener("keypress", function(e) { currentCombination += e.key; - if (currentCombination === combination && document.activeElement.tagName !== "INPUT") { + if (currentCombination === combination && document.activeElement.tagName !== "INPUT" && document.activeElement.tagName !== "TEXTAREA") { console.log("Reloading Poly+..."); chrome.runtime.sendMessage({ action: "reload" }); window.location.reload(); diff --git a/js/store/item-view.js b/js/store/item-view.js index 9b9aa02..af8e093 100755 --- a/js/store/item-view.js +++ b/js/store/item-view.js @@ -44,12 +44,14 @@ var Utilities; } if (Settings.ReplaceItemSalesOn === true) { - const Sales = document.querySelectorAll('.col:has(h6):has(h3.small)')[2]; + const Sales = document.querySelectorAll('.col:has(h6):has(h3.small)')[3]; if (Sales.children[1].innerText === '0') { InitialOwners = await (await fetch('https://api.polytoria.com/v1/store/' + ItemID + '/owners?limit=100')).json(); - Sales.children[0].innerText = 'Owners'; - Sales.children[1].innerText = Owners.total.toLocaleString(); + Sales.children[0].innerHTML = `Owners `; + Sales.children[1].innerText = InitialOwners.total.toLocaleString(); + + Utilities.InjectResource("registerTooltips") } } @@ -267,15 +269,12 @@ function TryOnItems() { .then((data) => { switch (AssetType) { case 'Shirt': - console.log('IS SHIRT'); Avatar.shirt = data.url; break; case 'Pants': - console.log('IS PANTS'); Avatar.pants = data.url; break; case 'Face': - console.log('IS FACE'); Avatar.face = data.url; break; } @@ -301,7 +300,7 @@ function TryOnItems() {
Preview
- Try this avatar on your avatar before purchasing it! + Try this item on your avatar before purchasing it!
diff --git a/popup.html b/popup.html new file mode 100644 index 0000000..efe656b --- /dev/null +++ b/popup.html @@ -0,0 +1,25 @@ + + + + + + + + + Poly+ Settings + + + + + +
+ extract texture from item +
+
+ + +
+
+ + + \ No newline at end of file diff --git a/popup.js b/popup.js new file mode 100644 index 0000000..7eb6460 --- /dev/null +++ b/popup.js @@ -0,0 +1,87 @@ +/* + ParseGLB & GetTexture function code made by ChatGPT (I didn't want to use external libraries because of storage space) +*/ + +const ExtractButton = document.getElementById('extract-texture') + +ExtractButton.addEventListener('click', async function(){ + const MeshURL = (await (await fetch('https://api.polytoria.com/v1/assets/serve-mesh/' + ExtractButton.previousElementSibling.value)).json()).url + + if (MeshURL !== undefined) { + const Mesh = (await (await fetch(MeshURL)).arrayBuffer()) + const ParsedGTLF = ParseGLB(Mesh) + + const Texture = GetTexture(ParsedGTLF); + if (Texture) { + const DownloadLink = document.createElement('a'); + + DownloadLink.href = Texture; + DownloadLink.download = ExtractButton.previousElementSibling.value + '.png'; + document.body.appendChild(DownloadLink) + DownloadLink.click() + DownloadLink.remove() + } + } +}) + +function ParseGLB(arrayBuffer) { + const MAGIC_glTF = 0x46546C67; + + const dataView = new DataView(arrayBuffer); + + const magic = dataView.getUint32(0, true); + if (magic !== MAGIC_glTF) { + throw new Error('Invalid GLB file.'); + } + + const version = dataView.getUint32(4, true); + if (version !== 2) { + throw new Error('Unsupported GLB version.'); + } + + const length = dataView.getUint32(8, true); + const chunkLength = dataView.getUint32(12, true); + const chunkType = dataView.getUint32(16, true); + + if (chunkType !== 0x4E4F534A) { + throw new Error('Invalid GLB JSON chunk.'); + } + + const jsonChunk = new TextDecoder().decode( + new Uint8Array(arrayBuffer, 20, chunkLength) + ); + const json = JSON.parse(jsonChunk); + + const binChunkHeader = 20 + chunkLength; + const binChunkLength = dataView.getUint32(binChunkHeader, true); + const binChunkType = dataView.getUint32(binChunkHeader + 4, true); + + if (binChunkType !== 0x004E4942) { + throw new Error('Invalid GLB BIN chunk.'); + } + + const binChunk = arrayBuffer.slice(binChunkHeader + 8, binChunkHeader + 8 + binChunkLength); + + return { + json: json, + bin: binChunk + }; +} + +function GetTexture(gltf) { + let Texture = null + + const images = gltf.json.images; + if (images.length === 0) { + return null; + } + + const image = images[0]; + const bufferView = gltf.json.bufferViews[image.bufferView]; + const byteOffset = bufferView.byteOffset || 0; + const byteLength = bufferView.byteLength; + const buffer = new Uint8Array(gltf.bin, byteOffset, byteLength); + + const blob = new Blob([buffer], { type: image.mimeType }); + return URL.createObjectURL(blob); +} \ No newline at end of file diff --git a/resources/utils.js b/resources/utils.js index 40baa56..d1c68dd 100644 --- a/resources/utils.js +++ b/resources/utils.js @@ -99,6 +99,8 @@ export default { Rectangles: true }, UploadMultipleDecals: true, + GD_ServerBalanceOn: true, + AvatarDimensionToggleOn: true }, Limits: { PinnedGames: 10, diff --git a/settings.html b/settings.html index afb5718..af33b8c 100755 --- a/settings.html +++ b/settings.html @@ -1,3 +1,4 @@ + @@ -9,111 +10,9 @@ + -

Poly+ Settings

-

+

+
+
+   +
+
+ + "Potentially Unbalanced" Server Tag + + +
+
+ Quickly check if The Great Divide official event place servers are balanced or not! To be unbalanced, the team opposite of you has to have at least 1 more member in the server than you. + + + * available until July 14th + +
+
  Pinned Games @@ -388,8 +305,8 @@
Pin your favorite places to the top of the homepage! (limit: places) -

-

+

+
  Forum Mentions @@ -399,9 +316,9 @@ Get a quick link to the popular person everyone is talking about's profile!
* Forum Mentions do not notify the user or show up as a notification on their account. -

+
-

+

  Improved Friend Lists @@ -423,8 +340,8 @@
* You can only remove up to friends at once.
-

-

+

+
  Upload multiple decals @@ -434,8 +351,8 @@ Lets you quickly upload multiple decals at once! -

-

+

+
  Show IRL price with Brick Count @@ -469,8 +386,8 @@ --> -

-

+

+
  Hide Notification Badges @@ -478,8 +395,8 @@
Hide the annoying red circles on the sidebar! -

-

+

+
  Show "OWNED" Tag on Store Main Page @@ -487,8 +404,8 @@
Quickly see if you own the item at a glance with a little tag in the top left corner of item cards on the main store page! -

-

+

+
  Theme Creator @@ -497,8 +414,8 @@
Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development) -

-

+

+
  More Search Filters @@ -508,8 +425,8 @@ Easily find what you're looking for with more search filters side-wide! (this does not affect the main site search on the navbar)
* This currently only has a "Creator" username filter on the forum search page, more search filters are yet to come. -

-

+

+
  Apply Membership Theme for Free @@ -521,8 +438,8 @@ -

-

+

+
  Multi-Cancel Outbound Trades @@ -534,8 +451,8 @@
* You can only cancel up to 10 trades at once.
-

-

+

+
  Modify Navbar @@ -544,8 +461,8 @@
Customize the navbar to your liking! -

-

+

+
  Item Wishlist @@ -553,8 +470,8 @@
Wishlist that item that you REALLY want! -

-

+

+
  Try-On Items @@ -562,8 +479,8 @@
See how that new item looks on your avatar before spending your bricks! -

-

+

+
  Show Outfit Cost on Profiles @@ -571,8 +488,8 @@
Quickly see how many bricks a user spent on their avatar! -

-

+

+
  Show Approximate Place Revenue @@ -584,8 +501,8 @@ * Gamepass revenue is calculated assuming the price hasn't changed and all users that bought the gamepass, bought it at the same price that it is at the time of calculating. -

-

+

+
  Show "Owners" instead of "Sales" @@ -593,8 +510,8 @@
Replace the "Sales" statistic with the "Owners" statistic if the item has 0 sales (most likely meaning it is an item awarded by staff). -

-

+

+
  Collectibles' Hoarders List @@ -618,8 +535,8 @@ -

-

+

+
  Quick Library Downloads @@ -627,8 +544,8 @@
Quickly download a model (as a .ptmd file), mesh, decal, or sound right from the page showing you details about the asset! -

-

+

+
  "Event Items" Store Category @@ -636,8 +553,8 @@
List all the on-going and past event items separated by their event with a store category! -

-

+

+
  Show Friend Count on Homepage @@ -645,8 +562,8 @@
See how many friends you have on your homepage/dashboard, just scroll to the "friends" section and you'll see it next to the heading! -

-

+

+
  Timed-Item Owner Check @@ -657,8 +574,8 @@ >Click the shopping bags icon in the bottom left-hand corner of the timed item's item thumbnail to toggle an input and a button. Then just enter someone's username and it'll tell you whether they own it or not and if so what serial! -

-

+

+
  Hide User Ads @@ -676,9 +593,20 @@ -

+
+
+   + + Avatar Dimension Toggle + + +
+ + Quickly switch between a 3D or 2D rendition of somebody's avatar on their profile page! + +

EXPERIMENTAL SETTINGS

These features are a work in progress.


-

+

  Game Profiles @@ -706,8 +634,8 @@ * Place creators must request a game profile for one to be made.
* This feature will be expanded upon in the future. -

-

+

+
  Inline Editing @@ -719,8 +647,8 @@ * This feature currently only supports places.
* This feature is not finished or polished. -

-

+

+
  Forum Unix Timestamps @@ -730,8 +658,8 @@ See a date and time that is adjusted to everyone (who is using Poly+)'s local time
* The styling for this feature is not yet done. -

-

+

+
  Avatar Sandbox @@ -741,7 +669,7 @@ Create an avatar with all the item possibilities available to your heart's content!
* This feature is not polished - things like modifying avatar "Body Colors", pagination, outfits, etc haven't been added. -

+

diff --git a/settings.js b/settings.js index d8b6f42..801262b 100644 --- a/settings.js +++ b/settings.js @@ -328,6 +328,48 @@ function LoadThemeJSON(string) { } } +chrome.storage.sync.get(['PolyPlus_AutoAds'], function(result){ + let AutoAds = result.PolyPlus_AutoAds || []; + + const Modal = document.getElementById("AutoAdBidding-Modal") + const AddButton = document.getElementById('auto-ad-bidding-add') + + AddButton.addEventListener('click', async function() { + const Page = new DOMParser().parseFromString((await (await fetch('https://polytoria.com/create/ad/' + AddButton.previousElementSibling.value)).text()), 'text/html') + + + }) + + const AddRow = function(index, info) { + const Row = document.createElement('tr') + Row.innerHTML = ` + ${index+1} + "${info.name}" + $ 150 + + + + +
+ + + +
+ + ` + } +}) + function AreIdentical(obj1, obj2) { if (obj1.length !== obj2.length) { return false } return JSON.stringify(obj1) === JSON.stringify(obj2)