diff --git a/resources/territory_patterns.json b/resources/territory_patterns.json index d8963a1bd..0cb33ebb0 100644 --- a/resources/territory_patterns.json +++ b/resources/territory_patterns.json @@ -1,100 +1,52 @@ { "patterns": { "stripes_v": { - "tileWidth": 2, - "tileHeight": 2, - "scale": 8, - "patternBase64": "oA==" + "patternBase64": "AQACAAIACKA=" }, "stripes_h": { - "tileWidth": 2, - "tileHeight": 2, - "scale": 8, - "patternBase64": "wA==" + "patternBase64": "AQACAAIACMA=" }, "checkerboard": { - "tileWidth": 2, - "tileHeight": 2, - "scale": 8, - "patternBase64": "kA==" + "patternBase64": "AQACAAIACJA=" }, "diagonal": { - "tileWidth": 16, - "tileHeight": 16, - "scale": 1, - "patternBase64": "gABAACAAEAAIAAQAAgABAACAAEAAIAAQAAgABAACAAE=" + "patternBase64": "AQAQABAAAYAAQAAgABAACAAEAAIAAQAAgABAACAAEAAIAAQAAgAB" }, "cross": { - "tileWidth": 16, - "tileHeight": 16, - "scale": 1, - "patternBase64": "gAFAAiAEEAgIEAQgAkABgAGAAkAEIAgQEAggBEACgAE=" + "patternBase64": "AQAQABAAAYABQAIgBBAICBAEIAJAAYABgAJABCAIEBAIIARAAoAB" }, "mini_cross": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "wAMwDAwwA8ADwAwwMAzAAw==" + "patternBase64": "AQAQAAgAAcADMAwMMAPAA8AMMDAMwAM=" }, "horizontal_stripes": { - "tileWidth": 16, - "tileHeight": 16, - "scale": 1, - "patternBase64": "//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAA=" + "patternBase64": "AQAQABAAAf//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA" }, "sparse_dots": { - "tileWidth": 16, - "tileHeight": 16, - "scale": 1, - "patternBase64": "gIAAAAAAAAAAAAAAAAAAAICAAAAAAAAAAAAAAAAAAAA=" + "patternBase64": "AQAQABAAAYCAAAAAAAAAAAAAAAAAAACAgAAAAAAAAAAAAAAAAAAA" }, "evan": { - "tileWidth": 24, - "tileHeight": 7, - "scale": 5, - "patternBase64": "AAAAeSMSQSSacSeWQMSSeMSSAAAA" + "patternBase64": "AQAYAAcABQAAAHkjEkEkmnEnlkDEknjEkgAAAA==" }, "diagonal_stripe": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "gAFAAiAEEAgIEAQgAkABgA==" + "patternBase64": "AQAQAAgAAYABQAIgBBAICBAEIAJAAYA=" }, "mountain_ridge": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "AAAYGDw8fn7//35+PDwYGA==" + "patternBase64": "AQAQAAgAAQAAGBg8PH5+//9+fjw8GBg=" }, "scattered_dots": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "AABABAAAAAAAAAAAEAgAAA==" + "patternBase64": "AQAQAAgAAQAAQAQAAAAAAAAAABAIAAA=" }, "circuit_board": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "w8PDwzAwMDAMMAwww8PDww==" + "patternBase64": "AQAQAAgAAcPDw8MwMDAwDDAMMMPDw8M=" }, "vertical_bars": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "kkmSSZJJkkmSSZJJkkmSSQ==" + "patternBase64": "AQAQAAgAAZJJkkmSSZJJkkmSSZJJkkk=" }, ".w.": { - "tileWidth": 16, - "tileHeight": 8, - "scale": 1, - "patternBase64": "AAAAAAAAQAJBgiJEdC5oFg==" + "patternBase64": "AQAQAAgAAQAAAAAAAEACQYIiRHQuaBY=" }, "openfront": { - "tileWidth": 66, - "tileHeight": 10, - "scale": 5, - "patternBase64": "AAAAAAAAAAAAAAAAAAAAAAHDj5EPnhxF8IkSBkIESJkQIkSBUIESJUQInjxMPHiJMQIkCBEIFCJEQIkCBEIEiJEQHED5EIERxEQAAAAAAAAAAAA=" + "patternBase64": "AQBCAAoABQAAAAAAAAAAAAAAAAAAAAABw4+RD54cRfCJEgZCBEiZECJEgVCBEiVECJ48TDx4iTECJAgRCBQiRECJAgRCBIiREBxA+RCBEcREAAAAAAAAAAAA" } } } diff --git a/src/client/TerritoryPatterns.ts b/src/client/TerritoryPatterns.ts index 50ac6ef75..20fd0689c 100644 --- a/src/client/TerritoryPatterns.ts +++ b/src/client/TerritoryPatterns.ts @@ -2,9 +2,9 @@ import { z } from "zod"; import rawTerritoryPatterns from "../../resources/territory_patterns.json"; const PatternSchema = z.object({ - tileWidth: z.number(), - tileHeight: z.number(), - scale: z.number(), + tileWidth: z.number().optional(), + tileHeight: z.number().optional(), + scale: z.number().optional(), pattern: z.array(z.array(z.number())).optional(), patternBase64: z.string().optional(), }); @@ -24,24 +24,39 @@ for (const [key, value] of Object.entries(territoryPatterns.patterns)) { bytes[i] = byteString.charCodeAt(i); } + const version = bytes[0]; + if (version !== 1) { + throw new Error("The pattern versions are different."); + } + const tileWidth = (bytes[1] << 8) | bytes[2]; + const tileHeight = (bytes[3] << 8) | bytes[4]; + const scale = (bytes[5] << 8) | bytes[6]; + + const totalBits = tileWidth * tileHeight; + const totalBytes = Math.ceil(totalBits / 8); + const data = bytes.slice(7, 7 + totalBytes); + const bits: number[] = []; - for (const byte of bytes) { + for (const byte of data) { for (let i = 7; i >= 0; i--) { bits.push((byte >> i) & 1); } } const pattern: number[][] = []; - for (let y = 0; y < value.tileHeight; y++) { + for (let y = 0; y < tileHeight; y++) { const row: number[] = []; - for (let x = 0; x < value.tileWidth; x++) { - const index = y * value.tileWidth + x; + for (let x = 0; x < tileWidth; x++) { + const index = y * tileWidth + x; row.push(bits[index] ?? 0); } pattern.push(row); } value.pattern = pattern; + value.tileWidth = tileWidth; + value.tileHeight = tileHeight; + value.scale = scale; } } diff --git a/src/client/TerritoryPatternsModal.ts b/src/client/TerritoryPatternsModal.ts index 08e29a851..6c238e90d 100644 --- a/src/client/TerritoryPatternsModal.ts +++ b/src/client/TerritoryPatternsModal.ts @@ -48,27 +48,6 @@ export class territoryPatternsModal extends LitElement { this.updatePreview(); }); - for (const [key, p] of Object.entries(territoryPatterns.patterns)) { - if (!p.pattern && p.patternBase64) { - const bytes = Uint8Array.from(atob(p.patternBase64), (c) => - c.charCodeAt(0), - ); - const bits = Array.from(bytes).flatMap((byte) => - [...Array(8)].map((_, i) => (byte >> (7 - i)) & 1), - ); - const pattern: number[][] = []; - for (let y = 0; y < p.tileHeight; y++) { - const row: number[] = []; - for (let x = 0; x < p.tileWidth; x++) { - const index = y * p.tileWidth + x; - row.push(bits[index] ?? 0); - } - pattern.push(row); - } - p.pattern = pattern; - } - } - this.setLockedPatterns(["evan"], { evan: "This pattern is locked because it is restricted.", }); @@ -133,8 +112,8 @@ export class territoryPatternsModal extends LitElement { " > ${(() => { - const cellCountX = pattern.tileWidth; - const cellCountY = pattern.tileHeight; + const cellCountX = pattern.tileWidth ?? 1; + const cellCountY = pattern.tileHeight ?? 1; const cellSize = Math.floor( this.buttonWidth / Math.max(cellCountX, cellCountY), ); @@ -200,8 +179,8 @@ export class territoryPatternsModal extends LitElement { const fixedHeight = 48; const fixedWidth = 48; - const cellCountX = pattern.tileWidth; - const cellCountY = pattern.tileHeight; + const cellCountX = pattern.tileWidth ?? 1; + const cellCountY = pattern.tileHeight ?? 1; const cellSize = Math.min( fixedHeight / cellCountY, diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts index 218112a90..d9d29be56 100644 --- a/src/client/graphics/layers/TerritoryLayer.ts +++ b/src/client/graphics/layers/TerritoryLayer.ts @@ -301,7 +301,12 @@ export class TerritoryLayer implements Layer { const baseColor = this.theme.territoryColor(owner); const patternConfig = territoryPatterns.patterns[patternName]; - const { tileWidth, tileHeight, scale, pattern } = patternConfig; + const { + tileWidth = 1, + tileHeight = 1, + scale = 1, + pattern, + } = patternConfig; const px = Math.floor(x / scale) % tileWidth; const py = Math.floor(y / scale) % tileHeight;