Skip to content

Instantly share code, notes, and snippets.

@jakeayy
Last active January 7, 2026 18:18
Show Gist options
  • Select an option

  • Save jakeayy/ba46bcf4fb2589a4fc608516addf888c to your computer and use it in GitHub Desktop.

Select an option

Save jakeayy/ba46bcf4fb2589a4fc608516addf888c to your computer and use it in GitHub Desktop.
decode bonk.io levelData (UNFINISHED TYPES)
import LZString from "lz-string";
class ByteBuffer {
off: number = 0;
constructor(public buf: Buffer, public littleEndian: boolean) {}
readShort() {
const v = this.buf[this.littleEndian ? "readInt16LE" : "readInt16BE"](
this.off,
);
this.off += 2;
return v;
}
readDouble() {
const v = this.buf[this.littleEndian ? "readDoubleLE" : "readDoubleBE"](
this.off,
);
this.off += 8;
return v;
}
readFloat() {
const v = this.buf[this.littleEndian ? "readFloatLE" : "readFloatBE"](
this.off,
);
this.off += 4;
return v;
}
readByte() {
return this.buf[this.off++];
}
readBoolean() {
return Boolean(this.readByte());
}
readUTF() {
const length = this.readShort();
return this.buf.toString("utf-8", this.off, (this.off += length));
}
readUint() {
const v = this.buf[this.littleEndian ? "readUint32LE" : "readUint32BE"](
this.off,
);
this.off += 4;
return v;
}
readInt() {
const v = this.buf[this.littleEndian ? "readInt32LE" : "readInt32BE"](
this.off
);
this.off += 4;
return v;
}
static fromBase64(data: string, littleEndian: boolean) {
return new this(Buffer.from(data, "base64"), littleEndian);
}
}
class MapUtils {
static getBlankMap() {
return {
v: 1,
s: {
re: false,
nc: false,
pq: 1,
gd: 25,
fl: false,
},
physics: {
shapes: [],
fixtures: [],
bodies: [],
bro: [],
joints: [],
ppm: 12,
},
spawns: [],
capZones: [],
m: {
a: "noauthor",
n: "noname",
dbv: 2,
dbid: -1,
authid: -1,
date: "",
rxid: 0,
rxn: "",
rxa: "",
rxdb: 1,
cr: [],
pub: false,
mo: "",
},
};
}
static getNewBoxShape() {
return {
type: "bx",
w: 10,
h: 40,
c: [0, 0],
a: 0,
sk: false,
};
}
static getNewPolyShape() {
return {
type: "po",
v: [],
s: 1,
a: 0,
c: [0, 0],
};
}
static getNewFixture() {
return {
n: "Def Fix",
fr: 0.3,
fp: null,
re: 0.8,
de: 0.3,
f: 5209260,
d: false,
np: false,
ng: false,
};
}
static getNewBody() {
return {
p: [0, 0],
a: 0,
lv: [0, 0],
av: 0,
cf: {
x: 0,
y: 0,
w: true,
ct: 0,
},
fx: [],
fz: {
on: false,
x: 0,
y: 0,
d: true,
p: true,
a: true,
t: 0,
cf: 0,
},
s: {
type: "s",
n: "Unnamed",
fric: 0.3,
fricp: false,
re: 0.8,
de: 0.3,
ld: 0,
ad: 0,
fr: false,
bu: false,
f_c: 1,
f_p: true,
f_1: true,
f_2: true,
f_3: true,
f_4: true,
},
};
}
static getNewSpawn() {
return {
x: 400,
y: 300,
xv: 0,
yv: 0,
priority: 5,
r: true,
f: true,
b: true,
gr: false,
ye: false,
n: "Spawn",
};
}
static getNewCapZone() {
return {
n: "Cap Zone",
ty: 1,
l: 10,
i: -1,
};
}
static getNewRevoluteJoint() {
return {
type: "rv",
d: {
la: 0,
ua: 0,
mmt: 0,
ms: 0,
el: false,
em: false,
cc: false,
bf: 0,
dl: true,
},
aa: [0, 0],
};
}
static getNewDistanceJoint() {
return {
type: "d",
d: {
fh: 0,
dr: 0,
cc: false,
bf: 0,
dl: true,
},
aa: [0, 0],
ab: [0, 0],
};
}
static getNewLPJJoint() {
return {
type: "lpj",
d: {
cc: false,
bf: 0,
dl: true,
},
pax: 0,
pay: 0,
pa: 0,
pf: 0,
pl: 0,
pu: 0,
plen: 0,
pms: 0,
};
}
static getNewLSJJoint() {
return {
type: "lsj",
d: {
cc: false,
bf: 0,
dl: true,
},
sax: 0,
say: 0,
sf: 0,
slen: 0,
};
}
static getNewGearJoint() {
return {
type: "g",
n: "Gear Joint",
ja: -1,
jb: -1,
r: 1,
};
}
static getNewCircleShape() {
return {
type: "ci",
r: 25,
c: [0, 0],
sk: false,
};
}
}
const game = {
mapVersion: 15,
};
function decodeFromDatabase(levelData: string) {
const decompressed = LZString.decompressFromEncodedURIComponent(levelData);
let buffer = ByteBuffer.fromBase64(decompressed, false);
const level = MapUtils.getBlankMap();
const physics = level.physics;
level.v = buffer.readShort();
if (level.v > game.mapVersion) {
throw new Error("Future map version, please refresh page");
}
level.s.re = buffer.readBoolean();
level.s.nc = buffer.readBoolean();
if (level.v >= 3) {
level.s.pq = buffer.readShort();
}
if (level.v >= 4 && level.v <= 12) {
level.s.gd = buffer.readShort();
} else if (level.v >= 13) {
level.s.gd = buffer.readFloat();
}
if (level.v >= 9) {
level.s.fl = buffer.readBoolean();
}
level.m.rxn = buffer.readUTF();
level.m.rxa = buffer.readUTF();
level.m.rxid = buffer.readUint();
level.m.rxdb = buffer.readShort();
level.m.n = buffer.readUTF();
level.m.a = buffer.readUTF();
if (level.v >= 10) {
level.m.vu = buffer.readUint();
level.m.vd = buffer.readUint();
}
if (level.v >= 4) {
let size = buffer.readShort();
for (let i = 0; i < size; i++) {
level.m.cr.push(buffer.readUTF());
}
}
if (level.v >= 5) {
level.m.mo = buffer.readUTF();
level.m.dbid = buffer.readInt();
}
if (level.v >= 7) {
level.m.pub = buffer.readBoolean();
}
if (level.v >= 8) {
level.m.dbv = buffer.readInt();
}
physics.ppm = buffer.readShort();
let size = buffer.readShort();
for (let i = 0; i < size; i++) {
physics.bro[i] = buffer.readShort();
}
size = buffer.readShort();
for (let i = 0; i < size; i++) {
let type = buffer.readShort();
if (type == 1) {
physics.shapes[i] = MapUtils.getNewBoxShape();
physics.shapes[i].w = buffer.readDouble();
physics.shapes[i].h = buffer.readDouble();
physics.shapes[i].c = [buffer.readDouble(), buffer.readDouble()];
physics.shapes[i].a = buffer.readDouble();
physics.shapes[i].sk = buffer.readBoolean();
}
if (type == 2) {
physics.shapes[i] = MapUtils.getNewCircleShape();
physics.shapes[i].r = buffer.readDouble();
physics.shapes[i].c = [buffer.readDouble(), buffer.readDouble()];
physics.shapes[i].sk = buffer.readBoolean();
}
if (type == 3) {
physics.shapes[i] = MapUtils.getNewPolyShape();
physics.shapes[i].s = buffer.readDouble();
physics.shapes[i].a = buffer.readDouble();
physics.shapes[i].c = [buffer.readDouble(), buffer.readDouble()];
let inner_size = buffer.readShort();
physics.shapes[i].v = [];
for (let j = 0; j < inner_size; j++) {
physics.shapes[i].v.push([buffer.readDouble(), buffer.readDouble()]);
}
}
}
size = buffer.readShort();
for (let i = 0; i < size; i++) {
physics.fixtures[i] = MapUtils.getNewFixture();
physics.fixtures[i].sh = buffer.readShort();
physics.fixtures[i].n = buffer.readUTF();
physics.fixtures[i].fr = buffer.readDouble();
if (physics.fixtures[i].fr == Number.MAX_VALUE) {
physics.fixtures[i].fr = null;
}
let type = buffer.readShort();
if (type == 0) {
physics.fixtures[i].fp = null;
}
if (type == 1) {
physics.fixtures[i].fp = false;
}
if (type == 2) {
physics.fixtures[i].fp = true;
}
physics.fixtures[i].re = buffer.readDouble();
if (physics.fixtures[i].re == Number.MAX_VALUE) {
physics.fixtures[i].re = null;
}
physics.fixtures[i].de = buffer.readDouble();
if (physics.fixtures[i].de == Number.MAX_VALUE) {
physics.fixtures[i].de = null;
}
physics.fixtures[i].f = buffer.readUint();
physics.fixtures[i].d = buffer.readBoolean();
physics.fixtures[i].np = buffer.readBoolean();
if (level.v >= 11) {
physics.fixtures[i].ng = buffer.readBoolean();
}
if (level.v >= 12) {
physics.fixtures[i].ig = buffer.readBoolean();
}
}
size = buffer.readShort();
for (let i = 0; i < size; i++) {
physics.bodies[i] = MapUtils.getNewBody();
physics.bodies[i].s.type = buffer.readUTF();
physics.bodies[i].s.n = buffer.readUTF();
physics.bodies[i].p = [buffer.readDouble(), buffer.readDouble()];
physics.bodies[i].a = buffer.readDouble();
physics.bodies[i].s.fric = buffer.readDouble();
physics.bodies[i].s.fricp = buffer.readBoolean();
physics.bodies[i].s.re = buffer.readDouble();
physics.bodies[i].s.de = buffer.readDouble();
physics.bodies[i].lv = [buffer.readDouble(), buffer.readDouble()];
physics.bodies[i].av = buffer.readDouble();
physics.bodies[i].s.ld = buffer.readDouble();
physics.bodies[i].s.ad = buffer.readDouble();
physics.bodies[i].s.fr = buffer.readBoolean();
physics.bodies[i].s.bu = buffer.readBoolean();
physics.bodies[i].cf.x = buffer.readDouble();
physics.bodies[i].cf.y = buffer.readDouble();
physics.bodies[i].cf.ct = buffer.readDouble();
physics.bodies[i].cf.w = buffer.readBoolean();
physics.bodies[i].s.f_c = buffer.readShort();
physics.bodies[i].s.f_1 = buffer.readBoolean();
physics.bodies[i].s.f_2 = buffer.readBoolean();
physics.bodies[i].s.f_3 = buffer.readBoolean();
physics.bodies[i].s.f_4 = buffer.readBoolean();
if (level.v >= 2) {
physics.bodies[i].s.f_p = buffer.readBoolean();
}
if (level.v >= 14) {
physics.bodies[i].fz.on = buffer.readBoolean();
if (physics.bodies[i].fz.on) {
physics.bodies[i].fz.x = buffer.readDouble();
physics.bodies[i].fz.y = buffer.readDouble();
physics.bodies[i].fz.d = buffer.readBoolean();
physics.bodies[i].fz.p = buffer.readBoolean();
physics.bodies[i].fz.a = buffer.readBoolean();
if (level.v >= 15) {
physics.bodies[i].fz.t = buffer.readShort();
physics.bodies[i].fz.cf = buffer.readDouble();
}
}
}
let inner_size = buffer.readShort();
for (let j = 0; j < inner_size; j++) {
physics.bodies[i].fx.push(buffer.readShort());
}
}
size = buffer.readShort();
for (let i = 0; i < size; i++) {
level.spawns[i] = MapUtils.getNewSpawn();
let spawn = level.spawns[i];
spawn.x = buffer.readDouble();
spawn.y = buffer.readDouble();
spawn.xv = buffer.readDouble();
spawn.yv = buffer.readDouble();
spawn.priority = buffer.readShort();
spawn.r = buffer.readBoolean();
spawn.f = buffer.readBoolean();
spawn.b = buffer.readBoolean();
spawn.gr = buffer.readBoolean();
spawn.ye = buffer.readBoolean();
spawn.n = buffer.readUTF();
}
size = buffer.readShort();
for (let i = 0; i < size; i++) {
level.capZones[i] = MapUtils.getNewCapZone();
level.capZones[i].n = buffer.readUTF();
level.capZones[i].l = buffer.readDouble();
level.capZones[i].i = buffer.readShort();
if (level.v >= 6) {
level.capZones[i].ty = buffer.readShort();
}
}
size = buffer.readShort();
for (let i = 0; i < size; i++) {
let type = buffer.readShort();
if (type == 1) {
physics.joints[i] = MapUtils.getNewRevoluteJoint();
let joint = physics.joints[i];
joint.d.la = buffer.readDouble();
joint.d.ua = buffer.readDouble();
joint.d.mmt = buffer.readDouble();
joint.d.ms = buffer.readDouble();
joint.d.el = buffer.readBoolean();
joint.d.em = buffer.readBoolean();
joint.aa = [buffer.readDouble(), buffer.readDouble()];
}
if (type == 2) {
physics.joints[i] = MapUtils.getNewDistanceJoint();
let joint = physics.joints[i];
joint.d.fh = buffer.readDouble();
joint.d.dr = buffer.readDouble();
joint.aa = [buffer.readDouble(), buffer.readDouble()];
joint.ab = [buffer.readDouble(), buffer.readDouble()];
}
if (type == 3) {
physics.joints[i] = MapUtils.getNewLPJJoint();
let joint = physics.joints[i];
joint.pax = buffer.readDouble();
joint.pay = buffer.readDouble();
joint.pa = buffer.readDouble();
joint.pf = buffer.readDouble();
joint.pl = buffer.readDouble();
joint.pu = buffer.readDouble();
joint.plen = buffer.readDouble();
joint.pms = buffer.readDouble();
}
if (type == 4) {
physics.joints[i] = MapUtils.getNewLSJJoint();
let joint = physics.joints[i];
joint.sax = buffer.readDouble();
joint.say = buffer.readDouble();
joint.sf = buffer.readDouble();
joint.slen = buffer.readDouble();
}
if (type == 5) {
physics.joints[i] = MapUtils.getNewGearJoint();
let joint = physics.joints[i];
joint.n = buffer.readUTF();
joint.ja = buffer.readShort();
joint.jb = buffer.readShort();
joint.r = buffer.readDouble();
}
if (type != 5) {
physics.joints[i].ba = buffer.readShort();
physics.joints[i].bb = buffer.readShort();
physics.joints[i].d.cc = buffer.readBoolean();
physics.joints[i].d.bf = buffer.readDouble();
physics.joints[i].d.dl = buffer.readBoolean();
}
}
return level;
}
console.log(
decodeFromDatabase(
"ILAcJAhBFBjBzCTlMsSAlAlgIwMqQBWsAdgGoAuAmgLYAeADjjQlQEyMBaNV8AcgHdgAGQwANADYTYARgCckWnQAWAUxoBVFCjTAKAMVUB1MgC8xABn24A4voBsnaBEwzh8AKJIAwiADWwDZCugCSIEJewFqQiAASIIjezgDSIADOwAAiIHwgACxZQs6QXh6IACrozvrORuiwgSCc6AD2SAwgAFLA+tp9-f0AsgD0choAbjYMANTTACYUA0vLhfps2tn42oOQOM4oAjYWiMjZYoPbkDT726MTU7MLK8-aQTY29gx0AOwACpCZHDAHDfewhfQCCzlACuaRiVG0AlimSEp2AlkuAgCBzWG2BeEusFRyEOzRQZwsl0IAxGY0mM3mixezJAHkOnROqGAAENfCgdspoQBHWCqUwCaBsQ6zLCQWB8DzfABO6Mp-KIfQE+jkePKCL6mV+wzIwjoQoAZuMSHsWczIALhaLxZLpdNZfLFSqqNzLhZ9SSHHjYKZLvB-UgkSj+hpvL8LihoDA8bRtt5OvHkONhn5OHRzS1oXg8hkQCNwLaK0gUTZypyINkNOGIDs-AUEzZhnWQNluakUB5IOM27dy5XK5EKwOYojMtjkGhutop13lmhoE2q0ax2PdBW0L8V8ALlptNB9DZtGgAPI3F5n4QDUzDYnblm-YBkE-ILzQvrQJK2jsNiHtAHg+v0T4vq+Ly5LWlzAae2p4rk0HaJBqEshmtqgcOXJ4Lezxnuaj7PhhzLvhgfQ7NOZFASBmS4Sg6Fkc8743thAGYZANHIKBBHIMxLHLGx-FHsAaoJkm5LACh-JRH+mSiRAglCQMlTseqE4kopeKUSx2R6f2wDTDSwyjqp-Rsh4c5VsARiidRh5ajZLg9FRMBKduhrDBZyyUr+iLnkJAgeKJ2Trv03m+UsoAlJqHgXjowBFpcPFkVF0X9LFi44i50EhYxUDADlGxbplfSxRgTn6AF87Fe5OCHq+GXlSg4AAKzxZ5lZah0SURQaZWtagA54FB4T6A+SVkO5Y0sTs0CiQIs4keNrXvlQG7RQKIHWatw3IO+9mXFV82QGQ3X7QdEC5BgbTqqdCYeIVrUqQdWEsmeM0sgOWlIGeiV9G9w2XQMfGXlEW2-X++gvdksnfpgTVHmZ131stoPpTJfQDo9I5o92IW1a1aB3UuSNDKjBNsrETjSbAX5IAO7USRGsQla5qh9YjACea1IrA-FoLAeUQEk3gvah4tw8A76ptyf3IEkmSHtkBKpn4YT9OLqt2aLgzeEK919OLxu2VQPOpqYgva6BfJojgH2lt4ADMnDI0kHj27ZsBO0e3jfHBJt20GnX8t4wx8B7IfSXMjPNpkRBrSAyuK1kwCqFRmQq8nwDc1kZBkNCzD6BQnD2fAGhsMoyiwDYZDDN8wzNy3zeoua0yt63ciN13LcCJAvzmska1eJkhfFzQpfl9AlfV7X9e933pHAB3y+jEvfdCDQNjKCEu4QGE49FyXZcV1XNd1w3TfL+3nfLz3N9b8AO97wfpYFyfU9n7PF8L9f6877r0foAl+u994Jk-pPae5955X03l3IBD8EGt23uA9+8lj7QJ-nPS+i8n6IJAGvZBBDUFgLfigBEWDT4z1wf-FB-ciH3z7iA2+5CIHIAaNQ7+tC-7wNIYw1ezCu6sK3pAMQ2BDyIG4TA3+cD8GgKEcAhhbdxGSO0AEGROC+EKLYUokhgC1FYEPG0LRvD5EAL0cQlhKjnyQCVGYNOGQzGwLwZY5++ibECNUdCIw5QtYkigTQ1x9DvEr2sSI2xA9BjQFMH7SkLi5FuKiUw5RYTomxL9gURJdD+GKIid3KJ9jHHaHADknR7jCGeMiek+0mSkpBJ4SEvJVjhGFNqQ40wis4rlIsSk6p7TDGdO6UfCewSkmhPyW0luojEGQF8f4nQFxenJPSakgxt86lxJ0M4FZkzWlpKGSU+cWg9ktI8QUmZRSJHGJ0FQsZTSJnnKqZc5uszUHFK6ToLhDzZG5N0Rc6ZbyinDCoKYM2UBpG-O0X0tZAyrm1NBeCnQmjoXmNWVMw5t9vBYCwBoPKkBTFouaQCl5QKN7pJxXiglzjiVPNJWQ+FwLEVgohegIQZyGWCNeRSwBVL8U6ASXS-5lTGU8vef3flBLsnCoqf08VUTvDmgsHIcsNxIBlNlbCzFGyxFDxHhASIfJOWiu5eSiVqj9XEiNWPLVGKDm6rmVaw1KdRlfz+XKuFCranOtZCnZZdr9mAqxXq4e1qU67MDc8sV5qim+uAEa05UauVt3WV4wx8ajX3PdTC+1wbHUfMzSnH5Ob0VBrJSGp1YaXXAG8FC0tJLTWpqZbyzZRb0AlmOpAGQDbKiA2QMIFeLJhiSxAMMRwNBuBTpoIQYY5RBhxMXQugmK7IFrgHMAUCNaoBEiyNyNgDA0iHHgCuNAQdyImX6FmfowwLBLqXbnVdrVIgEV3IlSI0iQDFGcIlfQ2I5hkGYO1ZQOATB+CROBOq3JR39F+Jevo16+i3vvQuwYj6n2ZRfegTdG6irAAaHZYoPbsHl0qHMNlCbIBYACS8Ed2sqbkjnah+9GGn3FFZOul1fJIBkliGQIw7VoRUCMDICQnAdjQgo2eHULJMidn6IO5Ovw5DMdU6xldugX0bpuM4Rcf6QAAaAyBsDEGIZUCwLaODAxEPaGQ6puJ6H1OqSw+u3cuh7pduI8EsjFGBwc2eHRk2DHThMZQyGJzaN2OUZw1x4IvH+OCeE6J8TwAw5PVFksOTyNFN9GU-Z1DEXrqaa-dpiAzh4z6eAIZmgwHQNkD8KBUW8MKxWavT5JDd78uOcKxhFzOG3MgDVJ5htlEEYYUC9oCO5kqyhfsz1g6UXtMTjHogHjIA+MCaEyJsTP4FKYxC9lodh0VNhb9vNoSxX+ubrK7LEAlXqu1ZM0FaaLX4PaBsygOzKHuvne3H10CA3dzDZI344AGlEb+ZWBNlAU2DSzZY79zKi3ON+tCugeLm2ktiYWqJf8MG4eHaUyd-LiPoqXYB9dr9yU7v-sAzV4z9WtT9tct9N8b2UAfeQF91TP3Se2n+7h7D9oQDA+88AKgacBxGGRje0dsONjw+Y3z3yyOYt+t6Oj9bCWtvJZ2PAXH+hIMvCywpo7SA8uneV6pcnpWqffUq-oJUhwZCntVJZ9nmZ2u2c699q3QkBeA-1MdOyPkyT9kgJD5Y0OlbBZm-OsLfuhKq63eruLUAcCxUIFtRrtoTd9By9oC3JPE8YRt2uG7+oHfjCRFNOq+F3fWa959n3POS+9ap651ykBsTB6MD5OO2xxIVmjz4WP9ZFeLrbxhZPy3AirbJLsWKMglo6Vk-J-PZuIBF5Q1P6CZfKfXaBD0bE+hq98eQq9xvN6W8Pt36+APXfUS958tyByQ-bQj7FmP7sE-l13+3DPi6rEMULuhtolttilvYEJHntoAXigNvmpv-pWPvjphnDTiAGQFgMJnQGkKoH4HFIiJ0KzsbuvrAZviAAgUunfhcKzC8KEJ3mLIgMRHyCEM4BZt4BcIuBILWgiJ0EIPdPEFQPrJACQBZL0BTi4GQIIFQGIHMMTIlNkEgbaBHKjNADYBlroGdkoQMEaHYjyEpJELztoegLoZRvnLxOnMYS8PoM3OAGoRoR-FYc8DgKovoTjOEE4SsJAC3GYf0Lsp4SsCELYZuuoX0JoQEcsCQK4a-u4cAEYdod4FmD5AOOYf9JYREabqoaERDGJBkRBNEQYR4XkRsOaM3L4X+OkcUcgFeMEfYWEY4VUVzgUbEfEUoR4KYSkX4ZUY0SABgLUdkQ0loRkZAIOnoTEUuEUT0ayD4Z0RUYoVMSABoP0Q4bkQseIs0RMXEQsXdkkeUaeN0T0WIMsfUasVMUQBsUZFsZWMMNMHgLEN8GQKFBQDYB4B4HgK1qhB4PoIQB4GkKQXEbEAaq8LscsNAAALxglAA",
),
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment