@crowdedkingdoms/construct 0.2.1-dev.1 → 0.2.3-dev.1

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.
@@ -1,15 +1,18 @@
1
1
  /**
2
- * The host side of CLIENT mods: what a sandboxed player module may ask the
3
- * game for, and how a consented grid-attached mod is started for a visitor.
2
+ * The host side of CLIENT mods: what a sandboxed player module (the Studio's
3
+ * preview, or a grid's CLIENT half, `clientHalves.ts`) may ask the game for.
4
4
  *
5
5
  * The SDK's `PlayerCodeBroker` has already validated every call against the
6
6
  * platform allowlist, clamped chunk coordinates to the mod's grid AABB, rate-
7
7
  * limited it, and answered `grid_info` / `hud_set` / `overlay_draw` itself.
8
8
  * What reaches `routeClientHostCall` is world_read, `voxel_set`, and
9
- * `pointer_clicks`. Reads return only what the running player can already
10
- * lawfully see. Writes go through ChunkStore.setVoxel (optimistic + UDP) and
11
- * markDirty (durable write-back), the same route Paint uses. Never hand a mod
12
- * the raw client.
9
+ * `pointer_clicks`, in the argument shapes `crowdy-client-sdk` sends. Reads
10
+ * return only what the running player can already lawfully see. Writes go
11
+ * through ChunkStore.setVoxel (optimistic + UDP) and markDirty (durable
12
+ * write-back), the same route Paint uses. Never hand a mod the raw client.
13
+ *
14
+ * `runConsentedGridMod` starts a legacy grid-attached client mod, until
15
+ * CrowdyJS 18 removes them.
13
16
  */
14
17
  import {
15
18
  PlayerCodeBroker,
@@ -54,12 +57,19 @@ export const OFFERED_HOST_CALLS = [
54
57
  /** One zero byte, base64: the smallest non-empty voxel state the API accepts. */
55
58
  export const DEFAULT_VOXEL_STATE = 'AA==';
56
59
 
57
- const MAX_RADIUS = 8;
60
+ /** `actors_list_radius` reaches this far, as the platform clamps it. */
61
+ const MAX_RADIUS_XZ = 3;
62
+ const MAX_RADIUS_Y = 1;
58
63
 
59
64
  function toBigInt(value: unknown): bigint {
60
65
  return BigInt(value as string | number | bigint);
61
66
  }
62
67
 
68
+ function radius(value: unknown, max: number): bigint {
69
+ const requested = Number(value ?? 0);
70
+ return BigInt(Number.isFinite(requested) ? Math.max(0, Math.min(max, Math.floor(requested))) : 0);
71
+ }
72
+
63
73
  export class HostCallRefusedError extends Error {
64
74
  constructor(readonly fn: string) {
65
75
  super(`host call '${fn}' is not offered by this game`);
@@ -80,22 +90,20 @@ export async function routeClientHostCall(
80
90
  return { actors: reads.actorsInChunk(toBigInt(args.x), toBigInt(args.y), toBigInt(args.z)) };
81
91
  case 'actors_list_radius': {
82
92
  const origin = { x: toBigInt(args.x), y: toBigInt(args.y), z: toBigInt(args.z) };
83
- const requested = Number(args.radius ?? args.r ?? 0);
84
- const radius = BigInt(
85
- Number.isFinite(requested) ? Math.max(0, Math.min(MAX_RADIUS, Math.floor(requested))) : 0,
86
- );
93
+ const rXz = radius(args.radiusXz ?? args.radius ?? args.r, MAX_RADIUS_XZ);
94
+ const rY = radius(args.radiusY, MAX_RADIUS_Y);
87
95
  const low = grid
88
96
  ? {
89
- x: maxBig(grid.low.x, origin.x - radius),
90
- y: maxBig(grid.low.y, origin.y - radius),
91
- z: maxBig(grid.low.z, origin.z - radius),
97
+ x: maxBig(grid.low.x, origin.x - rXz),
98
+ y: maxBig(grid.low.y, origin.y - rY),
99
+ z: maxBig(grid.low.z, origin.z - rXz),
92
100
  }
93
101
  : origin;
94
102
  const high = grid
95
103
  ? {
96
- x: minBig(grid.high.x, origin.x + radius),
97
- y: minBig(grid.high.y, origin.y + radius),
98
- z: minBig(grid.high.z, origin.z + radius),
104
+ x: minBig(grid.high.x, origin.x + rXz),
105
+ y: minBig(grid.high.y, origin.y + rY),
106
+ z: minBig(grid.high.z, origin.z + rXz),
99
107
  }
100
108
  : origin;
101
109
  const actors: Array<Record<string, unknown>> = [];
@@ -166,7 +174,7 @@ function asCoord3(value: unknown): { x: unknown; y: unknown; z: unknown } | null
166
174
  return null;
167
175
  }
168
176
 
169
- /** Accept the SDK tuple shape and the flattened host-call JSON the broker clamps. */
177
+ /** Accept the SDKs' flattened host-call JSON (the broker clamps its chunk) and the tuple shape. */
170
178
  export function parseVoxelSetArgs(args: Record<string, unknown>): {
171
179
  chunk: { x: number; y: number; z: number };
172
180
  x: number;
@@ -185,9 +193,9 @@ export function parseVoxelSetArgs(args: Record<string, unknown>): {
185
193
  const voxelRaw =
186
194
  asCoord3(args.voxel) ??
187
195
  ({
188
- x: coordField(args, 'x', 'vx'),
189
- y: coordField(args, 'y', 'vy'),
190
- z: coordField(args, 'z', 'vz'),
196
+ x: coordField(args, 'voxelX', 'x', 'vx'),
197
+ y: coordField(args, 'voxelY', 'y', 'vy'),
198
+ z: coordField(args, 'voxelZ', 'z', 'vz'),
191
199
  } as { x: unknown; y: unknown; z: unknown });
192
200
  const cx = intInRange(chunkRaw.x, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
193
201
  const cy = intInRange(chunkRaw.y, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
@@ -248,6 +256,10 @@ const artifactCache = new Map<string, CachedArtifact>();
248
256
  * circuit breaker as the Studio's own Test/Run path. Its HUD output lands in
249
257
  * the persistent text HUD. Returns null (fails closed) when the artifact
250
258
  * cannot be fetched.
259
+ *
260
+ * @deprecated A legacy grid-attached client mod (`marketplace.gridClientMods`),
261
+ * which CrowdyJS 18 removes. A ck-exec mod's CLIENT half runs through
262
+ * `GridClientHalves` (`clientHalves.ts`).
251
263
  */
252
264
  export async function runConsentedGridMod(options: {
253
265
  client: CrowdyClient;