mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 21:44:49 +00:00
4680b04656
## Description: - Refactor cosmetics.json to use base64 as the lookup key, to reduce the complexity of lookup. - Add refine() logic to PatternSchema to check if the pattern is valid. - Split PatternDecoder class out of Cosmetic.ts to resolve temporal deadzone caused by static parsing of cosmetics.json with the new refine(). ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors
62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
import { base64url } from "jose";
|
|
|
|
export class PatternDecoder {
|
|
private bytes: Uint8Array;
|
|
private tileWidth: number;
|
|
private tileHeight: number;
|
|
private scale: number;
|
|
|
|
constructor(base64: string) {
|
|
this.bytes = base64url.decode(base64);
|
|
|
|
if (this.bytes.length < 3) {
|
|
throw new Error(
|
|
"Pattern data is too short to contain required metadata.",
|
|
);
|
|
}
|
|
|
|
const version = this.bytes[0];
|
|
if (version !== 0) {
|
|
throw new Error(`Unrecognized pattern version ${version}.`);
|
|
}
|
|
|
|
const byte1 = this.bytes[1];
|
|
const byte2 = this.bytes[2];
|
|
this.scale = byte1 & 0x07;
|
|
|
|
this.tileWidth = (((byte2 & 0x03) << 5) | ((byte1 >> 3) & 0x1f)) + 2;
|
|
this.tileHeight = ((byte2 >> 2) & 0x3f) + 2;
|
|
|
|
const expectedBits = this.tileWidth * this.tileHeight;
|
|
const expectedBytes = (expectedBits + 7) >> 3; // Equivalent to: ceil(expectedBits / 8);
|
|
if (this.bytes.length - 3 < expectedBytes) {
|
|
throw new Error(
|
|
"Pattern data is too short for the specified dimensions.",
|
|
);
|
|
}
|
|
}
|
|
|
|
getTileWidth(): number {
|
|
return this.tileWidth;
|
|
}
|
|
|
|
getTileHeight(): number {
|
|
return this.tileHeight;
|
|
}
|
|
|
|
getScale(): number {
|
|
return this.scale;
|
|
}
|
|
|
|
isSet(x: number, y: number): boolean {
|
|
const px = (x >> this.scale) % this.tileWidth;
|
|
const py = (y >> this.scale) % this.tileHeight;
|
|
const idx = py * this.tileWidth + px;
|
|
const byteIndex = idx >> 3;
|
|
const bitIndex = idx & 7;
|
|
const byte = this.bytes[3 + byteIndex];
|
|
if (byte === undefined) throw new Error("Invalid pattern");
|
|
return (byte & (1 << bitIndex)) !== 0;
|
|
}
|
|
}
|