Object building API! Whoa!

(ty figment for helping with this)
This commit is contained in:
Colon 2020-10-13 10:25:07 -04:00
parent e08e36e7e2
commit d56a6343ff
14 changed files with 29696 additions and 174 deletions

View file

@ -2,7 +2,7 @@ const zlib = require('zlib')
const properties = require('../misc/objectProperties.json')
const init = require('../misc/initialProperties.json')
const colorStuff = require('../misc/colorProperties.json')
const ids = require('../misc/objects.json')
const ids = require('../misc/notableObjects.json')
const blocks = require('../misc/blocks.json')
module.exports = async (app, req, res, level) => {

31
api/object.js Normal file
View file

@ -0,0 +1,31 @@
const Jimp = require('jimp');
const objects = require('../misc/objects.json')
const sprites = require('../misc/sprites.json')
// pre-load this ONCE to drop loading time
let sheets = [1, 2, 3].map(x => `./assets/spritesheets/GJ_GameSheet0${x}.png`)
module.exports = async (app, req, res) => {
let objID = req.params.text
if (!objects[objID] || !sprites[objects[objID]]) objID = 1607 // question mark
let sprite = sprites[objects[objID]]
let rotateParams = req.query.rotation || req.query.rotate || req.query.r
let rotation = sprite.rotation - (+rotateParams || 0)
let spritesheet = sheets[sprite.spritesheet - 1]
let crop = [sprite.x, sprite.y, sprite.width, sprite.height]
if (sprite.rotation == 90) [crop[2], crop[3]] = [crop[3], crop[2]]
Jimp.read(spritesheet).then(sheet => {
if (typeof spritesheet == "string") sheets[sprite.spritesheet - 1] = new Jimp(sheet)
sheet.crop(...crop)
if (rotation) sheet.rotate(rotation)
sheet.mirror(req.query.hasOwnProperty("flipX"), req.query.hasOwnProperty("flipY"))
sheet.getBuffer(Jimp.AUTO, (err, buffer) => {
return res.contentType('image/png').end(buffer, 'base64')
})
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

View file

@ -1,5 +1,5 @@
const XOR = require(__dirname + "/../classes/XOR");
const config = require(__dirname + "/../misc/gdpsConfig");
const config = require(__dirname + "/../gdpsConfig");
let orbs = [0, 0, 50, 75, 125, 175, 225, 275, 350, 425, 500]
let length = ['Tiny', 'Short', 'Medium', 'Long', 'XL']

View file

@ -28,6 +28,7 @@
<a class="header-link" href="#level">Levels</a>
<a class="header-link" href="#search">Searching</a>
<a class="header-link" href="#levelleaderboard">Level Leaderboards</a>
<a class="header-link" href="#analyze">Level Analysis</a>
</div>
</div>
<div class="header-category">
@ -50,7 +51,7 @@
<div class="header-category">
<div class="category-name">Misc</div>
<div class="category-content">
<a class="header-link" href="#analyze">Level Analysis</a>
<a class="header-link" href="#objects">Objects</a>
<a class="header-link" href="#icons">Icons</a>
</div>
</div>
@ -78,12 +79,13 @@
<p><a href="#search"><u>Searching</u></a> <i>/api/search/search-query</i></p>
<p><a href="#leaderboard"><u>Leaderboards</u></a> <i>/api/leaderboard</i></p>
<p><a href="#levelleaderboard"><u>Level Leaderboards</u></a> <i>/api/leaderboardLevel/levelID</i></p>
<p><a href="#comments"><u>Comments & Posts</u></a> <i>/api/comments/level-or-user-ID</i></p>
<p><a href="#analyze"><u>Level Analysis</u></a> <i>/api/analyze/levelID</i></p>
<p><a href="#comments"><u>Comments & Posts</u></a> <i>/api/comments/level-or-user-ID</i></p>
<p><a href="#commenting"><u>Commenting</u></a> <i>/postComment (POST)</i></p>
<p><a href="#profileposting"><u>Profile Posting</u></a> <i>/postProfileComment (POST)</i></p>
<p><a href="#messages"><u>Messages</u></a> <i>/messages (4 different POSTs)</i></p>
<p><a href="#liking"><u>Liking</u></a> <i>/like (POST)</i></p>
<p><a href="#objects"><u>Objects</u></a> <i>/objects/objectID</i></p>
<p><a href="#icons"><u>Icons</u></a> <i>/icon/username</i></p>
</quote>
<br>
@ -413,6 +415,47 @@
<div class="seperator"></div>
</main>
<main>
<div id="analyze" class="anchor"></div>
<div class="main-block">
<h1>Level Analysis</h1>
<p>/api/analyze/levelID</p>
<p>Analyzes a level's data</p>
<p><sb>Level analysis is updated a lot so there may be changes in the future</sb></p>
<br>
<p class="reveal" onclick="$('#params-analyze').slideToggle(100)"><b>Parameters (0)</b></p>
<div class="subdiv" id="params-analyze">
<p>No parameters for this one!</p>
</div>
<br>
<p class="reveal" onclick="$('#response-analyze').slideToggle(100)"><b>Response (12)</b></p>
<div class="subdiv" id="response-analyze">
<p><b>Response is subject to change in the future</b></p>
<p>The API will return an array of each player with the following information:</p>
<p>level: Basic level info (name, ID, author, etc)</p>
<p>settings: The level's settings (song offset, starting form/speed, two player mode, font, etc)</p>
<p>portals: A string listing the order of all the portals in the level + their percent. Does not include starting form/speed</p>
<p>orbs: How many of each jump ring is in the level</p>
<p>triggers: How many of each trigger is in the level</p>
<p>blocks: How many of each block type is in the level</p>
<p>triggerGroups: How many of each group ID is in the level</p>
<p>misc: Amount of objects that aren't categorized above (glow, arrows, clouds, pickups, etc)</p>
<p>colors: The level's initial color channels. Contains channel, R, G, B, opacity, player color, blending, and copied channel</p>
<p>text: An array of all the text objects in a level. ([text, percent])</p>
<p>dataLength: How long the level data is (spoilers - very)</p>
<p>data: The decrypted data of the level. And it's freakin' huge</p>
</div>
<br>
</div>
<div class="seperator"></div>
</main>
<main>
<div id="comments" class="anchor"></div>
@ -473,47 +516,6 @@
<div class="seperator"></div>
</main>
<main>
<div id="analyze" class="anchor"></div>
<div class="main-block">
<h1>Level Analysis</h1>
<p>/api/analyze/levelID</p>
<p>Analyzes a level's data</p>
<p><sb>Level analysis is updated a lot so there may be changes in the future</sb></p>
<br>
<p class="reveal" onclick="$('#params-analyze').slideToggle(100)"><b>Parameters (0)</b></p>
<div class="subdiv" id="params-analyze">
<p>No parameters for this one!</p>
</div>
<br>
<p class="reveal" onclick="$('#response-analyze').slideToggle(100)"><b>Response (12)</b></p>
<div class="subdiv" id="response-analyze">
<p><b>Response is subject to change in the future</b></p>
<p>The API will return an array of each player with the following information:</p>
<p>level: Basic level info (name, ID, author, etc)</p>
<p>settings: The level's settings (song offset, starting form/speed, two player mode, font, etc)</p>
<p>portals: A string listing the order of all the portals in the level + their percent. Does not include starting form/speed</p>
<p>orbs: How many of each jump ring is in the level</p>
<p>triggers: How many of each trigger is in the level</p>
<p>blocks: How many of each block type is in the level</p>
<p>triggerGroups: How many of each group ID is in the level</p>
<p>misc: Amount of objects that aren't categorized above (glow, arrows, clouds, pickups, etc)</p>
<p>colors: The level's initial color channels. Contains channel, R, G, B, opacity, player color, blending, and copied channel</p>
<p>text: An array of all the text objects in a level. ([text, percent])</p>
<p>dataLength: How long the level data is (spoilers - very)</p>
<p>data: The decrypted data of the level. And it's freakin' huge</p>
</div>
<br>
</div>
<div class="seperator"></div>
</main>
<main>
<div id="commenting" class="anchor"></div>
<div class="main-block">
@ -708,6 +710,49 @@
<div class="seperator"></div>
</main>
</main>
<main>
<div id="objects" class="anchor"></div>
<div class="main-block">
<h1>Objects</h1>
<p>/object/objectID</p>
<p>Gets a PNG of an object from Geometry Dash</p>
<p style="font-weight: bold">This one is still a WIP so some objects (like monsters) are not yet supported</p>
<p style="font-size:15px; margin-top:-7px">All the object IDs are documented in <a target="_blank" href="../58079690">this level</a></p>
<br>
<p class="reveal" onclick="$('#params-objects').slideToggle(100)"><b>Parameters (3)</b></p>
<div class="subdiv" id="params-objects">
<p>rotation: The rotation of the object (clockwise)</p>
<p>flipX: Mirrors the object horizontally</p>
<p>flipY: Mirrors the object vertically</p>
</div>
<br>
<p class="reveal" onclick="$('#response-objects').slideToggle(100)"><b>Response (1)</b></p>
<div class="subdiv" id="response-objects">
<p>A delicious PNG of the object!</p>
</div>
<br>
<p class="reveal" onclick="$('#request-objects').slideToggle(100)"><b>Examples</b></p>
<div class="subdiv" id="request-objects">
<p><b>Sample Icons</b></p>
<p><a target="_blank" style="font-weight:400" href="../object/1">/object/1</a> (the default block)</p>
<p><a target="_blank" style="font-weight:400" href="../object/660?rotation=90">/object/660?rotation=90</a> (the wave portal, rotated 90 degrees clockwise)</p>
<p><a target="_blank" style="font-weight:400" href="../object/1704?flipX">/object/1704?flipX</a> (a dash orb flipped horizontally)</p>
</div>
<br>
</div>
<div class="seperator"></div>
</main>
</main>
<main>
<div id="icons" class="anchor"></div>
<div class="main-block">
@ -715,7 +760,6 @@
<p>/icon/username</p>
<p>Gets a player's GD icon, or builds a custom one (Sent as a PNG)</p>
<p style="font-size:15px; margin-top:-7px">This one isn't really part of the API, but dammit, my website my rules</p>
<br>
<p class="reveal" onclick="$('#params-icons').slideToggle(100)"><b>Parameters (9)</b></p>

View file

@ -79,14 +79,20 @@
let page = 1
$('#browserlogo').css('filter', `hue-rotate(${Math.floor(Math.random() * (330 - 60)) + 60}deg) saturate(${Math.floor(Math.random() * (150 - 100)) + 100}%)`)
let xButtonPos = '43%'
let lastPage
function loadCredits() {
$('.subCredits').hide()
$('#credits' + page).show()
$('#credits').show()
if (page == lastPage) $('#closeCredits').css('height', '52%')
else $('#closeCredits').css('height', xButtonPos)
}
fetch(`./api/credits`).then(res => res.json()).then(res => {
lastPage = res.credits.length + 1
res.credits.forEach((x, y) => {
$('#credits').append(`<div id="credits${y+1}" class="subCredits" style="display: none;">
<div class="brownBox center supercenter" style="width: 80vh; height: 43%; padding-top: 1.5%; padding-bottom: 3.5%;">
@ -103,22 +109,23 @@ fetch(`./api/credits`).then(res => res.json()).then(res => {
</div>`)
})
$('#credits').append(`<div id="credits${res.credits.length + 1}" class="subCredits" style="display: none;">
<div id="specialthanks" class="brownBox center supercenter" style="width: 80vh; height: 43%; padding-top: 1.5%; padding-bottom: 3.5%;">
$('#credits').append(`<div id="credits${lastPage}" class="subCredits" style="display: none;">
<div id="specialthanks" class="brownBox center supercenter" style="width: 80vh; height: 55%; padding-top: 1.5%; padding-bottom: 3.5%;">
<h1>Special Thanks!</h1><br>
</div>
<img class="gdButton" src="../assets/arrow-left.png" width="60vh" style="position: absolute; top: 45%; right: 75%" onclick="page -= 1; loadCredits()">
</div>`)
res.specialThanks.forEach((x, y) => {
n = x.split("/")
$('#specialthanks').append(`<div class="specialThanks">
<h2 class="gdButton smaller"><a href="./u/${x}">${x}</h2></a>
<img src="./icon/${x}" height=85%><br>
<h2 class="gdButton smaller"><a href="./u/${n[1] || n[0]}">${n[0]}</h2></a>
<img src="./icon/${n[1] || n[0]}" height=77%><br>
</div>`)
})
$('#credits').append(`<div class="center supercenter" style="width: 80vh; height: 43%; pointer-events: none;">
<img class="closeWindow gdButton" src="../assets/close.png" height="25%" style="position: absolute; top: -24%; left: -7vh; pointer-events: all;" onclick="$('#credits').hide(); page = 1;"></div>`)
$('#credits').append(`<div id="closeCredits" class="center supercenter" style="width: 80vh; height: ${xButtonPos}%; pointer-events: none;">
<img class="closeWindow gdButton" src="../assets/close.png" width="14%" style="position: absolute; top: -24%; left: -7vh; pointer-events: all;" onclick="$('#credits').hide(); page = 1;"></div>`)
$(document).keydown(function(k) {
@ -128,7 +135,7 @@ fetch(`./api/credits`).then(res => res.json()).then(res => {
page -= 1; loadCredits();
}
if (k.which == 39 && page < res.credits.length + 1) { //right
if (k.which == 39 && page < lastPage) { //right
page += 1; loadCredits();
}

View file

@ -11,7 +11,7 @@ const app = express();
app.offline = false // set to true to go into "offline" mode (in case of ip ban from rob)
app.secret = "Wmfd2893gb7" // lol
app.config = require('./misc/gdpsConfig') // tweak settings in this file if you're using a GDPS
app.config = require('./gdpsConfig') // tweak settings in this file if you're using a GDPS
app.endpoint = app.config.endpoint // boomlings.com/database/
app.gdParams = function(obj={}) {
@ -142,6 +142,7 @@ app.get("/api/search/:text", function(req, res) { app.run.search(app, req, res)
app.get("/icon", function(req, res) { res.redirect('/iconkit') })
app.get("/iconkit/:text", function(req, res) { res.redirect('/icon/' + req.params.text) })
app.get("/obj/:text", function(req, res) { res.redirect('/obj/' + req.params.text) })
app.get("/leaderboards/:id", function(req, res) { res.redirect('/leaderboard/' + req.params.id) })
app.get("/profile/:id", function(req, res) { res.redirect('/u/' + req.params.id) })
app.get("/p/:id", function(req, res) { res.redirect('/u/' + req.params.id) })
@ -160,6 +161,7 @@ app.get("/:id", function(req, res) { app.run.level(app, req, res) })
app.get("/assets/sizecheck.js", function(req, res) { res.sendFile(__dirname + "/misc/sizecheck.js") })
app.get("/icon/:text", function(req, res) { app.run.icon(app, req, res) })
app.get("/object/:text", function(req, res) { app.run.object(app, req, res) })
app.get('/api/icons', function(req, res) {
let sample = [JSON.stringify(sampleIcons[Math.floor(Math.random() * sampleIcons.length)].slice(1))]
res.send(gdIcons.concat(sample));

View file

@ -8,15 +8,6 @@
"github": ["https://github.com/GDColon", "github"]
},
{
"header": "Additional Help",
"name": "101arrowz",
"ign": "genius991",
"youtube": ["https://www.youtube.com/channel/UCuloR4qLkF3QGw8WUHjcNuQ", "youtube"],
"twitter": ["https://twitter.com/arjunbarrett", "twitter"],
"github": ["https://github.com/101arrowz", "github"]
},
{
"header": "Level Analyzing Help",
"name": "Alten",
@ -74,6 +65,8 @@
"ViPriN",
"Cvolton",
"Ucrash",
"zmxmx"
"zmxmx",
"101arrowz",
"Figment/FigmentBoy"
]
}

112
misc/notableObjects.json Normal file
View file

@ -0,0 +1,112 @@
{
"portals": {
"12": "cube",
"13": "ship",
"47": "ball",
"111": "ufo",
"660": "wave",
"745": "robot",
"1331": "spider",
"45": "mirrorOn",
"46": "mirrorOff",
"101": "mini",
"99": "big",
"286": "dual",
"287": "single",
"200": "-1x",
"201": "1x",
"202": "2x",
"203": "3x",
"1334": "4x"
},
"orbs": {
"36": "yellow",
"84": "blue",
"141": "pink",
"1022": "green",
"1333": "red",
"1330": "black",
"1704": "greenDash",
"1751": "pinkDash",
"1594": "trigger"
},
"triggers": {
"29": "Color",
"30": "Color",
"31": "StartPos",
"32": "EnableTrail",
"33": "DisableTrail",
"34": "StartPos2",
"104": "Color",
"105": "Color",
"221": "Color",
"717": "Color",
"718": "Color",
"743": "Color",
"744": "Color",
"899": "Color",
"900": "Color",
"915": "Color",
"901": "Move",
"1006": "Pulse",
"1007": "Alpha",
"1049": "Toggle",
"1268": "Spawn",
"1346": "Rotate",
"1347": "Follow",
"1520": "Shake",
"1585": "Animate",
"1595": "Touch",
"1611": "Count",
"1612": "HidePlayer",
"1613": "ShowPlayer",
"1616": "Stop",
"1811": "InstantCount",
"1812": "OnDeath",
"1814": "FollowPlayerY",
"1815": "Collision",
"1817": "Pickup",
"1818": "BGEffectOn",
"1819": "BGEffectOff",
"22": "Transition",
"24": "Transition",
"23": "Transition",
"25": "Transition",
"26": "Transition",
"27": "Transition",
"28": "Transition",
"55": "Transition",
"56": "Transition",
"57": "Transition",
"58": "Transition",
"59": "Transition",
"1912": "Random",
"1913": "CameraZoom",
"1914": "CameraStatic",
"1916": "CameraOffset",
"1917": "Reverse",
"1931": "LevelEnd"
},
"misc": {
"spikes": ["Spikes", 8, 218, 458, 39, 103, 144, 392, 205, 216, 145, 217, 459, 177, 178, 179],
"saws": ["Saws", 1705, 740, 1619, 1706, 741, 742, 1620, 184, 1707, 1734, 678, 185, 1708, 1736, 187, 679, 1709, 1710, 186, 1735, 188, 680, 183],
"invisibles": ["Fading", 146, 147, 206, 204, 673, 674, 1340, 1341, 1342, 1343, 1344, 1345, 144, 205, 145, 459, 740, 741, 742],
"pickups": ["Pickups", 1614, 1598, 1587, 1275],
"texts": ["Text", 914, 1615],
"glows": ["Glow", 1888, 1763, 1762, 1293, 1270, 1269, 1012, 1013, 1011, 1886, 1759, 1758, 1291, 1274, 1273, 504, 505, 503, 1887, 1761, 1760, 1272, 1271, 1009, 1010, 1292],
"hands": ["Hands", 1844, 1845, 1846, 1847, 1848],
"pulses": ["Pulsing", 50, 52, 51, 53, 54, 60, 148, 149, 405, 132, 460, 494, 133, 136, 150, 236, 497, 495, 496, 15, 16, 17],
"breakables": ["Breakable", 143],
"collisions": ["Collisions", 1816],
"pixels": ["Pixels", 916, 917],
"clouds": ["Clouds", 936, 937, 938, 129, 130, 131],
"arrows": ["Arrows", 1768, 1766, 1603, 1844, 132, 494, 460],
"particles": ["Particles", 1586, 1700, 1519, 1618],
"monsters": ["Monsters", 918, 1327, 1328, 1584],
"fires": ["Fire", 920, 923, 924, 921]
}
}

File diff suppressed because it is too large Load diff

27834
misc/sprites.json Normal file

File diff suppressed because it is too large Load diff