A Deno-powered backend service for Plants vs. Zombies: MODDED. [Read-only GitHub mirror] docs.pvzm.net
express typescript expressjs plant deno jspvz pvzm game online backend plants-vs-zombies zombie javascript plants modded vs plantsvszombies openapi pvz noads
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Format "v0.2.0 - modifying a levels metadata now also affects the level data - if github auth is disabled, dont show a login prompt on the admin page - fix incorrect plants map - clean up decoder/encoder" Original commit: https://github.com/ROBlNET13/pvzm-backend/commit/4e92302694f3882547820944fb42cd7b931de619

Co-authored-by: ClaytonTDM <clay@clay.rip>

+64 -74
+59 -59
README.md
··· 92 92 - **Code:** 201 93 93 - **Content:** 94 94 95 - ```json 96 - { 97 - "id": 123, 98 - "name": "Level Name", 99 - "author": "Author Name", 100 - "created_at": 1714680000, 101 - "sun": 100, 102 - "is_water": true, 103 - "version": 3 104 - } 105 - ``` 95 + ```json 96 + { 97 + "id": 123, 98 + "name": "Level Name", 99 + "author": "Author Name", 100 + "created_at": 1714680000, 101 + "sun": 100, 102 + "is_water": true, 103 + "version": 3 104 + } 105 + ``` 106 106 107 - Note: `is_water` is stored as `0/1` in the database and is returned as `0/1` in list/detail endpoints. 107 + Note: `is_water` is stored as `0/1` in the database and is returned as `0/1` in list/detail endpoints. 108 108 109 109 - **Error Responses:** 110 110 - **Code:** 400 ··· 136 136 - **Code:** 200 137 137 - **Content:** 138 138 139 - ```json 140 - { 141 - "levels": [ 142 - { 143 - "id": 123, 144 - "name": "Level Name", 145 - "author": "Author Name", 146 - "created_at": 1714680000, 147 - "sun": 100, 148 - "is_water": 1, 149 - "favorites": 5, 150 - "plays": 10, 151 - "difficulty": 7, 152 - "thumbnail": [[0, 10, 10, 40, 40, 1]], 153 - "version": 3 154 - } 155 - ], 156 - "pagination": { 157 - "total": 50, 158 - "page": 1, 159 - "limit": 10, 160 - "pages": 5 161 - } 162 - } 163 - ``` 139 + ```json 140 + { 141 + "levels": [ 142 + { 143 + "id": 123, 144 + "name": "Level Name", 145 + "author": "Author Name", 146 + "created_at": 1714680000, 147 + "sun": 100, 148 + "is_water": 1, 149 + "favorites": 5, 150 + "plays": 10, 151 + "difficulty": 7, 152 + "thumbnail": [[0, 10, 10, 40, 40, 1]], 153 + "version": 3 154 + } 155 + ], 156 + "pagination": { 157 + "total": 50, 158 + "page": 1, 159 + "limit": 10, 160 + "pages": 5 161 + } 162 + } 163 + ``` 164 164 165 165 - **Error Response:** 166 166 - **Code:** 401 ··· 178 178 - **Code:** 200 179 179 - **Content:** 180 180 181 - ```json 182 - { 183 - "id": 123, 184 - "name": "Level Name", 185 - "author": "Author Name", 186 - "created_at": 1714680000, 187 - "sun": 100, 188 - "is_water": 1, 189 - "favorites": 5, 190 - "plays": 10, 191 - "difficulty": 7, 192 - "thumbnail": null, 193 - "version": 3 194 - } 195 - ``` 181 + ```json 182 + { 183 + "id": 123, 184 + "name": "Level Name", 185 + "author": "Author Name", 186 + "created_at": 1714680000, 187 + "sun": 100, 188 + "is_water": 1, 189 + "favorites": 5, 190 + "plays": 10, 191 + "difficulty": 7, 192 + "thumbnail": null, 193 + "version": 3 194 + } 195 + ``` 196 196 197 197 - **Error Responses:** 198 198 - **Code:** 400 ··· 281 281 - **Code:** 200 282 282 - **Content:** 283 283 284 - ```json 285 - { 286 - "turnstileEnabled": true, 287 - "turnstileSiteKey": "0x0000000000000000000000", 288 - "moderationEnabled": true 289 - } 290 - ``` 284 + ```json 285 + { 286 + "turnstileEnabled": true, 287 + "turnstileSiteKey": "0x0000000000000000000000", 288 + "moderationEnabled": true 289 + } 290 + ``` 291 291 292 292 ## Environment Variables 293 293
+5 -15
modules/levels_io.ts
··· 26 26 27 27 export const IZL3_HEADER = new Uint8Array([0x49, 0x5a, 0x4c, 0x33]); // "IZL3" 28 28 29 - type DecodeLevelResult = 30 - | { decoded: ReturnType<typeof decodeFile>; decodeError: null } 31 - | { decoded: null; decodeError: string }; 29 + type DecodeLevelResult = { decoded: ReturnType<typeof decodeFile>; decodeError: null } | { decoded: null; decodeError: string }; 32 30 33 31 export async function decodeLevelFromDisk(dataFolderPath: string, levelId: number, version: number): Promise<DecodeLevelResult> { 34 32 try { ··· 64 62 eleHeight: 15, 65 63 }; 66 64 67 - const REVERSE_TINYIFIER_MAP: Record<number, string> = Object.fromEntries( 68 - Object.entries(TINYIFIER_MAP).map(([key, value]) => [value, key]) 69 - ); 65 + const REVERSE_TINYIFIER_MAP: Record<number, string> = Object.fromEntries(Object.entries(TINYIFIER_MAP).map(([key, value]) => [value, key])); 70 66 71 67 export const allPlantsStringArray = [ 72 68 "oPeashooter", ··· 205 201 if (Array.isArray(obj)) { 206 202 return obj.map((item) => reverseKeys(item)); 207 203 } 208 - 204 + 209 205 if (obj !== null && typeof obj === "object") { 210 206 const result: any = {}; 211 207 for (const [key, value] of Object.entries(obj)) { ··· 219 215 } 220 216 return result; 221 217 } 222 - 218 + 223 219 return obj; 224 220 } 225 221 ··· 355 351 } 356 352 357 353 export function detectFileVersion(bytes: Uint8Array): number { 358 - if ( 359 - bytes.length >= 4 && 360 - bytes[0] === IZL3_HEADER[0] && 361 - bytes[1] === IZL3_HEADER[1] && 362 - bytes[2] === IZL3_HEADER[2] && 363 - bytes[3] === IZL3_HEADER[3] 364 - ) { 354 + if (bytes.length >= 4 && bytes[0] === IZL3_HEADER[0] && bytes[1] === IZL3_HEADER[1] && bytes[2] === IZL3_HEADER[2] && bytes[3] === IZL3_HEADER[3]) { 365 355 return 3; 366 356 } 367 357