@adatechnology/game-contracts 0.21.0 → 0.22.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/README.md +2 -0
- package/dist/index.d.ts +238 -7
- package/dist/index.global.js +228 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +228 -2
- package/dist/index.js.map +1 -1
- package/dist/testing-CJY18EZK.d.ts +9 -0
- package/dist/testing.d.ts +1 -0
- package/dist/testing.js +11 -0
- package/dist/testing.js.map +1 -0
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -16,6 +16,30 @@ function blastShove(blast, target, options = {}) {
|
|
|
16
16
|
return { speed, direction: [direction[0] / length, direction[1] / length, direction[2] / length], distance, falloff };
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
// src/impact-cost.ts
|
|
20
|
+
var DEFAULT_COST_READS = 1e4;
|
|
21
|
+
var DEFAULT_COST_CEILING_MS = 50;
|
|
22
|
+
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
23
|
+
var heapUsedBytes = () => {
|
|
24
|
+
const nodeProcess = globalThis.process;
|
|
25
|
+
return nodeProcess?.memoryUsage?.().heapUsed;
|
|
26
|
+
};
|
|
27
|
+
var checkReadCost = ({ name, read, options, problems }) => {
|
|
28
|
+
const reads = options.reads ?? DEFAULT_COST_READS;
|
|
29
|
+
const ceilingMs = options.ceilingMs ?? DEFAULT_COST_CEILING_MS;
|
|
30
|
+
const allocationBytes = options.allocationBytes ?? DEFAULT_COST_ALLOCATION_BYTES;
|
|
31
|
+
if (read() !== read()) problems.push(`${name}() returns a new object on each read: cache it between changes (cost contract)`);
|
|
32
|
+
for (let i = 0; i < reads; i++) read();
|
|
33
|
+
const heapBefore = heapUsedBytes();
|
|
34
|
+
const started = performance.now();
|
|
35
|
+
for (let i = 0; i < reads; i++) read();
|
|
36
|
+
const elapsedMs = performance.now() - started;
|
|
37
|
+
const heapAfter = heapUsedBytes();
|
|
38
|
+
if (elapsedMs > ceilingMs) problems.push(`${name}() took ${elapsedMs.toFixed(1)} ms for ${reads} reads, over the ${ceilingMs} ms ceiling (cost contract)`);
|
|
39
|
+
if (heapBefore !== void 0 && heapAfter !== void 0 && heapAfter - heapBefore > allocationBytes)
|
|
40
|
+
problems.push(`${name}() grew the heap by ${heapAfter - heapBefore} bytes over ${reads} reads, over the ${allocationBytes} byte ceiling (cost contract)`);
|
|
41
|
+
};
|
|
42
|
+
|
|
19
43
|
// src/impact.ts
|
|
20
44
|
var IMPACT_CONTRACT = {
|
|
21
45
|
ballistic: { required: ["type", "point", "direction", "energy", "caliber"], optional: ["space", "source"], note: "bullets and pellets: joules and diameter in millimetres" },
|
|
@@ -122,6 +146,15 @@ var checkDestructible = (impl, options = {}) => {
|
|
|
122
146
|
} catch (e) {
|
|
123
147
|
problems.push(`reset() threw: ${String(e)}`);
|
|
124
148
|
}
|
|
149
|
+
if (options.cost) {
|
|
150
|
+
const cost = options.cost === true ? {} : options.cost;
|
|
151
|
+
try {
|
|
152
|
+
checkReadCost({ name: "state", read: () => impl.state(), options: cost, problems });
|
|
153
|
+
checkReadCost({ name: "describe", read: () => impl.describe(), options: cost, problems });
|
|
154
|
+
} catch (e) {
|
|
155
|
+
problems.push(`cost measurement threw: ${String(e)}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
125
158
|
return { ok: problems.length === 0, problems };
|
|
126
159
|
};
|
|
127
160
|
|
|
@@ -597,6 +630,66 @@ var createToolClipPlayer = (options) => {
|
|
|
597
630
|
};
|
|
598
631
|
};
|
|
599
632
|
|
|
633
|
+
// src/frame.ts
|
|
634
|
+
var FRAME_PHASES = ["input", "fixedSimulate", "lateSimulate", "present", "render", "idle"];
|
|
635
|
+
var DEFERRED_QUEUE_ID = {
|
|
636
|
+
DESTRUCTION_EVENTS: "destruction.events",
|
|
637
|
+
BREACH_PAINT: "floorplan.breach-paint",
|
|
638
|
+
AUDIO_VOICES: "audio.voices",
|
|
639
|
+
VEHICLE_CREASE: "vehicles.crease"
|
|
640
|
+
};
|
|
641
|
+
var DEFERRED_PRIORITY = {
|
|
642
|
+
[DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
|
|
643
|
+
[DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
|
|
644
|
+
[DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
|
|
645
|
+
[DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
|
|
646
|
+
};
|
|
647
|
+
function checkDeferredQueue(queue, fill) {
|
|
648
|
+
const problems = [];
|
|
649
|
+
fill();
|
|
650
|
+
const waiting = queue.pending(1);
|
|
651
|
+
if (waiting < 2) problems.push(`fill() must leave at least 2 units waiting (pending is ${waiting})`);
|
|
652
|
+
if (queue.pending(1) !== waiting) problems.push("pending(frame) changed between two calls in the same frame");
|
|
653
|
+
const ran = queue.run(0, () => 1);
|
|
654
|
+
if (ran !== 1) problems.push(`run with a deadline already past must run exactly one unit (ran ${ran})`);
|
|
655
|
+
if (waiting >= 2 && queue.pending(2) !== waiting - 1) problems.push(`one unit ran but pending went from ${waiting} to ${queue.pending(2)}`);
|
|
656
|
+
try {
|
|
657
|
+
queue.attach?.();
|
|
658
|
+
queue.attach?.();
|
|
659
|
+
queue.detach?.();
|
|
660
|
+
queue.detach?.();
|
|
661
|
+
} catch (error) {
|
|
662
|
+
problems.push(`attach/detach must be idempotent: ${error instanceof Error ? error.message : String(error)}`);
|
|
663
|
+
}
|
|
664
|
+
queue.flush();
|
|
665
|
+
if (queue.pending(3) !== 0) problems.push(`flush must leave nothing pending (pending is ${queue.pending(3)})`);
|
|
666
|
+
if (queue.run(0, () => 1) !== 0) problems.push("run on an empty queue must run no unit");
|
|
667
|
+
return { ok: problems.length === 0, problems };
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/warn.ts
|
|
671
|
+
var WARNED_KEY = /* @__PURE__ */ Symbol.for("@adatechnology/game-contracts.warned");
|
|
672
|
+
var warnedKeys = () => {
|
|
673
|
+
const holder = globalThis;
|
|
674
|
+
return holder[WARNED_KEY] ?? (holder[WARNED_KEY] = /* @__PURE__ */ new Set());
|
|
675
|
+
};
|
|
676
|
+
var isProduction = () => {
|
|
677
|
+
try {
|
|
678
|
+
return process.env.NODE_ENV === "production";
|
|
679
|
+
} catch {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
var isQuiet = () => globalThis.__GAME_KIT_QUIET__ === true;
|
|
684
|
+
var warnOnce = (key, message) => {
|
|
685
|
+
if (isQuiet() || isProduction()) return;
|
|
686
|
+
const seen = warnedKeys();
|
|
687
|
+
if (seen.has(key)) return;
|
|
688
|
+
seen.add(key);
|
|
689
|
+
console.warn(`[game-kit] ${message}`);
|
|
690
|
+
};
|
|
691
|
+
var resetWarnOnce = () => warnedKeys().clear();
|
|
692
|
+
|
|
600
693
|
// src/registry.ts
|
|
601
694
|
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
602
695
|
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
@@ -619,10 +712,13 @@ var applyPatches = (entries, patches) => {
|
|
|
619
712
|
for (const [id, patch] of Object.entries(patches ?? {})) {
|
|
620
713
|
const entry = entries.get(id);
|
|
621
714
|
if (entry) entries.set(id, deepMerge(entry, patch));
|
|
715
|
+
else warnOnce(`registry.patch.${id}`, `patch for "${id}" ignored: no entry has that id`);
|
|
622
716
|
}
|
|
623
717
|
};
|
|
624
718
|
var removeIds = (entries, ids) => {
|
|
625
|
-
for (const id of ids ?? [])
|
|
719
|
+
for (const id of ids ?? []) {
|
|
720
|
+
if (!entries.delete(id)) warnOnce(`registry.remove.${id}`, `remove of "${id}" ignored: no entry has that id`);
|
|
721
|
+
}
|
|
626
722
|
};
|
|
627
723
|
|
|
628
724
|
// src/bench.ts
|
|
@@ -861,14 +957,135 @@ function footprintBlocker(object, footprint) {
|
|
|
861
957
|
return lx > fp.minX - radius && lx < fp.maxX + radius && lz > fp.minZ - radius && lz < fp.maxZ + radius;
|
|
862
958
|
};
|
|
863
959
|
}
|
|
960
|
+
|
|
961
|
+
// src/foley.ts
|
|
962
|
+
var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
|
|
963
|
+
var DEFAULT_SURFACE = "concrete";
|
|
964
|
+
var GAIT_IDS = ["walk", "run"];
|
|
965
|
+
var LANDING_IDS = ["light", "heavy"];
|
|
966
|
+
var HEAVY_LANDING_SPEED = 5.5;
|
|
967
|
+
var BLOW_IDS = ["punch", "kick", "shove", "blade", "blunt", "chop"];
|
|
968
|
+
var BODY_SOUND_IDS = [
|
|
969
|
+
"jump",
|
|
970
|
+
"cloth_rustle",
|
|
971
|
+
"body_fall",
|
|
972
|
+
"fall_damage",
|
|
973
|
+
"player_hurt",
|
|
974
|
+
"player_breath_run",
|
|
975
|
+
"player_death",
|
|
976
|
+
"bite",
|
|
977
|
+
"grab",
|
|
978
|
+
"punch_swing",
|
|
979
|
+
"punch_hit_body",
|
|
980
|
+
"punch_hit_face",
|
|
981
|
+
"punch_hit_object",
|
|
982
|
+
"kick_swing",
|
|
983
|
+
"kick_hit",
|
|
984
|
+
"kick_hit_object",
|
|
985
|
+
"shove_two_hands",
|
|
986
|
+
"knife_swing",
|
|
987
|
+
"knife_stab",
|
|
988
|
+
"knife_slash",
|
|
989
|
+
"knife_hit_object",
|
|
990
|
+
"blunt_swing",
|
|
991
|
+
"blunt_hit",
|
|
992
|
+
"blunt_hit_object",
|
|
993
|
+
"axe_swing",
|
|
994
|
+
"axe_chop",
|
|
995
|
+
"axe_hit_object"
|
|
996
|
+
];
|
|
997
|
+
var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
|
|
998
|
+
var landSoundId = (surface, fallSpeed) => `land_${surface}_${fallSpeed >= HEAVY_LANDING_SPEED ? "heavy" : "light"}`;
|
|
999
|
+
var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
|
|
1000
|
+
var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing) => `land_${surface}_${landing}`));
|
|
1001
|
+
var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
|
|
1002
|
+
var SWING = {
|
|
1003
|
+
punch: "punch_swing",
|
|
1004
|
+
kick: "kick_swing",
|
|
1005
|
+
// two hands pushed out do not whistle: the shove is one sound, at the contact
|
|
1006
|
+
shove: null,
|
|
1007
|
+
blade: "knife_swing",
|
|
1008
|
+
blunt: "blunt_swing",
|
|
1009
|
+
chop: "axe_swing"
|
|
1010
|
+
};
|
|
1011
|
+
var SWING_LEAD_SECONDS = { punch: 0.07, kick: 0.09, shove: 0, blade: 0.05, blunt: 0.1, chop: 0.11 };
|
|
1012
|
+
var swingSoundId = (blow) => SWING[blow];
|
|
1013
|
+
var HIT = {
|
|
1014
|
+
punch: { body: "punch_hit_body", head: "punch_hit_face", object: "punch_hit_object" },
|
|
1015
|
+
kick: { body: "kick_hit", head: "kick_hit", object: "kick_hit_object" },
|
|
1016
|
+
shove: { body: "shove_two_hands", head: "shove_two_hands", object: "shove_two_hands" },
|
|
1017
|
+
blade: { body: "knife_stab", head: "knife_stab", object: "knife_hit_object" },
|
|
1018
|
+
blunt: { body: "blunt_hit", head: "blunt_hit", object: "blunt_hit_object" },
|
|
1019
|
+
chop: { body: "axe_chop", head: "axe_chop", object: "axe_hit_object" }
|
|
1020
|
+
};
|
|
1021
|
+
var hitSoundId = (blow, target) => HIT[blow][target];
|
|
1022
|
+
var MATERIAL_SURFACES = {
|
|
1023
|
+
concrete: "concrete",
|
|
1024
|
+
mortar: "concrete",
|
|
1025
|
+
stone: "concrete",
|
|
1026
|
+
brick: "concrete",
|
|
1027
|
+
plaster: "concrete",
|
|
1028
|
+
asphalt: "asphalt",
|
|
1029
|
+
wood_soft: "wood",
|
|
1030
|
+
wood_hard: "wood",
|
|
1031
|
+
green_wood: "wood",
|
|
1032
|
+
plywood: "wood",
|
|
1033
|
+
mdf: "wood",
|
|
1034
|
+
ceramic: "tile",
|
|
1035
|
+
plastic: "tile",
|
|
1036
|
+
soil: "dirt",
|
|
1037
|
+
wax: "dirt",
|
|
1038
|
+
flesh_fruit: "dirt",
|
|
1039
|
+
turf: "grass",
|
|
1040
|
+
foliage: "grass",
|
|
1041
|
+
cactus: "grass",
|
|
1042
|
+
gravel: "gravel",
|
|
1043
|
+
sand: "sand",
|
|
1044
|
+
steel: "metal",
|
|
1045
|
+
cast_iron: "metal",
|
|
1046
|
+
aluminium: "metal",
|
|
1047
|
+
copper: "metal",
|
|
1048
|
+
water: "water",
|
|
1049
|
+
glass: "glass",
|
|
1050
|
+
tempered_glass: "glass",
|
|
1051
|
+
fabric: "carpet",
|
|
1052
|
+
foam: "carpet",
|
|
1053
|
+
leather: "carpet",
|
|
1054
|
+
rubber: "carpet",
|
|
1055
|
+
paper: "carpet"
|
|
1056
|
+
};
|
|
1057
|
+
var isSurfaceId = (value) => typeof value === "string" && SURFACE_IDS.includes(value);
|
|
1058
|
+
function surfaceOfMaterial(material, table = MATERIAL_SURFACES, fallback = DEFAULT_SURFACE) {
|
|
1059
|
+
if (material === void 0) return fallback;
|
|
1060
|
+
if (isSurfaceId(material)) return material;
|
|
1061
|
+
return table[material] ?? fallback;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// src/index.ts
|
|
1065
|
+
var resetWarnOnce2 = resetWarnOnce;
|
|
864
1066
|
export {
|
|
1067
|
+
BLOW_IDS,
|
|
1068
|
+
BODY_FOLEY_IDS,
|
|
1069
|
+
BODY_SOUND_IDS,
|
|
865
1070
|
DEFAULT_BLAST_SHOVE,
|
|
866
1071
|
DEFAULT_ENVIRONMENT,
|
|
867
1072
|
DEFAULT_IGNITION_RULES,
|
|
1073
|
+
DEFAULT_SURFACE,
|
|
1074
|
+
DEFERRED_PRIORITY,
|
|
1075
|
+
DEFERRED_QUEUE_ID,
|
|
1076
|
+
FOOTSTEP_SOUND_IDS,
|
|
1077
|
+
FRAME_PHASES,
|
|
1078
|
+
GAIT_IDS,
|
|
1079
|
+
HEAVY_LANDING_SPEED,
|
|
868
1080
|
IMPACT_CONTRACT,
|
|
869
1081
|
KIT_ORIGIN_KEY,
|
|
1082
|
+
LANDING_IDS,
|
|
1083
|
+
LAND_SOUND_IDS,
|
|
1084
|
+
MATERIAL_SURFACES,
|
|
870
1085
|
MISSING_BITS,
|
|
871
1086
|
STAGE_EVENT,
|
|
1087
|
+
SURFACE_IDS,
|
|
1088
|
+
SWING_LEAD_SECONDS,
|
|
872
1089
|
TOOL_CLIP,
|
|
873
1090
|
TWIST_LIFT,
|
|
874
1091
|
applyPatches,
|
|
@@ -876,6 +1093,7 @@ export {
|
|
|
876
1093
|
checkAnimation,
|
|
877
1094
|
checkBench,
|
|
878
1095
|
checkCategorized,
|
|
1096
|
+
checkDeferredQueue,
|
|
879
1097
|
checkDestructible,
|
|
880
1098
|
checkHit,
|
|
881
1099
|
checkSpec,
|
|
@@ -886,11 +1104,16 @@ export {
|
|
|
886
1104
|
defineCategories,
|
|
887
1105
|
fillFactor,
|
|
888
1106
|
footprintBlocker,
|
|
1107
|
+
footstepSoundId,
|
|
1108
|
+
hitSoundId,
|
|
889
1109
|
ignitionChance,
|
|
1110
|
+
isSurfaceId,
|
|
890
1111
|
kitOriginOf,
|
|
1112
|
+
landSoundId,
|
|
891
1113
|
markKitOrigin,
|
|
892
1114
|
mergeById,
|
|
893
1115
|
removeIds,
|
|
1116
|
+
resetWarnOnce2 as resetWarnOnce,
|
|
894
1117
|
resolveEntry,
|
|
895
1118
|
resolveIgnitionRules,
|
|
896
1119
|
sampleClip,
|
|
@@ -900,9 +1123,12 @@ export {
|
|
|
900
1123
|
shotExtras,
|
|
901
1124
|
shotToHit,
|
|
902
1125
|
sparkTargetFactor,
|
|
1126
|
+
surfaceOfMaterial,
|
|
1127
|
+
swingSoundId,
|
|
903
1128
|
toolAnimationStep,
|
|
904
1129
|
twistStroke,
|
|
905
1130
|
unmarkedDrawings,
|
|
906
|
-
useToHit
|
|
1131
|
+
useToHit,
|
|
1132
|
+
warnOnce
|
|
907
1133
|
};
|
|
908
1134
|
//# sourceMappingURL=index.js.map
|