@vibemancer/core 1.0.5 → 1.0.7
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/{chunk-NEXWZU5I.js → chunk-NR326XEY.js} +13 -2
- package/dist/chunk-NR326XEY.js.map +1 -0
- package/dist/{index-browser-AFWi8jxB.d.ts → index-browser-iiIpqpDl.d.ts} +60 -5
- package/dist/index-browser.d.ts +1 -1
- package/dist/index-browser.js +5 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/simulation.ts +4 -1
- package/src/engine-version.ts +14 -1
- package/src/hooks/state-hooks.ts +7 -1
- package/src/index-browser.ts +1 -0
- package/src/index.ts +1 -0
- package/src/replay-compat.ts +35 -0
- package/src/utils/spatial.ts +14 -2
- package/dist/chunk-NEXWZU5I.js.map +0 -1
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export * from './rules.js';
|
|
3
3
|
export * from './engine-version.js';
|
|
4
|
+
export * from './replay-compat.js';
|
|
4
5
|
export * from './engine/simulation.js';
|
|
5
6
|
export {DEFAULT_BUDGET, DEFAULT_FIGHT_BACKSTOP_MS, createBudgetState, createFightBudget, recordSpend, mayAct} from './engine/bot-compute-budget.js';
|
|
6
7
|
export type {BudgetLimits, BotBudgetState, FightBudget} from './engine/bot-compute-budget.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a stored match can still be replayed by the running engine.
|
|
3
|
+
*
|
|
4
|
+
* Spectate re-simulates a recorded match from its seed, so it may only do that when the
|
|
5
|
+
* engine is the one that produced it. The check used to be `match.engineVersion ===
|
|
6
|
+
* ENGINE_VERSION`, which is right in spirit and slightly too strict in fact.
|
|
7
|
+
*
|
|
8
|
+
* ENGINE_VERSION is a CONTENT HASH, so it answers "is this the same source?" rather than
|
|
9
|
+
* "is this the same behaviour?". Those come apart when the hashing itself is corrected. On
|
|
10
|
+
* 2026-09-09 the comment stripper was fixed — it had been hashing most comments as if they
|
|
11
|
+
* were code — and the value moved from 1688330189011034 to 3884810833238487 without
|
|
12
|
+
* packages/core/src changing by a byte. Under an exact comparison that would have stranded
|
|
13
|
+
* 26,948 of the 42,896 stored matches, 63% of them, for no reason a player could act on.
|
|
14
|
+
*
|
|
15
|
+
* So the gate consults a short list of historical values known to describe the same engine.
|
|
16
|
+
* See scripts/engine-version-equivalents.json for what may go in it, and for why a wrong
|
|
17
|
+
* entry is the dangerous kind of wrong: it fails OPEN.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import {ENGINE_VERSION, EQUIVALENT_ENGINE_VERSIONS} from './engine-version.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param matchEngineVersion the `engineVersion` field as read from a stored match.
|
|
24
|
+
* Deliberately typed to admit the junk a database can hand back: a document written
|
|
25
|
+
* before the field existed returns undefined, and a missing version is never a match.
|
|
26
|
+
*/
|
|
27
|
+
export function canReplayMatch(matchEngineVersion: number | null | undefined): boolean
|
|
28
|
+
{
|
|
29
|
+
if (typeof matchEngineVersion !== 'number') return false;
|
|
30
|
+
// NaN would fail `===` against everything, so an exact gate happened to reject it. Being
|
|
31
|
+
// explicit keeps that true now that the comparison is a lookup.
|
|
32
|
+
if (!Number.isSafeInteger(matchEngineVersion)) return false;
|
|
33
|
+
if (matchEngineVersion === ENGINE_VERSION) return true;
|
|
34
|
+
return EQUIVALENT_ENGINE_VERSIONS.includes(matchEngineVersion);
|
|
35
|
+
}
|
package/src/utils/spatial.ts
CHANGED
|
@@ -43,8 +43,20 @@ export function directionAway(from: Position, to: Position): Position
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* Clamp a position
|
|
47
|
-
*
|
|
46
|
+
* Clamp a position into the arena rectangle — [0, ARENA_SIZE] on both axes.
|
|
47
|
+
*
|
|
48
|
+
* READ THIS BEFORE USING IT FOR SAFETY. It does NOT keep a wizard alive. The arena includes
|
|
49
|
+
* the 30-unit lava border, so clamping to it can hand you back a coordinate that is deep
|
|
50
|
+
* inside the lava — for example (0, 0), which is lethal. It used to be documented as
|
|
51
|
+
* clamping to "valid arena bounds", which reads like exactly the safety helper it is not:
|
|
52
|
+
* a player sanitising a blink target with this will blink into the fire.
|
|
53
|
+
*
|
|
54
|
+
* To stay ALIVE you want the safe box for a wizard's CENTRE, which is
|
|
55
|
+
* [ARENA_MIN + WIZARD_RADIUS, ARENA_MAX - WIZARD_RADIUS] — currently [35, 825], because
|
|
56
|
+
* `isInLava` tests your edge rather than your centre.
|
|
57
|
+
*
|
|
58
|
+
* For the engine's own wizard clamp (arena bounds minus the radius, still not lava-safe),
|
|
59
|
+
* see clampToArena in physics.ts.
|
|
48
60
|
*/
|
|
49
61
|
export function clampPositionToArena(position: Position): Position
|
|
50
62
|
{
|