@kradle/challenges-sdk 0.22.0 → 0.24.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/CHANGELOG.md +38 -1
- package/LLM_README.md +54 -15
- package/README.md +20 -2
- package/dist/engine.d.ts +2 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +4 -1
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/builder.d.ts.map +1 -1
- package/dist/runtime/builder.js +26 -6
- package/dist/runtime/builder.js.map +1 -1
- package/dist/runtime/dimensions.d.ts +24 -0
- package/dist/runtime/dimensions.d.ts.map +1 -0
- package/dist/runtime/dimensions.js +47 -0
- package/dist/runtime/dimensions.js.map +1 -0
- package/dist/runtime/reducer.d.ts.map +1 -1
- package/dist/runtime/reducer.js +98 -29
- package/dist/runtime/reducer.js.map +1 -1
- package/dist/runtime/types.d.ts +56 -6
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/runtime/wire.d.ts +33 -2
- package/dist/runtime/wire.d.ts.map +1 -1
- package/dist/runtime/wire.js +2 -0
- package/dist/runtime/wire.js.map +1 -1
- package/dist/runtime/world.d.ts +87 -4
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +288 -23
- package/dist/runtime/world.js.map +1 -1
- package/dist/structures.d.ts.map +1 -1
- package/dist/structures.js +3 -1
- package/dist/structures.js.map +1 -1
- package/dist/test/harness.d.ts +13 -2
- package/dist/test/harness.d.ts.map +1 -1
- package/dist/test/harness.js +44 -9
- package/dist/test/harness.js.map +1 -1
- package/dist/test/helpers.d.ts.map +1 -1
- package/dist/test/helpers.js +2 -1
- package/dist/test/helpers.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/world.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Dimension } from "./dimensions.js";
|
|
2
|
+
import type { BlockId as Block, Box, EntityTypeId as EntityType, GameMode, ItemId as Item, ItemMeta, Json, PlayerStatus, Vec3 } from "./wire.js";
|
|
2
3
|
/** The air block id. */
|
|
3
4
|
export declare const AIR: Block;
|
|
4
5
|
/** The id part of a block state string: `minecraft:oak_fence[north=true]` -> `minecraft:oak_fence`. */
|
|
@@ -35,6 +36,8 @@ export declare function applyEquipment(prev: Equipment | undefined, changes: rea
|
|
|
35
36
|
/** A 16x16x16 section: one palette index for a uniform section, or 4096 of them (y, then z, then x). */
|
|
36
37
|
export type Section = number | number[];
|
|
37
38
|
export interface Chunk {
|
|
39
|
+
/** The dimension of this chunk. Absent means minecraft:overworld. */
|
|
40
|
+
dimension?: Dimension | undefined;
|
|
38
41
|
x: number;
|
|
39
42
|
z: number;
|
|
40
43
|
/** The lowest block Y of the world (-64 in 1.20). */
|
|
@@ -54,6 +57,13 @@ export interface Entity {
|
|
|
54
57
|
tags: string[];
|
|
55
58
|
/** The custom name, when one is set. */
|
|
56
59
|
name?: string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* The saved NBT, as `/data get entity` shows it: `data` holds a marker's data, `Health` a mob's health.
|
|
62
|
+
* A number has no type suffix, and a byte boolean is `0` or `1`. It leaves out the keys that the other
|
|
63
|
+
* fields carry (position, motion, rotation, uuid, custom name, tags, fire, air, passengers, effects, absorption).
|
|
64
|
+
* `undefined` until the server reports it.
|
|
65
|
+
*/
|
|
66
|
+
nbt?: Readonly<Record<string, Json>> | undefined;
|
|
57
67
|
/** Half-hearts, for a living entity. */
|
|
58
68
|
health?: number | undefined;
|
|
59
69
|
/** Dropped items: what lies there. */
|
|
@@ -143,15 +153,21 @@ export interface WorldState {
|
|
|
143
153
|
palette: Block[];
|
|
144
154
|
/** The world time of day, 0..24000, as last reported. */
|
|
145
155
|
time: number;
|
|
146
|
-
/**
|
|
156
|
+
/** Time of day by dimension. */
|
|
157
|
+
times?: Partial<Record<Dimension, number>> | undefined;
|
|
158
|
+
/** By "[<dimension>|]cx,cz"; the Overworld has no prefix. */
|
|
147
159
|
chunks: Record<string, Chunk>;
|
|
148
160
|
/** The non-player entities, by id. */
|
|
149
161
|
entities: Record<string, Entity>;
|
|
150
162
|
/** The online players who are not participants, by name. */
|
|
151
163
|
others: Record<string, OtherPlayer>;
|
|
164
|
+
/** The saved NBT of the block entities, by "[<dimension>|]x,y,z"; the Overworld has no prefix. */
|
|
165
|
+
blockNbt: Record<string, Readonly<Record<string, Json>>>;
|
|
152
166
|
}
|
|
153
167
|
/** What the engine sends for one chunk: sections with a local palette; absent sections are air. */
|
|
154
168
|
export interface ChunkMessage {
|
|
169
|
+
/** The dimension of this chunk. Absent means minecraft:overworld. */
|
|
170
|
+
dimension?: Dimension | undefined;
|
|
155
171
|
/** The chunk x, in chunks (the block x divided by 16, floored). */
|
|
156
172
|
x: number;
|
|
157
173
|
/** The chunk z, in chunks. */
|
|
@@ -178,7 +194,7 @@ export interface ChunkMessage {
|
|
|
178
194
|
}>;
|
|
179
195
|
}
|
|
180
196
|
export declare const emptyWorld: () => WorldState;
|
|
181
|
-
export declare const chunkKey: (x: number, z: number) => string;
|
|
197
|
+
export declare const chunkKey: (x: number, z: number, dimension?: Dimension) => string;
|
|
182
198
|
/** Block coordinates of a box, both corners inclusive, ordered. */
|
|
183
199
|
export declare function bounds(box: Box): {
|
|
184
200
|
/** The smallest x, y and z. */
|
|
@@ -189,7 +205,7 @@ export declare function bounds(box: Box): {
|
|
|
189
205
|
/** True when the block at `pos` (feet for a player) is inside `box`. */
|
|
190
206
|
export declare function inBox(pos: Vec3, box: Box): boolean;
|
|
191
207
|
export declare function applyChunk(w: WorldState, msg: ChunkMessage): WorldState;
|
|
192
|
-
export declare function removeChunk(w: WorldState, x: number, z: number): WorldState;
|
|
208
|
+
export declare function removeChunk(w: WorldState, x: number, z: number, dimension?: Dimension): WorldState;
|
|
193
209
|
/** The full block state at `at` (`minecraft:oak_fence[north=true,...]`); undefined outside the loaded chunks. */
|
|
194
210
|
export declare function blockStateAt(w: WorldState, at: Vec3): Block | undefined;
|
|
195
211
|
/** The block id at `at`, without its state properties. */
|
|
@@ -231,6 +247,8 @@ export type EntityMove = {
|
|
|
231
247
|
export declare function moveEntities(w: WorldState, moves: ReadonlyArray<EntityMove>): WorldState;
|
|
232
248
|
/** Which entities `g.entities` returns; every field narrows the result. */
|
|
233
249
|
export interface EntityFilter {
|
|
250
|
+
/** Only entities in this dimension. Absent includes all enabled dimensions. */
|
|
251
|
+
dimension?: Dimension | undefined;
|
|
234
252
|
/** Only the entities whose position is inside the box. */
|
|
235
253
|
box?: Box | undefined;
|
|
236
254
|
/** Only the entities of this type. */
|
|
@@ -241,4 +259,69 @@ export interface EntityFilter {
|
|
|
241
259
|
export declare function entitiesIn(w: WorldState, f?: EntityFilter): Entity[];
|
|
242
260
|
export declare function putOther(w: WorldState, p: OtherPlayer): WorldState;
|
|
243
261
|
export declare function removeOther(w: WorldState, name: string): WorldState;
|
|
262
|
+
/**
|
|
263
|
+
* The NBT that changed on one server tick. The first sight of an entity or a block entity holds every key.
|
|
264
|
+
* After that, `nbt` is a delta: an object holds the changed keys, recursively, and null removes a key; a
|
|
265
|
+
* list patch `{"@len": n, "<index>": delta}` holds the changed entries of a list with n entries; any other
|
|
266
|
+
* value replaces the old one. A block entity that is gone has `nbt: null`.
|
|
267
|
+
*/
|
|
268
|
+
export interface NbtMessage {
|
|
269
|
+
/** The entities whose NBT changed. */
|
|
270
|
+
entities?: ReadonlyArray<{
|
|
271
|
+
id: string;
|
|
272
|
+
nbt: Record<string, Json>;
|
|
273
|
+
}> | undefined;
|
|
274
|
+
/** The block entities whose NBT changed or that are gone. */
|
|
275
|
+
blocks?: ReadonlyArray<{
|
|
276
|
+
pos: Vec3;
|
|
277
|
+
nbt: Record<string, Json> | null;
|
|
278
|
+
}> | undefined;
|
|
279
|
+
}
|
|
280
|
+
/** The key of a list patch that holds the list's new length. */
|
|
281
|
+
export declare const NBT_LIST_LEN = "@len";
|
|
282
|
+
type JsonObject = {
|
|
283
|
+
[key: string]: Json;
|
|
284
|
+
};
|
|
285
|
+
/** A compound delta applied to a compound (or to nothing, on the first sight). */
|
|
286
|
+
export declare function mergeNbt(prev: Readonly<JsonObject> | undefined, d: Readonly<JsonObject>): Readonly<JsonObject>;
|
|
287
|
+
/** The delta from `prev` to `cur`, as the engine computes it; `undefined` when they are equal. */
|
|
288
|
+
export declare function nbtDelta(prev: Readonly<JsonObject>, cur: Readonly<JsonObject>): JsonObject | undefined;
|
|
289
|
+
/** One entity whose NBT an `nbt` message changed: the entity before, and the delta. */
|
|
290
|
+
export interface NbtEntityChange {
|
|
291
|
+
id: string;
|
|
292
|
+
was: Entity;
|
|
293
|
+
delta: Readonly<JsonObject>;
|
|
294
|
+
}
|
|
295
|
+
/** One block entity whose NBT an `nbt` message changed: the NBT before, and the delta (`null`: the block entity is gone). */
|
|
296
|
+
export interface NbtBlockChange {
|
|
297
|
+
at: Vec3;
|
|
298
|
+
was: Readonly<JsonObject> | undefined;
|
|
299
|
+
delta: Readonly<JsonObject> | null;
|
|
300
|
+
}
|
|
301
|
+
/** The world after one `nbt` message, and what changed. Unknown entities and blocks outside the loaded chunks are ignored. */
|
|
302
|
+
export declare function applyNbt(w: WorldState, m: NbtMessage): {
|
|
303
|
+
world: WorldState;
|
|
304
|
+
entities: NbtEntityChange[];
|
|
305
|
+
blocks: NbtBlockChange[];
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* The paths of the leaves that a delta changes, from the value before it: `nbt.data.score`, `nbt.Items[3].count`.
|
|
309
|
+
* A replaced or new value, a removed key and a removed list entry give their own path. `base` is the path of the
|
|
310
|
+
* value itself: the first sight of a value gives `base` alone.
|
|
311
|
+
*/
|
|
312
|
+
export declare function nbtPaths(prev: Json | undefined, d: Json, base: string, out?: string[]): string[];
|
|
313
|
+
/** The names of the top-level fields that differ between two observations of an entity. */
|
|
314
|
+
export declare function changedFields(was: object, now: object): string[];
|
|
315
|
+
/**
|
|
316
|
+
* The value at a change path (`"nbt.Items[3].count"`, `'nbt["Paper.Delay"]'`), or `undefined` when nothing is there.
|
|
317
|
+
* Read from the object that the path starts at: the entity for `entityChanged`, the NBT for `blockNbtChanged`.
|
|
318
|
+
* The path `""` is the object itself.
|
|
319
|
+
*/
|
|
320
|
+
export declare function valueAt(root: unknown, path: string): unknown;
|
|
321
|
+
/**
|
|
322
|
+
* Whether a change touches the value at `path`: a changed path is `path`, under it (`nbt.data.score` for `nbt.data`),
|
|
323
|
+
* or above it (`nbt` on the first sight, for `nbt.data`). A prefix test alone would match `nbt.dataX` too.
|
|
324
|
+
*/
|
|
325
|
+
export declare function changedUnder(changed: readonly string[], path: string): boolean;
|
|
326
|
+
export {};
|
|
244
327
|
//# sourceMappingURL=world.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/world.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// The world mirror: the loaded chunks, the entities and the other players, as
|
|
3
|
-
// the engine streams them. It lives in the challenge state, but every update
|
|
4
|
-
// copies only the containers it touches (a section, the entity map), so a
|
|
5
|
-
// reduction shares the rest with the state before it. Nothing here mutates
|
|
6
|
-
// in place; the reducer treats the mirror as a value.
|
|
7
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.AIR_STATES = exports.chunkKey = exports.emptyWorld = exports.MAX_SECTIONS = exports.AIR = void 0;
|
|
3
|
+
exports.NBT_LIST_LEN = exports.AIR_STATES = exports.chunkKey = exports.emptyWorld = exports.MAX_SECTIONS = exports.AIR = void 0;
|
|
9
4
|
exports.blockIdOf = blockIdOf;
|
|
10
5
|
exports.freezeObservation = freezeObservation;
|
|
11
6
|
exports.applyEquipment = applyEquipment;
|
|
@@ -27,6 +22,15 @@ exports.moveEntities = moveEntities;
|
|
|
27
22
|
exports.entitiesIn = entitiesIn;
|
|
28
23
|
exports.putOther = putOther;
|
|
29
24
|
exports.removeOther = removeOther;
|
|
25
|
+
exports.mergeNbt = mergeNbt;
|
|
26
|
+
exports.nbtDelta = nbtDelta;
|
|
27
|
+
exports.applyNbt = applyNbt;
|
|
28
|
+
exports.nbtPaths = nbtPaths;
|
|
29
|
+
exports.changedFields = changedFields;
|
|
30
|
+
exports.valueAt = valueAt;
|
|
31
|
+
exports.changedUnder = changedUnder;
|
|
32
|
+
const dimensions_js_1 = require("./dimensions.js");
|
|
33
|
+
const errors_js_1 = require("./errors.js");
|
|
30
34
|
/** The air block id. */
|
|
31
35
|
exports.AIR = "minecraft:air";
|
|
32
36
|
/** The id part of a block state string: `minecraft:oak_fence[north=true]` -> `minecraft:oak_fence`. */
|
|
@@ -80,20 +84,32 @@ function applyEquipment(prev, changes) {
|
|
|
80
84
|
}
|
|
81
85
|
return next;
|
|
82
86
|
}
|
|
83
|
-
const emptyWorld = () => ({
|
|
87
|
+
const emptyWorld = () => ({
|
|
88
|
+
palette: [exports.AIR],
|
|
89
|
+
time: 0,
|
|
90
|
+
chunks: {},
|
|
91
|
+
entities: {},
|
|
92
|
+
others: {},
|
|
93
|
+
blockNbt: {},
|
|
94
|
+
});
|
|
84
95
|
exports.emptyWorld = emptyWorld;
|
|
85
|
-
const chunkKey = (x, z) => `${x},${z}`;
|
|
96
|
+
const chunkKey = (x, z, dimension) => `${(0, dimensions_js_1.dimensionPrefix)(dimension)}${x},${z}`;
|
|
86
97
|
exports.chunkKey = chunkKey;
|
|
87
98
|
const sectionIndex = (x, y, z) => ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
|
88
99
|
/** Block coordinates of a box, both corners inclusive, ordered. */
|
|
89
100
|
function bounds(box) {
|
|
101
|
+
if ((0, dimensions_js_1.dimensionOf)(box.from) !== (0, dimensions_js_1.dimensionOf)(box.to))
|
|
102
|
+
throw (0, errors_js_1.apiError)("invalid_value", "A box cannot cross dimensions", { path: "box", value: box });
|
|
103
|
+
const scope = box.from.dimension ? { dimension: box.from.dimension } : {};
|
|
90
104
|
return {
|
|
91
105
|
lo: {
|
|
106
|
+
...scope,
|
|
92
107
|
x: Math.floor(Math.min(box.from.x, box.to.x)),
|
|
93
108
|
y: Math.floor(Math.min(box.from.y, box.to.y)),
|
|
94
109
|
z: Math.floor(Math.min(box.from.z, box.to.z)),
|
|
95
110
|
},
|
|
96
111
|
hi: {
|
|
112
|
+
...scope,
|
|
97
113
|
x: Math.floor(Math.max(box.from.x, box.to.x)),
|
|
98
114
|
y: Math.floor(Math.max(box.from.y, box.to.y)),
|
|
99
115
|
z: Math.floor(Math.max(box.from.z, box.to.z)),
|
|
@@ -103,6 +119,8 @@ function bounds(box) {
|
|
|
103
119
|
/** True when the block at `pos` (feet for a player) is inside `box`. */
|
|
104
120
|
function inBox(pos, box) {
|
|
105
121
|
const { lo, hi } = bounds(box);
|
|
122
|
+
if ((0, dimensions_js_1.dimensionOf)(pos) !== (0, dimensions_js_1.dimensionOf)(lo))
|
|
123
|
+
return false;
|
|
106
124
|
const x = Math.floor(pos.x);
|
|
107
125
|
const y = Math.floor(pos.y);
|
|
108
126
|
const z = Math.floor(pos.z);
|
|
@@ -119,7 +137,7 @@ function intern(palette, block) {
|
|
|
119
137
|
// ---------------------------------------------------------------- chunks
|
|
120
138
|
function applyChunk(w, msg) {
|
|
121
139
|
let palette = w.palette;
|
|
122
|
-
const count = Math.max(w.chunks[(0, exports.chunkKey)(msg.x, msg.z)]?.sections.length ?? 0, ...msg.sections.map((s) => ((s.y - msg.minY) >> 4) + 1));
|
|
140
|
+
const count = Math.max(w.chunks[(0, exports.chunkKey)(msg.x, msg.z, msg.dimension)]?.sections.length ?? 0, ...msg.sections.map((s) => ((s.y - msg.minY) >> 4) + 1));
|
|
123
141
|
const sections = new Array(Math.max(count, 0)).fill(0);
|
|
124
142
|
for (const s of msg.sections) {
|
|
125
143
|
const sy = (s.y - msg.minY) >> 4;
|
|
@@ -144,23 +162,40 @@ function applyChunk(w, msg) {
|
|
|
144
162
|
return {
|
|
145
163
|
...w,
|
|
146
164
|
palette,
|
|
147
|
-
chunks: {
|
|
165
|
+
chunks: {
|
|
166
|
+
...w.chunks,
|
|
167
|
+
[(0, exports.chunkKey)(msg.x, msg.z, msg.dimension)]: {
|
|
168
|
+
...(msg.dimension ? { dimension: msg.dimension } : {}),
|
|
169
|
+
x: msg.x,
|
|
170
|
+
z: msg.z,
|
|
171
|
+
minY: msg.minY,
|
|
172
|
+
sections,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
148
175
|
};
|
|
149
176
|
}
|
|
150
|
-
function removeChunk(w, x, z) {
|
|
151
|
-
const key = (0, exports.chunkKey)(x, z);
|
|
177
|
+
function removeChunk(w, x, z, dimension) {
|
|
178
|
+
const key = (0, exports.chunkKey)(x, z, dimension);
|
|
152
179
|
if (!(key in w.chunks))
|
|
153
180
|
return w;
|
|
154
181
|
const chunks = { ...w.chunks };
|
|
155
182
|
delete chunks[key];
|
|
156
|
-
|
|
183
|
+
let blockNbt = w.blockNbt;
|
|
184
|
+
for (const k of Object.keys(blockNbt)) {
|
|
185
|
+
if (!(0, dimensions_js_1.keyInChunk)(k, x, z, dimension))
|
|
186
|
+
continue;
|
|
187
|
+
if (blockNbt === w.blockNbt)
|
|
188
|
+
blockNbt = { ...blockNbt };
|
|
189
|
+
delete blockNbt[k];
|
|
190
|
+
}
|
|
191
|
+
return { ...w, chunks, blockNbt };
|
|
157
192
|
}
|
|
158
193
|
/** The full block state at `at` (`minecraft:oak_fence[north=true,...]`); undefined outside the loaded chunks. */
|
|
159
194
|
function blockStateAt(w, at) {
|
|
160
195
|
const x = Math.floor(at.x);
|
|
161
196
|
const y = Math.floor(at.y);
|
|
162
197
|
const z = Math.floor(at.z);
|
|
163
|
-
const chunk = w.chunks[(0, exports.chunkKey)(x >> 4, z >> 4)];
|
|
198
|
+
const chunk = w.chunks[(0, exports.chunkKey)(x >> 4, z >> 4, at.dimension)];
|
|
164
199
|
if (!chunk)
|
|
165
200
|
return undefined;
|
|
166
201
|
const sy = (y - chunk.minY) >> 4;
|
|
@@ -187,7 +222,7 @@ function setBlocks(w, changes) {
|
|
|
187
222
|
const x = Math.floor(c.x);
|
|
188
223
|
const y = Math.floor(c.y);
|
|
189
224
|
const z = Math.floor(c.z);
|
|
190
|
-
const key = (0, exports.chunkKey)(x >> 4, z >> 4);
|
|
225
|
+
const key = (0, exports.chunkKey)(x >> 4, z >> 4, c.dimension);
|
|
191
226
|
let chunk = touched.get(key);
|
|
192
227
|
if (!chunk) {
|
|
193
228
|
const base = w.chunks[key];
|
|
@@ -242,7 +277,7 @@ function fillBlocks(w, box, block) {
|
|
|
242
277
|
for (let x = lo.x; x <= hi.x; x++)
|
|
243
278
|
for (let y = lo.y; y <= hi.y; y++)
|
|
244
279
|
for (let z = lo.z; z <= hi.z; z++)
|
|
245
|
-
changes.push({ x, y, z, block });
|
|
280
|
+
changes.push({ ...lo, x, y, z, block });
|
|
246
281
|
return setBlocks(w, changes);
|
|
247
282
|
}
|
|
248
283
|
/** The air states the vanilla `masked` clone skips. */
|
|
@@ -264,11 +299,11 @@ function cloneBlocks(w, box, dest, mode = "replace") {
|
|
|
264
299
|
for (let y = lo.y; y <= hi.y; y++)
|
|
265
300
|
for (let z = lo.z; z <= hi.z; z++) {
|
|
266
301
|
if (mode === "move")
|
|
267
|
-
cleared.push({ x, y, z, block: exports.AIR });
|
|
268
|
-
const block = blockStateAt(w, { x, y, z });
|
|
302
|
+
cleared.push({ ...lo, x, y, z, block: exports.AIR });
|
|
303
|
+
const block = blockStateAt(w, { ...lo, x, y, z });
|
|
269
304
|
if (block === undefined || (mode === "masked" && exports.AIR_STATES.has(block)))
|
|
270
305
|
continue;
|
|
271
|
-
copies.push({ x: x + dx, y: y + dy, z: z + dz, block });
|
|
306
|
+
copies.push({ ...dest, x: x + dx, y: y + dy, z: z + dz, block });
|
|
272
307
|
}
|
|
273
308
|
return setBlocks(w, [...cleared, ...copies]);
|
|
274
309
|
}
|
|
@@ -277,7 +312,7 @@ function walkBox(w, box, visit) {
|
|
|
277
312
|
const { lo, hi } = bounds(box);
|
|
278
313
|
for (let cx = lo.x >> 4; cx <= hi.x >> 4; cx++) {
|
|
279
314
|
for (let cz = lo.z >> 4; cz <= hi.z >> 4; cz++) {
|
|
280
|
-
const chunk = w.chunks[(0, exports.chunkKey)(cx, cz)];
|
|
315
|
+
const chunk = w.chunks[(0, exports.chunkKey)(cx, cz, lo.dimension)];
|
|
281
316
|
if (!chunk)
|
|
282
317
|
continue;
|
|
283
318
|
const x1 = Math.max(lo.x, cx << 4);
|
|
@@ -324,7 +359,7 @@ function regionLoaded(w, box) {
|
|
|
324
359
|
const { lo, hi } = bounds(box);
|
|
325
360
|
for (let cx = lo.x >> 4; cx <= hi.x >> 4; cx++) {
|
|
326
361
|
for (let cz = lo.z >> 4; cz <= hi.z >> 4; cz++)
|
|
327
|
-
if (!w.chunks[(0, exports.chunkKey)(cx, cz)])
|
|
362
|
+
if (!w.chunks[(0, exports.chunkKey)(cx, cz, lo.dimension)])
|
|
328
363
|
return false;
|
|
329
364
|
}
|
|
330
365
|
return true;
|
|
@@ -344,7 +379,7 @@ function findBlocks(w, box, match, limit = Number.MAX_SAFE_INTEGER) {
|
|
|
344
379
|
const out = [];
|
|
345
380
|
walkBox(w, box, (x, y, z, b) => {
|
|
346
381
|
if (ok(b))
|
|
347
|
-
out.push({ x, y, z });
|
|
382
|
+
out.push({ ...(box.from.dimension ? { dimension: box.from.dimension } : {}), x, y, z });
|
|
348
383
|
return out.length < limit;
|
|
349
384
|
});
|
|
350
385
|
return out;
|
|
@@ -382,8 +417,11 @@ function moveEntities(w, moves) {
|
|
|
382
417
|
return any ? { ...w, entities } : w;
|
|
383
418
|
}
|
|
384
419
|
function entitiesIn(w, f = {}) {
|
|
420
|
+
if (f.box)
|
|
421
|
+
bounds(f.box);
|
|
385
422
|
const prefix = f.tag?.endsWith("*") ? f.tag.slice(0, -1) : undefined;
|
|
386
|
-
return Object.values(w.entities).filter((e) => (f.
|
|
423
|
+
return Object.values(w.entities).filter((e) => (f.dimension === undefined || (0, dimensions_js_1.dimensionOf)(e.pos) === f.dimension) &&
|
|
424
|
+
(f.type === undefined || e.type === f.type) &&
|
|
387
425
|
(f.box === undefined || inBox(e.pos, f.box)) &&
|
|
388
426
|
(f.tag === undefined ||
|
|
389
427
|
(prefix !== undefined ? e.tags.some((t) => t.startsWith(prefix)) : e.tags.includes(f.tag))));
|
|
@@ -399,4 +437,231 @@ function removeOther(w, name) {
|
|
|
399
437
|
delete others[name];
|
|
400
438
|
return { ...w, others };
|
|
401
439
|
}
|
|
440
|
+
/** The key of a list patch that holds the list's new length. */
|
|
441
|
+
exports.NBT_LIST_LEN = "@len";
|
|
442
|
+
const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
443
|
+
function freezeJson(v) {
|
|
444
|
+
if (v !== null && typeof v === "object" && !Object.isFrozen(v)) {
|
|
445
|
+
for (const x of Object.values(v))
|
|
446
|
+
freezeJson(x);
|
|
447
|
+
Object.freeze(v);
|
|
448
|
+
}
|
|
449
|
+
return v;
|
|
450
|
+
}
|
|
451
|
+
/** One delta applied to a value. The unchanged parts keep their frozen nodes. */
|
|
452
|
+
function patchNbt(prev, d) {
|
|
453
|
+
if (isObject(d)) {
|
|
454
|
+
const len = d[exports.NBT_LIST_LEN];
|
|
455
|
+
if (Array.isArray(prev) && typeof len === "number") {
|
|
456
|
+
const out = prev.slice(0, len);
|
|
457
|
+
for (const [k, v] of Object.entries(d))
|
|
458
|
+
if (k !== exports.NBT_LIST_LEN)
|
|
459
|
+
out[Number(k)] = patchNbt(out[Number(k)], v);
|
|
460
|
+
Object.freeze(out);
|
|
461
|
+
return out;
|
|
462
|
+
}
|
|
463
|
+
if (isObject(prev))
|
|
464
|
+
return mergeNbt(prev, d);
|
|
465
|
+
}
|
|
466
|
+
return freezeJson(d);
|
|
467
|
+
}
|
|
468
|
+
/** A compound delta applied to a compound (or to nothing, on the first sight). */
|
|
469
|
+
function mergeNbt(prev, d) {
|
|
470
|
+
const out = { ...prev };
|
|
471
|
+
for (const [k, v] of Object.entries(d)) {
|
|
472
|
+
if (v === null)
|
|
473
|
+
delete out[k];
|
|
474
|
+
else
|
|
475
|
+
out[k] = patchNbt(out[k], v);
|
|
476
|
+
}
|
|
477
|
+
return Object.freeze(out);
|
|
478
|
+
}
|
|
479
|
+
/** The delta from `prev` to `cur`, as the engine computes it; `undefined` when they are equal. */
|
|
480
|
+
function nbtDelta(prev, cur) {
|
|
481
|
+
const out = {};
|
|
482
|
+
let any = false;
|
|
483
|
+
for (const [k, v] of Object.entries(cur)) {
|
|
484
|
+
const p = prev[k];
|
|
485
|
+
if (p !== undefined && sameJson(p, v))
|
|
486
|
+
continue;
|
|
487
|
+
out[k] = p === undefined ? v : nbtValueDelta(p, v);
|
|
488
|
+
any = true;
|
|
489
|
+
}
|
|
490
|
+
for (const k of Object.keys(prev)) {
|
|
491
|
+
if (k in cur)
|
|
492
|
+
continue;
|
|
493
|
+
out[k] = null;
|
|
494
|
+
any = true;
|
|
495
|
+
}
|
|
496
|
+
return any ? out : undefined;
|
|
497
|
+
}
|
|
498
|
+
function nbtValueDelta(prev, cur) {
|
|
499
|
+
if (isObject(prev) && isObject(cur))
|
|
500
|
+
return nbtDelta(prev, cur) ?? {};
|
|
501
|
+
if (Array.isArray(prev) && Array.isArray(cur)) {
|
|
502
|
+
const out = { [exports.NBT_LIST_LEN]: cur.length };
|
|
503
|
+
let changed = 0;
|
|
504
|
+
cur.forEach((c, i) => {
|
|
505
|
+
const p = prev[i];
|
|
506
|
+
if (p !== undefined && sameJson(p, c))
|
|
507
|
+
return;
|
|
508
|
+
out[String(i)] = p === undefined ? c : nbtValueDelta(p, c);
|
|
509
|
+
changed++;
|
|
510
|
+
});
|
|
511
|
+
return cur.length > 2 && changed * 2 > cur.length ? cur : out;
|
|
512
|
+
}
|
|
513
|
+
return cur;
|
|
514
|
+
}
|
|
515
|
+
function sameJson(a, b) {
|
|
516
|
+
if (a === b)
|
|
517
|
+
return true;
|
|
518
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object")
|
|
519
|
+
return false;
|
|
520
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
521
|
+
return false;
|
|
522
|
+
const ka = Object.keys(a);
|
|
523
|
+
const kb = Object.keys(b);
|
|
524
|
+
if (ka.length !== kb.length)
|
|
525
|
+
return false;
|
|
526
|
+
for (const k of ka) {
|
|
527
|
+
if (!(k in b))
|
|
528
|
+
return false;
|
|
529
|
+
if (!sameJson(a[k], b[k]))
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
/** The world after one `nbt` message, and what changed. Unknown entities and blocks outside the loaded chunks are ignored. */
|
|
535
|
+
function applyNbt(w, m) {
|
|
536
|
+
let entities = w.entities;
|
|
537
|
+
let blockNbt = w.blockNbt;
|
|
538
|
+
const changedEntities = [];
|
|
539
|
+
const changedBlocks = [];
|
|
540
|
+
for (const d of m.entities ?? []) {
|
|
541
|
+
const prev = entities[d.id];
|
|
542
|
+
if (!prev)
|
|
543
|
+
continue;
|
|
544
|
+
if (entities === w.entities)
|
|
545
|
+
entities = { ...entities };
|
|
546
|
+
entities[d.id] = freezeObservation({ ...prev, nbt: mergeNbt(prev.nbt, d.nbt) });
|
|
547
|
+
changedEntities.push({ id: d.id, was: prev, delta: d.nbt });
|
|
548
|
+
}
|
|
549
|
+
for (const d of m.blocks ?? []) {
|
|
550
|
+
const x = Math.floor(d.pos.x);
|
|
551
|
+
const y = Math.floor(d.pos.y);
|
|
552
|
+
const z = Math.floor(d.pos.z);
|
|
553
|
+
// A delta for a chunk the mirror dropped would leave a partial entry.
|
|
554
|
+
if (!((0, exports.chunkKey)(x >> 4, z >> 4, d.pos.dimension) in w.chunks))
|
|
555
|
+
continue;
|
|
556
|
+
const key = (0, dimensions_js_1.positionKey)(d.pos);
|
|
557
|
+
if (blockNbt === w.blockNbt)
|
|
558
|
+
blockNbt = { ...blockNbt };
|
|
559
|
+
const was = blockNbt[key];
|
|
560
|
+
if (d.nbt === null) {
|
|
561
|
+
if (!was)
|
|
562
|
+
continue;
|
|
563
|
+
delete blockNbt[key];
|
|
564
|
+
}
|
|
565
|
+
else
|
|
566
|
+
blockNbt[key] = mergeNbt(was, d.nbt);
|
|
567
|
+
changedBlocks.push({ at: { ...d.pos, x, y, z }, was, delta: d.nbt });
|
|
568
|
+
}
|
|
569
|
+
const world = entities === w.entities && blockNbt === w.blockNbt ? w : { ...w, entities, blockNbt };
|
|
570
|
+
return { world, entities: changedEntities, blocks: changedBlocks };
|
|
571
|
+
}
|
|
572
|
+
// ---------------------------------------------------------------- change paths
|
|
573
|
+
const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
574
|
+
/** `base.key`, or `base["key"]` for a key that is not a plain name (`Paper.Delay`, `minecraft:custom_data`). */
|
|
575
|
+
function pathJoin(base, key) {
|
|
576
|
+
if (IDENTIFIER.test(key))
|
|
577
|
+
return base === "" ? key : `${base}.${key}`;
|
|
578
|
+
return `${base}[${JSON.stringify(key)}]`;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* The paths of the leaves that a delta changes, from the value before it: `nbt.data.score`, `nbt.Items[3].count`.
|
|
582
|
+
* A replaced or new value, a removed key and a removed list entry give their own path. `base` is the path of the
|
|
583
|
+
* value itself: the first sight of a value gives `base` alone.
|
|
584
|
+
*/
|
|
585
|
+
function nbtPaths(prev, d, base, out = []) {
|
|
586
|
+
if (isObject(d)) {
|
|
587
|
+
const len = d[exports.NBT_LIST_LEN];
|
|
588
|
+
if (Array.isArray(prev) && typeof len === "number") {
|
|
589
|
+
for (const [k, v] of Object.entries(d))
|
|
590
|
+
if (k !== exports.NBT_LIST_LEN)
|
|
591
|
+
nbtPaths(prev[Number(k)], v, `${base}[${k}]`, out);
|
|
592
|
+
for (let i = len; i < prev.length; i++)
|
|
593
|
+
out.push(`${base}[${i}]`);
|
|
594
|
+
return out;
|
|
595
|
+
}
|
|
596
|
+
if (isObject(prev)) {
|
|
597
|
+
for (const [k, v] of Object.entries(d)) {
|
|
598
|
+
if (v === null)
|
|
599
|
+
out.push(pathJoin(base, k));
|
|
600
|
+
else
|
|
601
|
+
nbtPaths(prev[k], v, pathJoin(base, k), out);
|
|
602
|
+
}
|
|
603
|
+
return out;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
out.push(base);
|
|
607
|
+
return out;
|
|
608
|
+
}
|
|
609
|
+
/** The names of the top-level fields that differ between two observations of an entity. */
|
|
610
|
+
function changedFields(was, now) {
|
|
611
|
+
const a = was;
|
|
612
|
+
const b = now;
|
|
613
|
+
const out = [];
|
|
614
|
+
for (const k of new Set([...Object.keys(a), ...Object.keys(b)]))
|
|
615
|
+
if (a[k] !== b[k])
|
|
616
|
+
out.push(k);
|
|
617
|
+
return out;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* The value at a change path (`"nbt.Items[3].count"`, `'nbt["Paper.Delay"]'`), or `undefined` when nothing is there.
|
|
621
|
+
* Read from the object that the path starts at: the entity for `entityChanged`, the NBT for `blockNbtChanged`.
|
|
622
|
+
* The path `""` is the object itself.
|
|
623
|
+
*/
|
|
624
|
+
function valueAt(root, path) {
|
|
625
|
+
let v = root;
|
|
626
|
+
let i = 0;
|
|
627
|
+
const step = (key) => {
|
|
628
|
+
v = v !== null && typeof v === "object" && Object.hasOwn(v, key) ? v[key] : undefined;
|
|
629
|
+
};
|
|
630
|
+
while (i < path.length) {
|
|
631
|
+
if (v === undefined)
|
|
632
|
+
return undefined;
|
|
633
|
+
if (path[i] === "[") {
|
|
634
|
+
if (path[i + 1] === '"') {
|
|
635
|
+
let j = i + 2;
|
|
636
|
+
while (j < path.length && path[j] !== '"')
|
|
637
|
+
j += path[j] === "\\" ? 2 : 1;
|
|
638
|
+
step(JSON.parse(path.slice(i + 1, j + 1)));
|
|
639
|
+
i = j + 2;
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
const j = path.indexOf("]", i);
|
|
643
|
+
step(Number(path.slice(i + 1, j)));
|
|
644
|
+
i = j + 1;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
if (path[i] === ".")
|
|
649
|
+
i++;
|
|
650
|
+
let j = i;
|
|
651
|
+
while (j < path.length && path[j] !== "." && path[j] !== "[")
|
|
652
|
+
j++;
|
|
653
|
+
step(path.slice(i, j));
|
|
654
|
+
i = j;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return v;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Whether a change touches the value at `path`: a changed path is `path`, under it (`nbt.data.score` for `nbt.data`),
|
|
661
|
+
* or above it (`nbt` on the first sight, for `nbt.data`). A prefix test alone would match `nbt.dataX` too.
|
|
662
|
+
*/
|
|
663
|
+
function changedUnder(changed, path) {
|
|
664
|
+
const within = (a, b) => a === b || b === "" || a.startsWith(`${b}.`) || a.startsWith(`${b}[`);
|
|
665
|
+
return changed.some((p) => within(p, path) || within(path, p));
|
|
666
|
+
}
|
|
402
667
|
//# sourceMappingURL=world.js.map
|