@aethervtt/shard-sprite 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/baseline/lights2d.d.ts +6 -0
- package/dist/baseline/lights2d.js +114 -0
- package/dist/ground.d.ts +81 -0
- package/dist/ground.js +394 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +52 -2
- package/dist/lighting-shaders.js +4 -4
- package/dist/lights2d.d.ts +23 -7
- package/dist/lights2d.js +78 -40
- package/dist/methods.d.ts +82 -0
- package/dist/methods.js +246 -0
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.js +43 -6
- package/dist/render.d.ts +19 -7
- package/dist/render.js +60 -51
- package/dist/shaders.js +11 -6
- package/dist/tilemap-format.d.ts +39 -0
- package/dist/tilemap-format.js +177 -0
- package/dist/tilemap.d.ts +83 -12
- package/dist/tilemap.js +311 -58
- package/dist/validate.d.ts +11 -0
- package/dist/validate.js +49 -0
- package/package.json +9 -9
package/dist/shaders.js
CHANGED
|
@@ -113,8 +113,8 @@ struct SpriteRecord {
|
|
|
113
113
|
_pad1: u32,
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
@group(1) @binding(0) var<storage, read> sprites: array<SpriteRecord>;
|
|
117
|
-
@group(1) @binding(1) var<storage, read> order: array<u32>;
|
|
116
|
+
@data @group(1) @binding(0) var<storage, read> sprites: array<SpriteRecord>;
|
|
117
|
+
@data @group(1) @binding(1) var<storage, read> order: array<u32>;
|
|
118
118
|
|
|
119
119
|
@vertex fn vs(@builtin(vertex_index) v: u32, @builtin(instance_index) i: u32) -> SpriteOutput {
|
|
120
120
|
let s = sprites[order[i]];
|
|
@@ -189,10 +189,10 @@ struct TilemapParams {
|
|
|
189
189
|
chunks: vec4u,
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
@group(1) @binding(0) var<storage, read> tiles: array<u32>;
|
|
193
|
-
@group(1) @binding(1) var<storage, read> visible_chunks: array<u32>;
|
|
194
|
-
@group(1) @binding(2) var<storage, read> regions: array<vec4f>;
|
|
195
|
-
@group(1) @binding(3) var<storage, read> remap: array<u32>;
|
|
192
|
+
@data @group(1) @binding(0) var<storage, read> tiles: array<u32>;
|
|
193
|
+
@data @group(1) @binding(1) var<storage, read> visible_chunks: array<u32>;
|
|
194
|
+
@data @group(1) @binding(2) var<storage, read> regions: array<vec4f>;
|
|
195
|
+
@data @group(1) @binding(3) var<storage, read> remap: array<u32>;
|
|
196
196
|
@group(1) @binding(4) var<uniform> map: TilemapParams;
|
|
197
197
|
|
|
198
198
|
/**
|
|
@@ -217,6 +217,11 @@ struct TilemapParams {
|
|
|
217
217
|
return out;
|
|
218
218
|
}
|
|
219
219
|
let tile = remap[min(raw, arrayLength(&remap) - 1u)];
|
|
220
|
+
// A palette name the atlas lacks resolves to 0: nothing to draw.
|
|
221
|
+
if (tile == 0u) {
|
|
222
|
+
out.clip = vec4f(0.0, 0.0, 0.0, 0.0);
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
220
225
|
let flags = value >> 16u;
|
|
221
226
|
let c = corner(v);
|
|
222
227
|
// Tile (x, y) covers [x, x + 1] \xD7 [-y - 1, -y] in tile units.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Tile flag bits (shared with the renderer). */
|
|
2
|
+
export declare const TILE_FLAG_NAMES: {
|
|
3
|
+
readonly fx: 1;
|
|
4
|
+
readonly fy: 2;
|
|
5
|
+
readonly r90: 4;
|
|
6
|
+
};
|
|
7
|
+
export type TileEncoding = 'rows' | 'base64';
|
|
8
|
+
/** What a layer's cells are in memory: tile ids (palette index + 1, 0 empty) and flag bits. */
|
|
9
|
+
export interface CellGrid {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
tiles: Uint16Array;
|
|
13
|
+
flags: Uint8Array;
|
|
14
|
+
}
|
|
15
|
+
/** Whether a palette name can be written in rows (no spaces or the run syntax's characters). */
|
|
16
|
+
export declare function rowsCanName(name: string): boolean;
|
|
17
|
+
/** The rows of one chunk: `chunkSize` cells a row at most, rows from the top. Undefined if empty. */
|
|
18
|
+
export declare function chunkRows(grid: CellGrid, palette: readonly string[], cx: number, cy: number, chunkSize: number): string[] | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* The cells of a w × h rectangle as rows, in the rows syntax (`tilemap.read` with a rect), and
|
|
21
|
+
* whether any cell is filled. The rectangle must lie inside the grid.
|
|
22
|
+
*/
|
|
23
|
+
export declare function rectRows(grid: CellGrid, palette: readonly string[], x0: number, y0: number, w: number, h: number): {
|
|
24
|
+
rows: string[];
|
|
25
|
+
any: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Reads one chunk's rows into the grid. Unknown names are added to the palette (the caller
|
|
29
|
+
* checks them against the atlas); `path` is the chunk's JSON pointer.
|
|
30
|
+
*/
|
|
31
|
+
export declare function readChunkRows(grid: CellGrid, palette: string[], index: Map<string, number>, cx: number, cy: number, chunkSize: number, rows: unknown, path: string): void;
|
|
32
|
+
/** All non-empty chunks of a layer as rows, keyed "cx,cy" in row-major order. */
|
|
33
|
+
export declare function layerChunks(grid: CellGrid, palette: readonly string[], chunkSize: number): Record<string, string[]>;
|
|
34
|
+
export declare function fromBase64(s: string): Uint8Array;
|
|
35
|
+
export declare function toBase64(bytes: Uint8Array): string;
|
|
36
|
+
/** A layer's tile ids as base64 of little-endian u16s. */
|
|
37
|
+
export declare function tilesToBase64(tiles: Uint16Array): string;
|
|
38
|
+
export declare function tilesFromBase64(s: string, n: number, path: string, name: string): Uint16Array;
|
|
39
|
+
export declare function flagsFromBase64(s: string, n: number, path: string, name: string): Uint8Array;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { ShardError } from "@aethervtt/shard-core";
|
|
2
|
+
const TILE_FLAG_NAMES = { fx: 1, fy: 2, r90: 4 };
|
|
3
|
+
function invalid(message, path, hint) {
|
|
4
|
+
return new ShardError("sprite/invalid-tilemap", message, {
|
|
5
|
+
path,
|
|
6
|
+
hint: hint ?? 'Rows are space-separated runs of name[:flags][*count]; flags are fx, fy and r90 joined by +; "." is an empty cell.'
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function rowsCanName(name) {
|
|
10
|
+
return name.length > 0 && name !== "." && !/[\s:*+]/.test(name);
|
|
11
|
+
}
|
|
12
|
+
function flagText(flags) {
|
|
13
|
+
const parts = [];
|
|
14
|
+
if (flags & 1) parts.push("fx");
|
|
15
|
+
if (flags & 2) parts.push("fy");
|
|
16
|
+
if (flags & 4) parts.push("r90");
|
|
17
|
+
return parts.join("+");
|
|
18
|
+
}
|
|
19
|
+
function chunkRows(grid, palette, cx, cy, chunkSize) {
|
|
20
|
+
const x0 = cx * chunkSize;
|
|
21
|
+
const y0 = cy * chunkSize;
|
|
22
|
+
const { rows, any } = rectRows(
|
|
23
|
+
grid,
|
|
24
|
+
palette,
|
|
25
|
+
x0,
|
|
26
|
+
y0,
|
|
27
|
+
Math.min(chunkSize, grid.width - x0),
|
|
28
|
+
Math.min(chunkSize, grid.height - y0)
|
|
29
|
+
);
|
|
30
|
+
return any ? rows : void 0;
|
|
31
|
+
}
|
|
32
|
+
function rectRows(grid, palette, x0, y0, w, h) {
|
|
33
|
+
let any = false;
|
|
34
|
+
const rows = [];
|
|
35
|
+
for (let ly = 0; ly < h; ly++) {
|
|
36
|
+
const runs = [];
|
|
37
|
+
let token = "";
|
|
38
|
+
let count = 0;
|
|
39
|
+
for (let lx = 0; lx < w; lx++) {
|
|
40
|
+
const i = (y0 + ly) * grid.width + x0 + lx;
|
|
41
|
+
const id = grid.tiles[i];
|
|
42
|
+
let t;
|
|
43
|
+
if (id === 0) t = ".";
|
|
44
|
+
else {
|
|
45
|
+
any = true;
|
|
46
|
+
const name = palette[id - 1];
|
|
47
|
+
if (name === void 0) throw invalid(`Tile id ${id} has no palette entry`, `/palette`);
|
|
48
|
+
const f = grid.flags[i];
|
|
49
|
+
t = f ? `${name}:${flagText(f)}` : name;
|
|
50
|
+
}
|
|
51
|
+
if (t === token) count++;
|
|
52
|
+
else {
|
|
53
|
+
if (count > 0) runs.push(count > 1 ? `${token}*${count}` : token);
|
|
54
|
+
token = t;
|
|
55
|
+
count = 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (count > 0) runs.push(count > 1 ? `${token}*${count}` : token);
|
|
59
|
+
rows.push(runs.join(" "));
|
|
60
|
+
}
|
|
61
|
+
return { rows, any };
|
|
62
|
+
}
|
|
63
|
+
function readChunkRows(grid, palette, index, cx, cy, chunkSize, rows, path) {
|
|
64
|
+
if (!Array.isArray(rows)) throw invalid("Expected a list of rows", path);
|
|
65
|
+
const x0 = cx * chunkSize;
|
|
66
|
+
const y0 = cy * chunkSize;
|
|
67
|
+
const w = Math.min(chunkSize, grid.width - x0);
|
|
68
|
+
const h = Math.min(chunkSize, grid.height - y0);
|
|
69
|
+
if (w <= 0 || h <= 0) throw invalid(`Chunk ${cx},${cy} is outside the layer`, path);
|
|
70
|
+
if (rows.length > h) throw invalid(`Chunk has ${rows.length} rows; it can hold ${h}`, path);
|
|
71
|
+
for (let ly = 0; ly < rows.length; ly++) {
|
|
72
|
+
const row = rows[ly];
|
|
73
|
+
const at = `${path}/${ly}`;
|
|
74
|
+
if (typeof row !== "string") throw invalid("Expected a row string", at);
|
|
75
|
+
let lx = 0;
|
|
76
|
+
const runs = row.trim() === "" ? [] : row.trim().split(/\s+/);
|
|
77
|
+
for (const run of runs) {
|
|
78
|
+
const star = run.lastIndexOf("*");
|
|
79
|
+
const body = star === -1 ? run : run.slice(0, star);
|
|
80
|
+
const count = star === -1 ? 1 : Number(run.slice(star + 1));
|
|
81
|
+
if (!Number.isInteger(count) || count < 1) {
|
|
82
|
+
throw invalid(`Bad run count in "${run}" (column ${lx + 1})`, at);
|
|
83
|
+
}
|
|
84
|
+
let id = 0;
|
|
85
|
+
let flags = 0;
|
|
86
|
+
if (body !== ".") {
|
|
87
|
+
const colon = body.indexOf(":");
|
|
88
|
+
const name = colon === -1 ? body : body.slice(0, colon);
|
|
89
|
+
if (!rowsCanName(name)) throw invalid(`Bad tile name in "${run}" (column ${lx + 1})`, at);
|
|
90
|
+
if (colon !== -1) {
|
|
91
|
+
for (const f of body.slice(colon + 1).split("+")) {
|
|
92
|
+
const bit = TILE_FLAG_NAMES[f];
|
|
93
|
+
if (!bit) throw invalid(`Unknown flag "${f}" in "${run}" (column ${lx + 1})`, at);
|
|
94
|
+
flags |= bit;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
let p = index.get(name);
|
|
98
|
+
if (p === void 0) {
|
|
99
|
+
p = palette.length;
|
|
100
|
+
palette.push(name);
|
|
101
|
+
index.set(name, p);
|
|
102
|
+
}
|
|
103
|
+
id = p + 1;
|
|
104
|
+
}
|
|
105
|
+
if (lx + count > w) throw invalid(`Row has more than ${w} cells`, at);
|
|
106
|
+
for (let k = 0; k < count; k++) {
|
|
107
|
+
const i = (y0 + ly) * grid.width + x0 + lx + k;
|
|
108
|
+
grid.tiles[i] = id;
|
|
109
|
+
grid.flags[i] = flags;
|
|
110
|
+
}
|
|
111
|
+
lx += count;
|
|
112
|
+
}
|
|
113
|
+
if (lx !== 0 && lx !== w) throw invalid(`Row has ${lx} cells; it needs ${w}`, at);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function layerChunks(grid, palette, chunkSize) {
|
|
117
|
+
const out = {};
|
|
118
|
+
const cols = Math.ceil(grid.width / chunkSize);
|
|
119
|
+
const rowsOfChunks = Math.ceil(grid.height / chunkSize);
|
|
120
|
+
for (let cy = 0; cy < rowsOfChunks; cy++) {
|
|
121
|
+
for (let cx = 0; cx < cols; cx++) {
|
|
122
|
+
const rows = chunkRows(grid, palette, cx, cy, chunkSize);
|
|
123
|
+
if (rows) out[`${cx},${cy}`] = rows;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
function fromBase64(s) {
|
|
129
|
+
const bin = atob(s);
|
|
130
|
+
const out = new Uint8Array(bin.length);
|
|
131
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
function toBase64(bytes) {
|
|
135
|
+
let s = "";
|
|
136
|
+
for (let i = 0; i < bytes.length; i += 32768) {
|
|
137
|
+
s += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
138
|
+
}
|
|
139
|
+
return btoa(s);
|
|
140
|
+
}
|
|
141
|
+
function tilesToBase64(tiles) {
|
|
142
|
+
const bytes = new Uint8Array(tiles.length * 2);
|
|
143
|
+
const view = new DataView(bytes.buffer);
|
|
144
|
+
for (let k = 0; k < tiles.length; k++) view.setUint16(k * 2, tiles[k], true);
|
|
145
|
+
return toBase64(bytes);
|
|
146
|
+
}
|
|
147
|
+
function tilesFromBase64(s, n, path, name) {
|
|
148
|
+
const bytes = fromBase64(s);
|
|
149
|
+
if (bytes.length !== n * 2) {
|
|
150
|
+
throw invalid(`Layer "${name}" has ${bytes.length / 2} tiles; it needs ${n}`, path);
|
|
151
|
+
}
|
|
152
|
+
const tiles = new Uint16Array(n);
|
|
153
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
154
|
+
for (let k = 0; k < n; k++) tiles[k] = view.getUint16(k * 2, true);
|
|
155
|
+
return tiles;
|
|
156
|
+
}
|
|
157
|
+
function flagsFromBase64(s, n, path, name) {
|
|
158
|
+
if (!s) return new Uint8Array(n);
|
|
159
|
+
const flags = fromBase64(s);
|
|
160
|
+
if (flags.length !== n) {
|
|
161
|
+
throw invalid(`Layer "${name}" has ${flags.length} flag bytes; it needs ${n}`, path);
|
|
162
|
+
}
|
|
163
|
+
return flags;
|
|
164
|
+
}
|
|
165
|
+
export {
|
|
166
|
+
TILE_FLAG_NAMES,
|
|
167
|
+
chunkRows,
|
|
168
|
+
flagsFromBase64,
|
|
169
|
+
fromBase64,
|
|
170
|
+
layerChunks,
|
|
171
|
+
readChunkRows,
|
|
172
|
+
rectRows,
|
|
173
|
+
rowsCanName,
|
|
174
|
+
tilesFromBase64,
|
|
175
|
+
tilesToBase64,
|
|
176
|
+
toBase64
|
|
177
|
+
};
|
package/dist/tilemap.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AssetStore } from '@aethervtt/shard-assets';
|
|
2
|
-
import { type AssetRef, type Entity, type World } from '@aethervtt/shard-core';
|
|
2
|
+
import { type AssetRef, type Entity, ShardError, type World } from '@aethervtt/shard-core';
|
|
3
|
+
import { type TileEncoding } from './tilemap-format.js';
|
|
3
4
|
/** Tile flag bits. */
|
|
4
5
|
export declare const TileFlags: {
|
|
5
6
|
readonly FlipX: 1;
|
|
@@ -7,17 +8,22 @@ export declare const TileFlags: {
|
|
|
7
8
|
readonly Rotate90: 4;
|
|
8
9
|
};
|
|
9
10
|
export declare const TilemapDataSchema: import("@aethervtt/shard-core").ComponentDef<{
|
|
11
|
+
readonly version: import("@aethervtt/shard-core").FieldType<number, "u8">;
|
|
12
|
+
readonly encoding: import("@aethervtt/shard-core").FieldType<"base64" | "rows", "u8">;
|
|
13
|
+
readonly chunkSize: import("@aethervtt/shard-core").FieldType<number, "u16">;
|
|
14
|
+
readonly palette: import("@aethervtt/shard-core").FieldType<string[], "object">;
|
|
10
15
|
readonly layers: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
11
16
|
name: import("@aethervtt/shard-core").FieldType<string, "object">;
|
|
12
17
|
width: import("@aethervtt/shard-core").FieldType<number, "u32">;
|
|
13
18
|
height: import("@aethervtt/shard-core").FieldType<number, "u32">;
|
|
14
19
|
tiles: import("@aethervtt/shard-core").FieldType<string, "object">;
|
|
15
20
|
flags: import("@aethervtt/shard-core").FieldType<string, "object">;
|
|
21
|
+
chunks: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").JsonValue, "object">;
|
|
16
22
|
occludes: import("@aethervtt/shard-core").FieldType<boolean, "u8">;
|
|
17
23
|
}>[], "object">;
|
|
18
24
|
readonly animations: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
19
|
-
tile: import("@aethervtt/shard-core").FieldType<
|
|
20
|
-
frames: import("@aethervtt/shard-core").FieldType<
|
|
25
|
+
tile: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").JsonValue, "object">;
|
|
26
|
+
frames: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").JsonValue[], "object">;
|
|
21
27
|
frameTime: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
22
28
|
}>[], "object">;
|
|
23
29
|
}>;
|
|
@@ -45,31 +51,88 @@ export declare class TilemapData {
|
|
|
45
51
|
frames: number[];
|
|
46
52
|
frameTime: number;
|
|
47
53
|
}[];
|
|
54
|
+
/**
|
|
55
|
+
* Atlas region names: tile id N draws the region named `palette[N - 1]` (0059). Undefined for
|
|
56
|
+
* maps made before palettes, whose ids are atlas regions + 1.
|
|
57
|
+
*/
|
|
58
|
+
palette: string[] | undefined;
|
|
59
|
+
/** How the map is saved: readable rows (the default) or compact base64. */
|
|
60
|
+
encoding: TileEncoding;
|
|
61
|
+
/** Tiles per chunk side in the rows encoding. */
|
|
62
|
+
chunkSize: number;
|
|
48
63
|
/** Bumps when the layers are replaced (hot reload). */
|
|
49
64
|
version: number;
|
|
50
|
-
constructor(layers?: TileLayer[], animations?: TilemapData['animations']);
|
|
51
|
-
/**
|
|
52
|
-
|
|
65
|
+
constructor(layers?: TileLayer[], animations?: TilemapData['animations'], palette?: string[]);
|
|
66
|
+
/**
|
|
67
|
+
* An empty map of `layers` layers, width × height tiles each. With a palette, tile ids name its
|
|
68
|
+
* entries; without, they're atlas regions + 1.
|
|
69
|
+
*/
|
|
70
|
+
static create(width: number, height: number, layers?: string[], palette?: string[]): TilemapData;
|
|
71
|
+
/** The id of a palette name, adding it to the palette if it's new. Needs a palette. */
|
|
72
|
+
tileId(name: string): number;
|
|
73
|
+
/** The name a tile id draws: through the palette, or the atlas for version 1 maps. */
|
|
74
|
+
tileName(id: number, atlas?: {
|
|
75
|
+
names: readonly string[];
|
|
76
|
+
}): string | undefined;
|
|
77
|
+
/** A map from its file's JSON (`$schema`, an editor's pointer, is ignored). */
|
|
53
78
|
static fromJson(json: unknown): TilemapData;
|
|
54
|
-
|
|
55
|
-
|
|
79
|
+
/**
|
|
80
|
+
* The map as version 2 JSON, in its encoding (or `options.encoding`). A version 1 map needs its
|
|
81
|
+
* atlas to name its tiles; its palette lists them in first use order. A map with a palette keeps
|
|
82
|
+
* it in order, so an edit that uses a known tile changes one row.
|
|
83
|
+
*/
|
|
84
|
+
toJson(options?: {
|
|
85
|
+
encoding?: TileEncoding;
|
|
86
|
+
atlas?: {
|
|
87
|
+
names: readonly string[];
|
|
88
|
+
};
|
|
89
|
+
}): {
|
|
90
|
+
version: number;
|
|
91
|
+
encoding: TileEncoding;
|
|
92
|
+
chunkSize?: number | undefined;
|
|
93
|
+
palette: string[];
|
|
94
|
+
layers: ({
|
|
56
95
|
name: string;
|
|
57
96
|
width: number;
|
|
58
97
|
height: number;
|
|
98
|
+
chunks: Record<string, string[]>;
|
|
99
|
+
tiles?: undefined;
|
|
100
|
+
flags?: undefined;
|
|
101
|
+
occludes?: boolean | undefined;
|
|
102
|
+
} | {
|
|
103
|
+
name: string;
|
|
104
|
+
width: number;
|
|
105
|
+
height: number;
|
|
106
|
+
chunks?: undefined;
|
|
59
107
|
tiles: string;
|
|
60
108
|
flags: string;
|
|
61
109
|
occludes?: boolean | undefined;
|
|
62
|
-
}[];
|
|
110
|
+
})[];
|
|
63
111
|
animations: {
|
|
64
|
-
tile:
|
|
65
|
-
frames:
|
|
112
|
+
tile: string;
|
|
113
|
+
frames: string[];
|
|
66
114
|
frameTime: number;
|
|
67
115
|
}[];
|
|
68
116
|
};
|
|
117
|
+
private sameAs;
|
|
69
118
|
/** The largest tile index any layer uses (for validating against an atlas). */
|
|
70
119
|
maxTile(): number;
|
|
120
|
+
/** Takes another map's content (hot reload). Identical content (a save reloading) changes nothing. */
|
|
71
121
|
copyFrom(other: TilemapData): void;
|
|
72
122
|
}
|
|
123
|
+
/** The palette itself when the map has one; else the atlas's names (version 1 ids are regions + 1). */
|
|
124
|
+
export declare function tileNames(data: TilemapData, atlas?: {
|
|
125
|
+
names: readonly string[];
|
|
126
|
+
}): readonly string[];
|
|
127
|
+
/** A tilemap file's text: its JSON, two-space indented, a newline at the end. */
|
|
128
|
+
export declare function tilemapToText(data: TilemapData, options?: {
|
|
129
|
+
encoding?: TileEncoding;
|
|
130
|
+
atlas?: {
|
|
131
|
+
names: readonly string[];
|
|
132
|
+
};
|
|
133
|
+
/** The file's `$schema`, written first. */
|
|
134
|
+
schema?: string;
|
|
135
|
+
}): string;
|
|
73
136
|
export declare class TilemapDataStore extends AssetStore<TilemapData, 'TilemapData'> {
|
|
74
137
|
constructor();
|
|
75
138
|
}
|
|
@@ -83,7 +146,7 @@ export declare const Tilemap: import("@aethervtt/shard-core").ComponentDef<{
|
|
|
83
146
|
readonly tileSize: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
84
147
|
readonly chunkSize: import("@aethervtt/shard-core").FieldType<number, "u16">;
|
|
85
148
|
readonly layer: import("@aethervtt/shard-core").FieldType<number, "i16">;
|
|
86
|
-
readonly lit: import("@aethervtt/shard-core").FieldType<
|
|
149
|
+
readonly lit: import("@aethervtt/shard-core").FieldType<"2d" | "3d" | "none", "u8">;
|
|
87
150
|
}>;
|
|
88
151
|
/** Sets a tile (atlas region + 1, 0 to clear) and its flags. Only its chunk re-uploads. */
|
|
89
152
|
export declare function setTile(world: World, tilemap: Entity, x: number, y: number, tile: number, options?: {
|
|
@@ -92,3 +155,11 @@ export declare function setTile(world: World, tilemap: Entity, x: number, y: num
|
|
|
92
155
|
}): void;
|
|
93
156
|
/** The tile at (x, y): atlas region + 1, or 0 for empty or outside the map. */
|
|
94
157
|
export declare function tileAt(world: World, tilemap: Entity, x: number, y: number, layer?: number | string): number;
|
|
158
|
+
/**
|
|
159
|
+
* Palette names the atlas has no region for (0059), each as `sprite/unknown-tile` naming the
|
|
160
|
+
* name, the first layer and cell that use it, and a JSON pointer to where that cell is saved: its
|
|
161
|
+
* row in the rows encoding, or the layer's tiles in base64. Version 1 maps name no tiles: none.
|
|
162
|
+
*/
|
|
163
|
+
export declare function unknownTiles(data: TilemapData, atlas: {
|
|
164
|
+
region(name: string): number;
|
|
165
|
+
}): ShardError[];
|