mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-01-11 22:40:18 +00:00
193 lines
11 KiB
HTML
193 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>JSDoc: Source: apiManager.js</title>
|
|
|
|
<script src="scripts/prettify/prettify.js"> </script>
|
|
<script src="scripts/prettify/lang-css.js"> </script>
|
|
<!--[if lt IE 9]>
|
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
<![endif]-->
|
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="main">
|
|
|
|
<h1 class="page-title">Source: apiManager.js</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<section>
|
|
<article>
|
|
<pre class="prettyprint source linenums"><code>/** ApiManager class for handling API requests, responses, and interactions.
|
|
* Note: Fetch spying is done in main.js, not here.
|
|
* @since 0.11.1
|
|
*/
|
|
|
|
import TemplateManager from "./templateManager.js";
|
|
import { escapeHTML, numberToEncoded, serverTPtoDisplayTP } from "./utils.js";
|
|
|
|
export default class ApiManager {
|
|
|
|
/** Constructor for ApiManager class
|
|
* @param {TemplateManager} templateManager
|
|
* @since 0.11.34
|
|
*/
|
|
constructor(templateManager) {
|
|
this.templateManager = templateManager;
|
|
this.disableAll = false; // Should the entire userscript be disabled?
|
|
this.coordsTilePixel = []; // Contains the last detected tile/pixel coordinate pair requested
|
|
this.templateCoordsTilePixel = []; // Contains the last "enabled" template coords
|
|
}
|
|
|
|
/** Determines if the spontaneously recieved response is something we want.
|
|
* Otherwise, we can ignore it.
|
|
* Note: Due to aggressive compression, make your calls like `data['jsonData']['name']` instead of `data.jsonData.name`
|
|
*
|
|
* @param {Overlay} overlay - The Overlay class instance
|
|
* @since 0.11.1
|
|
*/
|
|
spontaneousResponseListener(overlay) {
|
|
|
|
// Triggers whenever a message is sent
|
|
window.addEventListener('message', async (event) => {
|
|
|
|
const data = event.data; // The data of the message
|
|
const dataJSON = data['jsonData']; // The JSON response, if any
|
|
|
|
// Kills itself if the message was not intended for Blue Marble
|
|
if (!(data && data['source'] === 'blue-marble')) {return;}
|
|
|
|
// Kills itself if the message has no endpoint (intended for Blue Marble, but not this function)
|
|
if (!data['endpoint']) {return;}
|
|
|
|
// Trims endpoint to the second to last non-number, non-null directoy.
|
|
// E.g. "wplace.live/api/pixel/0/0?payload" -> "pixel"
|
|
// E.g. "wplace.live/api/files/s0/tiles/0/0/0.png" -> "tiles"
|
|
const endpointText = data['endpoint']?.split('?')[0].split('/').filter(s => s && isNaN(Number(s))).filter(s => s && !s.includes('.')).pop();
|
|
|
|
console.log(`%cBlue Marble%c: Recieved message about "%s"`, 'color: cornflowerblue;', '', endpointText);
|
|
|
|
// Each case is something that Blue Marble can use from the fetch.
|
|
// For instance, if the fetch was for "me", we can update the overlay stats
|
|
switch (endpointText) {
|
|
|
|
case 'me': // Request to retrieve user data
|
|
|
|
// If the game can not retrieve the userdata...
|
|
if (dataJSON['status'] && dataJSON['status']?.toString()[0] != '2') {
|
|
// The server is probably down (NOT a 2xx status)
|
|
|
|
overlay.handleDisplayError(`You are not logged in!\nCould not fetch userdata.`);
|
|
return; // Kills itself before attempting to display null userdata
|
|
}
|
|
|
|
const nextLevelPixels = Math.ceil(Math.pow(Math.floor(dataJSON['level']) * Math.pow(30, 0.65), (1/0.65)) - dataJSON['pixelsPainted']); // Calculates pixels to the next level
|
|
|
|
console.log(dataJSON['id']);
|
|
if (!!dataJSON['id'] || dataJSON['id'] === 0) {
|
|
console.log(numberToEncoded(
|
|
dataJSON['id'],
|
|
'!#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'
|
|
));
|
|
}
|
|
this.templateManager.userID = dataJSON['id'];
|
|
|
|
overlay.updateInnerHTML('bm-user-name', `Username: <b>${escapeHTML(dataJSON['name'])}</b>`); // Updates the text content of the username field
|
|
overlay.updateInnerHTML('bm-user-droplets', `Droplets: <b>${new Intl.NumberFormat().format(dataJSON['droplets'])}</b>`); // Updates the text content of the droplets field
|
|
overlay.updateInnerHTML('bm-user-nextlevel', `Next level in <b>${new Intl.NumberFormat().format(nextLevelPixels)}</b> pixel${nextLevelPixels == 1 ? '' : 's'}`); // Updates the text content of the next level field
|
|
break;
|
|
|
|
case 'pixel': // Request to retrieve pixel data
|
|
const coordsTile = data['endpoint'].split('?')[0].split('/').filter(s => s && !isNaN(Number(s))); // Retrieves the tile coords as [x, y]
|
|
const payloadExtractor = new URLSearchParams(data['endpoint'].split('?')[1]); // Declares a new payload deconstructor and passes in the fetch request payload
|
|
const coordsPixel = [payloadExtractor.get('x'), payloadExtractor.get('y')]; // Retrieves the deconstructed pixel coords from the payload
|
|
|
|
// Don't save the coords if there are previous coords that could be used
|
|
if (this.coordsTilePixel.length && (!coordsTile.length || !coordsPixel.length)) {
|
|
overlay.handleDisplayError(`Coordinates are malformed!\nDid you try clicking the canvas first?`);
|
|
return; // Kills itself
|
|
}
|
|
|
|
this.coordsTilePixel = [...coordsTile, ...coordsPixel]; // Combines the two arrays such that [x, y, x, y]
|
|
const displayTP = serverTPtoDisplayTP(coordsTile, coordsPixel);
|
|
|
|
const spanElements = document.querySelectorAll('span'); // Retrieves all span elements
|
|
|
|
// For every span element, find the one we want (pixel numbers when canvas clicked)
|
|
for (const element of spanElements) {
|
|
if (element.textContent.trim().includes(`${displayTP[0]}, ${displayTP[1]}`)) {
|
|
|
|
let displayCoords = document.querySelector('#bm-display-coords'); // Find the additional pixel coords span
|
|
|
|
const text = `(Tl X: ${coordsTile[0]}, Tl Y: ${coordsTile[1]}, Px X: ${coordsPixel[0]}, Px Y: ${coordsPixel[1]})`;
|
|
|
|
// If we could not find the addition coord span, we make it then update the textContent with the new coords
|
|
if (!displayCoords) {
|
|
displayCoords = document.createElement('span');
|
|
displayCoords.id = 'bm-display-coords';
|
|
displayCoords.textContent = text;
|
|
displayCoords.style = 'margin-left: calc(var(--spacing)*3); font-size: small;';
|
|
element.parentNode.parentNode.parentNode.insertAdjacentElement('afterend', displayCoords);
|
|
} else {
|
|
displayCoords.textContent = text;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'tiles':
|
|
|
|
// Runs only if the tile has the template
|
|
let tileCoordsTile = data['endpoint'].split('/');
|
|
tileCoordsTile = [parseInt(tileCoordsTile[tileCoordsTile.length - 2]), parseInt(tileCoordsTile[tileCoordsTile.length - 1].replace('.png', ''))];
|
|
|
|
const blobUUID = data['blobID'];
|
|
const blobData = data['blobData'];
|
|
|
|
const templateBlob = await this.templateManager.drawTemplateOnTile(blobData, tileCoordsTile);
|
|
|
|
window.postMessage({
|
|
source: 'blue-marble',
|
|
blobID: blobUUID,
|
|
blobData: templateBlob,
|
|
blink: data['blink']
|
|
});
|
|
break;
|
|
|
|
case 'robots': // Request to retrieve what script types are allowed
|
|
this.disableAll = dataJSON['userscript']?.toString().toLowerCase() == 'false'; // Disables Blue Marble if site owner wants userscripts disabled
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
}</code></pre>
|
|
</article>
|
|
</section>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<nav>
|
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
|
</nav>
|
|
|
|
<br class="clear">
|
|
|
|
<footer>
|
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 16:09:33 GMT-0400 (Eastern Daylight Time)
|
|
</footer>
|
|
|
|
<script> prettyPrint(); </script>
|
|
<script src="scripts/linenumber.js"> </script>
|
|
</body>
|
|
</html>
|