quake2ts 0.0.7 → 0.0.39

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.
Files changed (177) hide show
  1. package/README.md +425 -0
  2. package/apps/viewer/dist/browser/index.global.js +1 -1
  3. package/apps/viewer/dist/browser/index.global.js.map +1 -1
  4. package/apps/viewer/dist/cjs/index.cjs +2097 -295
  5. package/apps/viewer/dist/cjs/index.cjs.map +1 -1
  6. package/apps/viewer/dist/esm/index.js +2097 -295
  7. package/apps/viewer/dist/esm/index.js.map +1 -1
  8. package/apps/viewer/dist/tsconfig.tsbuildinfo +1 -1
  9. package/apps/viewer/dist/types/index.d.ts +1 -1
  10. package/package.json +1 -1
  11. package/packages/client/dist/browser/index.global.js +1 -1
  12. package/packages/client/dist/browser/index.global.js.map +1 -1
  13. package/packages/client/dist/cjs/index.cjs +1200 -13
  14. package/packages/client/dist/cjs/index.cjs.map +1 -1
  15. package/packages/client/dist/esm/index.js +1186 -12
  16. package/packages/client/dist/esm/index.js.map +1 -1
  17. package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
  18. package/packages/client/dist/types/index.d.ts +14 -6
  19. package/packages/client/dist/types/index.d.ts.map +1 -1
  20. package/packages/client/dist/types/input/bindings.d.ts +18 -0
  21. package/packages/client/dist/types/input/bindings.d.ts.map +1 -0
  22. package/packages/client/dist/types/input/command-buffer.d.ts +15 -0
  23. package/packages/client/dist/types/input/command-buffer.d.ts.map +1 -0
  24. package/packages/client/dist/types/input/controller.d.ts +125 -0
  25. package/packages/client/dist/types/input/controller.d.ts.map +1 -0
  26. package/packages/client/dist/types/prediction.d.ts +38 -0
  27. package/packages/client/dist/types/prediction.d.ts.map +1 -0
  28. package/packages/client/dist/types/view-effects.d.ts +41 -0
  29. package/packages/client/dist/types/view-effects.d.ts.map +1 -0
  30. package/packages/engine/dist/browser/index.global.js +257 -1
  31. package/packages/engine/dist/browser/index.global.js.map +1 -1
  32. package/packages/engine/dist/cjs/index.cjs +2408 -2
  33. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  34. package/packages/engine/dist/esm/index.js +2340 -2
  35. package/packages/engine/dist/esm/index.js.map +1 -1
  36. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  37. package/packages/engine/dist/types/assets/animation.d.ts +33 -0
  38. package/packages/engine/dist/types/assets/animation.d.ts.map +1 -0
  39. package/packages/engine/dist/types/assets/audio.d.ts +21 -0
  40. package/packages/engine/dist/types/assets/audio.d.ts.map +1 -0
  41. package/packages/engine/dist/types/assets/bsp.d.ts +1 -1
  42. package/packages/engine/dist/types/assets/bsp.d.ts.map +1 -1
  43. package/packages/engine/dist/types/assets/ingestion.d.ts +31 -0
  44. package/packages/engine/dist/types/assets/ingestion.d.ts.map +1 -1
  45. package/packages/engine/dist/types/assets/manager.d.ts +43 -0
  46. package/packages/engine/dist/types/assets/manager.d.ts.map +1 -0
  47. package/packages/engine/dist/types/assets/md3.d.ts +69 -0
  48. package/packages/engine/dist/types/assets/md3.d.ts.map +1 -0
  49. package/packages/engine/dist/types/assets/ogg.d.ts +12 -0
  50. package/packages/engine/dist/types/assets/ogg.d.ts.map +1 -0
  51. package/packages/engine/dist/types/assets/pakIndexStore.d.ts +19 -0
  52. package/packages/engine/dist/types/assets/pakIndexStore.d.ts.map +1 -0
  53. package/packages/engine/dist/types/assets/pakValidation.d.ts +28 -0
  54. package/packages/engine/dist/types/assets/pakValidation.d.ts.map +1 -0
  55. package/packages/engine/dist/types/assets/pcx.d.ts +13 -0
  56. package/packages/engine/dist/types/assets/pcx.d.ts.map +1 -0
  57. package/packages/engine/dist/types/assets/texture.d.ts +29 -0
  58. package/packages/engine/dist/types/assets/texture.d.ts.map +1 -0
  59. package/packages/engine/dist/types/assets/wal.d.ts +21 -0
  60. package/packages/engine/dist/types/assets/wal.d.ts.map +1 -0
  61. package/packages/engine/dist/types/assets/wav.d.ts +11 -0
  62. package/packages/engine/dist/types/assets/wav.d.ts.map +1 -0
  63. package/packages/engine/dist/types/audio/api.d.ts +29 -0
  64. package/packages/engine/dist/types/audio/api.d.ts.map +1 -0
  65. package/packages/engine/dist/types/audio/channels.d.ts +15 -0
  66. package/packages/engine/dist/types/audio/channels.d.ts.map +1 -0
  67. package/packages/engine/dist/types/audio/constants.d.ts +24 -0
  68. package/packages/engine/dist/types/audio/constants.d.ts.map +1 -0
  69. package/packages/engine/dist/types/audio/context.d.ts +67 -0
  70. package/packages/engine/dist/types/audio/context.d.ts.map +1 -0
  71. package/packages/engine/dist/types/audio/music.d.ts +42 -0
  72. package/packages/engine/dist/types/audio/music.d.ts.map +1 -0
  73. package/packages/engine/dist/types/audio/precache.d.ts +28 -0
  74. package/packages/engine/dist/types/audio/precache.d.ts.map +1 -0
  75. package/packages/engine/dist/types/audio/registry.d.ts +13 -0
  76. package/packages/engine/dist/types/audio/registry.d.ts.map +1 -0
  77. package/packages/engine/dist/types/audio/spatialization.d.ts +14 -0
  78. package/packages/engine/dist/types/audio/spatialization.d.ts.map +1 -0
  79. package/packages/engine/dist/types/audio/system.d.ts +101 -0
  80. package/packages/engine/dist/types/audio/system.d.ts.map +1 -0
  81. package/packages/engine/dist/types/configstrings.d.ts +1 -0
  82. package/packages/engine/dist/types/configstrings.d.ts.map +1 -1
  83. package/packages/engine/dist/types/index.d.ts +26 -1
  84. package/packages/engine/dist/types/index.d.ts.map +1 -1
  85. package/packages/engine/dist/types/render/bspPipeline.d.ts +42 -0
  86. package/packages/engine/dist/types/render/bspPipeline.d.ts.map +1 -0
  87. package/packages/engine/dist/types/render/bspTraversal.d.ts +11 -0
  88. package/packages/engine/dist/types/render/bspTraversal.d.ts.map +1 -0
  89. package/packages/engine/dist/types/render/culling.d.ts +8 -0
  90. package/packages/engine/dist/types/render/culling.d.ts.map +1 -0
  91. package/packages/engine/dist/types/render/md2Pipeline.d.ts +51 -0
  92. package/packages/engine/dist/types/render/md2Pipeline.d.ts.map +1 -0
  93. package/packages/engine/dist/types/render/resources.d.ts +10 -0
  94. package/packages/engine/dist/types/render/resources.d.ts.map +1 -1
  95. package/packages/engine/dist/types/render/skybox.d.ts +26 -0
  96. package/packages/engine/dist/types/render/skybox.d.ts.map +1 -0
  97. package/packages/game/dist/browser/index.global.js +1 -1
  98. package/packages/game/dist/browser/index.global.js.map +1 -1
  99. package/packages/game/dist/cjs/index.cjs +2926 -116
  100. package/packages/game/dist/cjs/index.cjs.map +1 -1
  101. package/packages/game/dist/esm/index.js +2863 -115
  102. package/packages/game/dist/esm/index.js.map +1 -1
  103. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  104. package/packages/game/dist/types/ai/constants.d.ts +13 -0
  105. package/packages/game/dist/types/ai/constants.d.ts.map +1 -0
  106. package/packages/game/dist/types/ai/index.d.ts +4 -0
  107. package/packages/game/dist/types/ai/index.d.ts.map +1 -0
  108. package/packages/game/dist/types/ai/movement.d.ts +20 -0
  109. package/packages/game/dist/types/ai/movement.d.ts.map +1 -0
  110. package/packages/game/dist/types/ai/perception.d.ts +21 -0
  111. package/packages/game/dist/types/ai/perception.d.ts.map +1 -0
  112. package/packages/game/dist/types/checksum.d.ts +3 -0
  113. package/packages/game/dist/types/checksum.d.ts.map +1 -0
  114. package/packages/game/dist/types/combat/armor.d.ts +39 -0
  115. package/packages/game/dist/types/combat/armor.d.ts.map +1 -0
  116. package/packages/game/dist/types/combat/damage.d.ts +52 -0
  117. package/packages/game/dist/types/combat/damage.d.ts.map +1 -0
  118. package/packages/game/dist/types/combat/damageFlags.d.ts +15 -0
  119. package/packages/game/dist/types/combat/damageFlags.d.ts.map +1 -0
  120. package/packages/game/dist/types/combat/damageMods.d.ts +79 -0
  121. package/packages/game/dist/types/combat/damageMods.d.ts.map +1 -0
  122. package/packages/game/dist/types/combat/index.d.ts +6 -0
  123. package/packages/game/dist/types/combat/index.d.ts.map +1 -0
  124. package/packages/game/dist/types/combat/specialDamage.d.ts +88 -0
  125. package/packages/game/dist/types/combat/specialDamage.d.ts.map +1 -0
  126. package/packages/game/dist/types/entities/entity.d.ts +46 -2
  127. package/packages/game/dist/types/entities/entity.d.ts.map +1 -1
  128. package/packages/game/dist/types/entities/index.d.ts +6 -2
  129. package/packages/game/dist/types/entities/index.d.ts.map +1 -1
  130. package/packages/game/dist/types/entities/pool.d.ts +9 -0
  131. package/packages/game/dist/types/entities/pool.d.ts.map +1 -1
  132. package/packages/game/dist/types/entities/spawn.d.ts +27 -0
  133. package/packages/game/dist/types/entities/spawn.d.ts.map +1 -0
  134. package/packages/game/dist/types/entities/system.d.ts +32 -1
  135. package/packages/game/dist/types/entities/system.d.ts.map +1 -1
  136. package/packages/game/dist/types/entities/thinkScheduler.d.ts +6 -0
  137. package/packages/game/dist/types/entities/thinkScheduler.d.ts.map +1 -1
  138. package/packages/game/dist/types/entities/triggers.d.ts +3 -0
  139. package/packages/game/dist/types/entities/triggers.d.ts.map +1 -0
  140. package/packages/game/dist/types/entities/utils.d.ts +4 -0
  141. package/packages/game/dist/types/entities/utils.d.ts.map +1 -0
  142. package/packages/game/dist/types/index.d.ts +5 -0
  143. package/packages/game/dist/types/index.d.ts.map +1 -1
  144. package/packages/game/dist/types/inventory/ammo.d.ts +17 -0
  145. package/packages/game/dist/types/inventory/ammo.d.ts.map +1 -0
  146. package/packages/game/dist/types/inventory/index.d.ts +2 -0
  147. package/packages/game/dist/types/inventory/index.d.ts.map +1 -0
  148. package/packages/game/dist/types/level.d.ts +1 -0
  149. package/packages/game/dist/types/level.d.ts.map +1 -1
  150. package/packages/game/dist/types/save/index.d.ts +4 -0
  151. package/packages/game/dist/types/save/index.d.ts.map +1 -0
  152. package/packages/game/dist/types/save/rerelease.d.ts +25 -0
  153. package/packages/game/dist/types/save/rerelease.d.ts.map +1 -0
  154. package/packages/game/dist/types/save/save.d.ts +49 -0
  155. package/packages/game/dist/types/save/save.d.ts.map +1 -0
  156. package/packages/game/dist/types/save/storage.d.ts +37 -0
  157. package/packages/game/dist/types/save/storage.d.ts.map +1 -0
  158. package/packages/shared/dist/browser/index.global.js +1 -1
  159. package/packages/shared/dist/browser/index.global.js.map +1 -1
  160. package/packages/shared/dist/cjs/index.cjs +638 -9
  161. package/packages/shared/dist/cjs/index.cjs.map +1 -1
  162. package/packages/shared/dist/esm/index.js +616 -9
  163. package/packages/shared/dist/esm/index.js.map +1 -1
  164. package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
  165. package/packages/shared/dist/types/bsp/collision.d.ts +56 -0
  166. package/packages/shared/dist/types/bsp/collision.d.ts.map +1 -1
  167. package/packages/shared/dist/types/bsp/contents.d.ts +1 -0
  168. package/packages/shared/dist/types/bsp/contents.d.ts.map +1 -1
  169. package/packages/shared/dist/types/index.d.ts +2 -0
  170. package/packages/shared/dist/types/index.d.ts.map +1 -1
  171. package/packages/shared/dist/types/math/random.d.ts +11 -0
  172. package/packages/shared/dist/types/math/random.d.ts.map +1 -1
  173. package/packages/shared/dist/types/protocol/contracts.d.ts +17 -0
  174. package/packages/shared/dist/types/protocol/contracts.d.ts.map +1 -0
  175. package/packages/shared/dist/types/protocol/usercmd.d.ts +30 -0
  176. package/packages/shared/dist/types/protocol/usercmd.d.ts.map +1 -0
  177. package/packages/tools/dist/tsconfig.tsbuildinfo +1 -1
@@ -25,30 +25,719 @@ __export(index_exports, {
25
25
  module.exports = __toCommonJS(index_exports);
26
26
 
27
27
  // ../../packages/client/dist/esm/index.js
28
+ var ZERO_VEC3 = { x: 0, y: 0, z: 0 };
29
+ var DEG_TO_RAD = Math.PI / 180;
30
+ function addVec3(a, b) {
31
+ return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
32
+ }
33
+ function scaleVec3(a, scalar) {
34
+ return { x: a.x * scalar, y: a.y * scalar, z: a.z * scalar };
35
+ }
36
+ function dotVec3(a, b) {
37
+ return a.x * b.x + a.y * b.y + a.z * b.z;
38
+ }
39
+ function lengthSquaredVec3(a) {
40
+ return dotVec3(a, a);
41
+ }
42
+ function lengthVec3(a) {
43
+ return Math.sqrt(lengthSquaredVec3(a));
44
+ }
45
+ function normalizeVec3(a) {
46
+ const len = lengthVec3(a);
47
+ return len === 0 ? a : scaleVec3(a, 1 / len);
48
+ }
49
+ var PITCH = 0;
50
+ var YAW = 1;
51
+ var ROLL = 2;
52
+ var DEG2RAD_FACTOR = Math.PI / 180;
53
+ var RAD2DEG_FACTOR = 180 / Math.PI;
54
+ function axisComponent(vec, axis) {
55
+ switch (axis) {
56
+ case PITCH:
57
+ return vec.x;
58
+ case YAW:
59
+ return vec.y;
60
+ case ROLL:
61
+ default:
62
+ return vec.z;
63
+ }
64
+ }
65
+ function degToRad(degrees) {
66
+ return degrees * DEG2RAD_FACTOR;
67
+ }
68
+ function angleMod(angle) {
69
+ const value = angle % 360;
70
+ return value < 0 ? 360 + value : value;
71
+ }
72
+ function angleVectors(angles) {
73
+ const yaw = degToRad(axisComponent(angles, YAW));
74
+ const pitch = degToRad(axisComponent(angles, PITCH));
75
+ const roll = degToRad(axisComponent(angles, ROLL));
76
+ const sy = Math.sin(yaw);
77
+ const cy = Math.cos(yaw);
78
+ const sp = Math.sin(pitch);
79
+ const cp = Math.cos(pitch);
80
+ const sr = Math.sin(roll);
81
+ const cr = Math.cos(roll);
82
+ const forward = {
83
+ x: cp * cy,
84
+ y: cp * sy,
85
+ z: -sp
86
+ };
87
+ const right = {
88
+ x: -sr * sp * cy - cr * -sy,
89
+ y: -sr * sp * sy - cr * cy,
90
+ z: -sr * cp
91
+ };
92
+ const up = {
93
+ x: cr * sp * cy - sr * -sy,
94
+ y: cr * sp * sy - sr * cy,
95
+ z: cr * cp
96
+ };
97
+ return { forward, right, up };
98
+ }
99
+ var CONTENTS_SOLID = 1 << 0;
100
+ var CONTENTS_WINDOW = 1 << 1;
101
+ var CONTENTS_AUX = 1 << 2;
102
+ var CONTENTS_LAVA = 1 << 3;
103
+ var CONTENTS_SLIME = 1 << 4;
104
+ var CONTENTS_WATER = 1 << 5;
105
+ var CONTENTS_MIST = 1 << 6;
106
+ var CONTENTS_NO_WATERJUMP = 1 << 13;
107
+ var CONTENTS_PROJECTILECLIP = 1 << 14;
108
+ var CONTENTS_AREAPORTAL = 1 << 15;
109
+ var CONTENTS_PLAYERCLIP = 1 << 16;
110
+ var CONTENTS_MONSTERCLIP = 1 << 17;
111
+ var CONTENTS_CURRENT_0 = 1 << 18;
112
+ var CONTENTS_CURRENT_90 = 1 << 19;
113
+ var CONTENTS_CURRENT_180 = 1 << 20;
114
+ var CONTENTS_CURRENT_270 = 1 << 21;
115
+ var CONTENTS_CURRENT_UP = 1 << 22;
116
+ var CONTENTS_CURRENT_DOWN = 1 << 23;
117
+ var CONTENTS_ORIGIN = 1 << 24;
118
+ var CONTENTS_MONSTER = 1 << 25;
119
+ var CONTENTS_DEADMONSTER = 1 << 26;
120
+ var CONTENTS_DETAIL = 1 << 27;
121
+ var CONTENTS_TRANSLUCENT = 1 << 28;
122
+ var CONTENTS_LADDER = 1 << 29;
123
+ var CONTENTS_PLAYER = 1 << 30;
124
+ var CONTENTS_PROJECTILE = 1 << 31;
125
+ var SURF_LIGHT = 1 << 0;
126
+ var SURF_SLICK = 1 << 1;
127
+ var SURF_SKY = 1 << 2;
128
+ var SURF_WARP = 1 << 3;
129
+ var SURF_TRANS33 = 1 << 4;
130
+ var SURF_TRANS66 = 1 << 5;
131
+ var SURF_FLOWING = 1 << 6;
132
+ var SURF_NODRAW = 1 << 7;
133
+ var SURF_ALPHATEST = 1 << 25;
134
+ var SURF_N64_UV = 1 << 28;
135
+ var SURF_N64_SCROLL_X = 1 << 29;
136
+ var SURF_N64_SCROLL_Y = 1 << 30;
137
+ var SURF_N64_SCROLL_FLIP = 1 << 31;
138
+ var MASK_SOLID = CONTENTS_SOLID | CONTENTS_WINDOW;
139
+ var MASK_PLAYERSOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_PLAYER;
140
+ var MASK_DEADSOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW;
141
+ var MASK_MONSTERSOLID = CONTENTS_SOLID | CONTENTS_MONSTERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_PLAYER;
142
+ var MASK_WATER = CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME;
143
+ var MASK_OPAQUE = CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA;
144
+ var MASK_SHOT = CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_PLAYER | CONTENTS_WINDOW | CONTENTS_DEADMONSTER;
145
+ var MASK_CURRENT = CONTENTS_CURRENT_0 | CONTENTS_CURRENT_90 | CONTENTS_CURRENT_180 | CONTENTS_CURRENT_270 | CONTENTS_CURRENT_UP | CONTENTS_CURRENT_DOWN;
146
+ var MASK_BLOCK_SIGHT = CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_MONSTER | CONTENTS_PLAYER;
147
+ var MASK_NAV_SOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW;
148
+ var MASK_LADDER_NAV_SOLID = CONTENTS_SOLID | CONTENTS_WINDOW;
149
+ var MASK_WALK_NAV_SOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTERCLIP;
150
+ var MASK_PROJECTILE = MASK_SHOT | CONTENTS_PROJECTILECLIP;
151
+ var MAX_CHECKCOUNT = Number.MAX_SAFE_INTEGER - 1;
152
+ var MAX_CLIENTS = 256;
153
+ var MAX_LIGHTSTYLES = 256;
154
+ var MAX_MODELS = 8192;
155
+ var MAX_SOUNDS = 2048;
156
+ var MAX_IMAGES = 512;
157
+ var MAX_ITEMS = 256;
158
+ var MAX_GENERAL = MAX_CLIENTS * 2;
159
+ var MAX_SHADOW_LIGHTS = 256;
160
+ var MAX_WHEEL_ITEMS = 32;
161
+ var ConfigStringIndex = ((ConfigStringIndex22) => {
162
+ ConfigStringIndex22[ConfigStringIndex22["Name"] = 0] = "Name";
163
+ ConfigStringIndex22[ConfigStringIndex22["CdTrack"] = 1] = "CdTrack";
164
+ ConfigStringIndex22[ConfigStringIndex22["Sky"] = 2] = "Sky";
165
+ ConfigStringIndex22[ConfigStringIndex22["SkyAxis"] = 3] = "SkyAxis";
166
+ ConfigStringIndex22[ConfigStringIndex22["SkyRotate"] = 4] = "SkyRotate";
167
+ ConfigStringIndex22[ConfigStringIndex22["StatusBar"] = 5] = "StatusBar";
168
+ ConfigStringIndex22[ConfigStringIndex22["AirAccel"] = 59] = "AirAccel";
169
+ ConfigStringIndex22[ConfigStringIndex22["MaxClients"] = 60] = "MaxClients";
170
+ ConfigStringIndex22[ConfigStringIndex22["MapChecksum"] = 61] = "MapChecksum";
171
+ ConfigStringIndex22[ConfigStringIndex22["Models"] = 62] = "Models";
172
+ ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS] = "Sounds";
173
+ ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS] = "Images";
174
+ ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES] = "Lights";
175
+ ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES] = "ShadowLights";
176
+ ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS] = "Items";
177
+ ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS] = "PlayerSkins";
178
+ ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS] = "General";
179
+ ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL] = "WheelWeapons";
180
+ ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS] = "WheelAmmo";
181
+ ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS] = "WheelPowerups";
182
+ ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS] = "CdLoopCount";
183
+ ConfigStringIndex22[ConfigStringIndex22["GameStyle"] = ConfigStringIndex22.CdLoopCount + 1] = "GameStyle";
184
+ ConfigStringIndex22[ConfigStringIndex22["MaxConfigStrings"] = ConfigStringIndex22.GameStyle + 1] = "MaxConfigStrings";
185
+ return ConfigStringIndex22;
186
+ })(ConfigStringIndex || {});
187
+ var MAX_CONFIGSTRINGS = ConfigStringIndex.MaxConfigStrings;
188
+ var WaterLevel = /* @__PURE__ */ ((WaterLevel3) => {
189
+ WaterLevel3[WaterLevel3["None"] = 0] = "None";
190
+ WaterLevel3[WaterLevel3["Feet"] = 1] = "Feet";
191
+ WaterLevel3[WaterLevel3["Waist"] = 2] = "Waist";
192
+ WaterLevel3[WaterLevel3["Under"] = 3] = "Under";
193
+ return WaterLevel3;
194
+ })(WaterLevel || {});
195
+ var PmFlag = /* @__PURE__ */ ((PmFlag2) => {
196
+ PmFlag2[PmFlag2["Ducked"] = 1] = "Ducked";
197
+ PmFlag2[PmFlag2["JumpHeld"] = 2] = "JumpHeld";
198
+ PmFlag2[PmFlag2["OnGround"] = 4] = "OnGround";
199
+ PmFlag2[PmFlag2["TimeWaterJump"] = 8] = "TimeWaterJump";
200
+ PmFlag2[PmFlag2["TimeLand"] = 16] = "TimeLand";
201
+ PmFlag2[PmFlag2["TimeTeleport"] = 32] = "TimeTeleport";
202
+ PmFlag2[PmFlag2["NoPositionalPrediction"] = 64] = "NoPositionalPrediction";
203
+ PmFlag2[PmFlag2["OnLadder"] = 128] = "OnLadder";
204
+ PmFlag2[PmFlag2["NoAngularPrediction"] = 256] = "NoAngularPrediction";
205
+ PmFlag2[PmFlag2["IgnorePlayerCollision"] = 512] = "IgnorePlayerCollision";
206
+ PmFlag2[PmFlag2["TimeTrick"] = 1024] = "TimeTrick";
207
+ return PmFlag2;
208
+ })(PmFlag || {});
209
+ function hasPmFlag(flags, flag) {
210
+ return (flags & flag) !== 0;
211
+ }
212
+ var PmType = /* @__PURE__ */ ((PmType2) => {
213
+ PmType2[PmType2["Normal"] = 0] = "Normal";
214
+ PmType2[PmType2["Grapple"] = 1] = "Grapple";
215
+ PmType2[PmType2["NoClip"] = 2] = "NoClip";
216
+ PmType2[PmType2["Spectator"] = 3] = "Spectator";
217
+ PmType2[PmType2["Dead"] = 4] = "Dead";
218
+ PmType2[PmType2["Gib"] = 5] = "Gib";
219
+ PmType2[PmType2["Freeze"] = 6] = "Freeze";
220
+ return PmType2;
221
+ })(PmType || {});
222
+ var PlayerButton = /* @__PURE__ */ ((PlayerButton2) => {
223
+ PlayerButton2[PlayerButton2["None"] = 0] = "None";
224
+ PlayerButton2[PlayerButton2["Attack"] = 1] = "Attack";
225
+ PlayerButton2[PlayerButton2["Use"] = 2] = "Use";
226
+ PlayerButton2[PlayerButton2["Holster"] = 4] = "Holster";
227
+ PlayerButton2[PlayerButton2["Jump"] = 8] = "Jump";
228
+ PlayerButton2[PlayerButton2["Crouch"] = 16] = "Crouch";
229
+ PlayerButton2[PlayerButton2["Any"] = 128] = "Any";
230
+ return PlayerButton2;
231
+ })(PlayerButton || {});
232
+ function applyPmoveFriction(params) {
233
+ const {
234
+ velocity,
235
+ frametime,
236
+ onGround,
237
+ groundIsSlick,
238
+ onLadder,
239
+ waterlevel,
240
+ pmFriction,
241
+ pmStopSpeed,
242
+ pmWaterFriction
243
+ } = params;
244
+ const speed = lengthVec3(velocity);
245
+ if (speed < 1) {
246
+ return { x: 0, y: 0, z: velocity.z };
247
+ }
248
+ let drop = 0;
249
+ if (onGround && !groundIsSlick || onLadder) {
250
+ const control = speed < pmStopSpeed ? pmStopSpeed : speed;
251
+ const friction = pmFriction;
252
+ drop += control * friction * frametime;
253
+ }
254
+ if (waterlevel > 0 && !onLadder) {
255
+ drop += speed * pmWaterFriction * waterlevel * frametime;
256
+ }
257
+ let newspeed = speed - drop;
258
+ if (newspeed < 0) {
259
+ newspeed = 0;
260
+ }
261
+ if (newspeed === speed) {
262
+ return velocity;
263
+ }
264
+ const scale = newspeed / speed;
265
+ return scaleVec3(velocity, scale);
266
+ }
267
+ function applyPmoveAccelerate(params) {
268
+ const { velocity, wishdir, wishspeed, accel, frametime } = params;
269
+ const currentSpeed = dotVec3(velocity, wishdir);
270
+ const addSpeed = wishspeed - currentSpeed;
271
+ if (addSpeed <= 0) {
272
+ return velocity;
273
+ }
274
+ let accelSpeed = accel * frametime * wishspeed;
275
+ if (accelSpeed > addSpeed) {
276
+ accelSpeed = addSpeed;
277
+ }
278
+ return {
279
+ x: velocity.x + wishdir.x * accelSpeed,
280
+ y: velocity.y + wishdir.y * accelSpeed,
281
+ z: velocity.z + wishdir.z * accelSpeed
282
+ };
283
+ }
284
+ function applyPmoveAirAccelerate(params) {
285
+ const { velocity, wishdir, wishspeed, accel, frametime } = params;
286
+ const wishspd = Math.min(wishspeed, 30);
287
+ const currentSpeed = dotVec3(velocity, wishdir);
288
+ const addSpeed = wishspd - currentSpeed;
289
+ if (addSpeed <= 0) {
290
+ return velocity;
291
+ }
292
+ let accelSpeed = accel * wishspeed * frametime;
293
+ if (accelSpeed > addSpeed) {
294
+ accelSpeed = addSpeed;
295
+ }
296
+ return {
297
+ x: velocity.x + wishdir.x * accelSpeed,
298
+ y: velocity.y + wishdir.y * accelSpeed,
299
+ z: velocity.z + wishdir.z * accelSpeed
300
+ };
301
+ }
302
+ function buildAirGroundWish(params) {
303
+ const { forward, right, cmd, maxSpeed } = params;
304
+ let wishvel = {
305
+ x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
306
+ y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
307
+ z: 0
308
+ };
309
+ let wishspeed = lengthVec3(wishvel);
310
+ if (wishspeed > maxSpeed) {
311
+ const scale = maxSpeed / wishspeed;
312
+ wishvel = scaleVec3(wishvel, scale);
313
+ wishspeed = maxSpeed;
314
+ }
315
+ return {
316
+ wishdir: wishspeed === 0 ? wishvel : normalizeVec3(wishvel),
317
+ wishspeed
318
+ };
319
+ }
320
+ function buildWaterWish(params) {
321
+ const { forward, right, cmd, maxSpeed } = params;
322
+ let wishvel = {
323
+ x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
324
+ y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
325
+ z: 0
326
+ };
327
+ if (cmd.upmove > 10) {
328
+ wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
329
+ } else if (cmd.upmove < -10) {
330
+ wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
331
+ } else {
332
+ wishvel = addVec3(wishvel, { x: 0, y: 0, z: 10 });
333
+ }
334
+ let wishspeed = lengthVec3(wishvel);
335
+ if (wishspeed > maxSpeed) {
336
+ const scale = maxSpeed / wishspeed;
337
+ wishvel = scaleVec3(wishvel, scale);
338
+ wishspeed = maxSpeed;
339
+ }
340
+ wishspeed *= 0.5;
341
+ return {
342
+ wishdir: wishspeed === 0 ? wishvel : normalizeVec3(wishvel),
343
+ wishspeed
344
+ };
345
+ }
346
+ var WATERJUMP_CLEAR = 8 | 16 | 32 | 1024;
347
+ function addAngles(cmdAngles, deltaAngles) {
348
+ return {
349
+ x: cmdAngles.x + deltaAngles.x,
350
+ y: cmdAngles.y + deltaAngles.y,
351
+ z: cmdAngles.z + deltaAngles.z
352
+ };
353
+ }
354
+ function clampPitch(pitch) {
355
+ if (pitch > 89 && pitch < 180) {
356
+ return 89;
357
+ }
358
+ if (pitch < 271 && pitch >= 180) {
359
+ return 271;
360
+ }
361
+ return pitch;
362
+ }
363
+ function clampViewAngles(params) {
364
+ const { pmFlags, cmdAngles, deltaAngles } = params;
365
+ let viewangles;
366
+ if ((pmFlags & 32) !== 0) {
367
+ viewangles = {
368
+ x: 0,
369
+ y: cmdAngles.y + deltaAngles.y,
370
+ z: 0
371
+ };
372
+ } else {
373
+ viewangles = addAngles(cmdAngles, deltaAngles);
374
+ viewangles = { ...viewangles, x: clampPitch(viewangles.x) };
375
+ }
376
+ const vectors = angleVectors(viewangles);
377
+ return { viewangles, ...vectors };
378
+ }
379
+ var DEFAULTS = {
380
+ pmFriction: 6,
381
+ pmStopSpeed: 100,
382
+ pmAccelerate: 10,
383
+ pmAirAccelerate: 1,
384
+ pmWaterAccelerate: 4,
385
+ pmWaterFriction: 1,
386
+ pmMaxSpeed: 300,
387
+ pmDuckSpeed: 100,
388
+ pmWaterSpeed: 400,
389
+ groundIsSlick: false
390
+ };
391
+ var DEFAULT_GRAVITY = 800;
392
+ var ZERO_VEC32 = { x: 0, y: 0, z: 0 };
393
+ var MSEC_MAX = 250;
394
+ function defaultPredictionState() {
395
+ return {
396
+ origin: ZERO_VEC32,
397
+ velocity: ZERO_VEC32,
398
+ viewangles: ZERO_VEC32,
399
+ pmFlags: PmFlag.OnGround,
400
+ pmType: PmType.Normal,
401
+ waterlevel: WaterLevel.None,
402
+ gravity: DEFAULT_GRAVITY,
403
+ deltaAngles: ZERO_VEC32
404
+ };
405
+ }
406
+ function normalizeState(state) {
407
+ if (!state) return defaultPredictionState();
408
+ return {
409
+ ...defaultPredictionState(),
410
+ ...state,
411
+ origin: { ...state.origin },
412
+ velocity: { ...state.velocity },
413
+ viewangles: { ...state.viewangles },
414
+ deltaAngles: state.deltaAngles ? { ...state.deltaAngles } : ZERO_VEC32
415
+ };
416
+ }
417
+ function lerp(a, b, t) {
418
+ return a + (b - a) * t;
419
+ }
420
+ function lerpAngle(a, b, t) {
421
+ let delta = angleMod(b - a);
422
+ if (delta > 180) {
423
+ delta -= 360;
424
+ }
425
+ return angleMod(a + delta * t);
426
+ }
427
+ function interpolatePredictionState(previous, latest, alpha) {
428
+ const clamped = Math.max(0, Math.min(alpha, 1));
429
+ return {
430
+ origin: {
431
+ x: lerp(previous.origin.x, latest.origin.x, clamped),
432
+ y: lerp(previous.origin.y, latest.origin.y, clamped),
433
+ z: lerp(previous.origin.z, latest.origin.z, clamped)
434
+ },
435
+ velocity: {
436
+ x: lerp(previous.velocity.x, latest.velocity.x, clamped),
437
+ y: lerp(previous.velocity.y, latest.velocity.y, clamped),
438
+ z: lerp(previous.velocity.z, latest.velocity.z, clamped)
439
+ },
440
+ viewangles: {
441
+ x: lerpAngle(previous.viewangles.x, latest.viewangles.x, clamped),
442
+ y: lerpAngle(previous.viewangles.y, latest.viewangles.y, clamped),
443
+ z: lerpAngle(previous.viewangles.z, latest.viewangles.z, clamped)
444
+ },
445
+ pmFlags: latest.pmFlags,
446
+ pmType: latest.pmType,
447
+ waterlevel: latest.waterlevel,
448
+ gravity: latest.gravity,
449
+ deltaAngles: latest.deltaAngles
450
+ };
451
+ }
452
+ function simulateCommand(state, cmd, settings) {
453
+ const frametime = Math.min(Math.max(cmd.msec, 0), MSEC_MAX) / 1e3;
454
+ const onGround = hasPmFlag(state.pmFlags, PmFlag.OnGround);
455
+ const onLadder = hasPmFlag(state.pmFlags, PmFlag.OnLadder);
456
+ let velocity = applyPmoveFriction({
457
+ velocity: state.velocity,
458
+ frametime,
459
+ onGround,
460
+ groundIsSlick: settings.groundIsSlick,
461
+ onLadder,
462
+ waterlevel: state.waterlevel,
463
+ pmFriction: settings.pmFriction,
464
+ pmStopSpeed: settings.pmStopSpeed,
465
+ pmWaterFriction: settings.pmWaterFriction
466
+ });
467
+ const { viewangles, forward, right } = clampViewAngles({
468
+ pmFlags: state.pmFlags,
469
+ cmdAngles: cmd.angles,
470
+ deltaAngles: state.deltaAngles ?? ZERO_VEC32
471
+ });
472
+ const wish = state.waterlevel > WaterLevel.None ? buildWaterWish({ forward, right, cmd, maxSpeed: settings.pmWaterSpeed }) : buildAirGroundWish({ forward, right, cmd, maxSpeed: settings.pmMaxSpeed });
473
+ if (state.waterlevel > WaterLevel.None) {
474
+ velocity = applyPmoveAccelerate({
475
+ velocity,
476
+ wishdir: wish.wishdir,
477
+ wishspeed: wish.wishspeed,
478
+ accel: settings.pmWaterAccelerate,
479
+ frametime
480
+ });
481
+ } else if (onGround || onLadder) {
482
+ const maxSpeed = hasPmFlag(state.pmFlags, PmFlag.Ducked) ? settings.pmDuckSpeed : settings.pmMaxSpeed;
483
+ const clampedWish = wish.wishspeed > maxSpeed ? {
484
+ wishdir: wish.wishdir,
485
+ wishspeed: maxSpeed
486
+ } : wish;
487
+ velocity = applyPmoveAccelerate({
488
+ velocity,
489
+ wishdir: clampedWish.wishdir,
490
+ wishspeed: clampedWish.wishspeed,
491
+ accel: settings.pmAccelerate,
492
+ frametime
493
+ });
494
+ } else {
495
+ velocity = applyPmoveAirAccelerate({
496
+ velocity,
497
+ wishdir: wish.wishdir,
498
+ wishspeed: wish.wishspeed,
499
+ accel: settings.pmAirAccelerate,
500
+ frametime
501
+ });
502
+ velocity = { ...velocity, z: velocity.z - state.gravity * frametime };
503
+ }
504
+ const originDelta = scaleVec3(velocity, frametime);
505
+ const origin = addVec3(state.origin, originDelta);
506
+ return {
507
+ ...state,
508
+ origin,
509
+ velocity,
510
+ viewangles
511
+ };
512
+ }
513
+ var ClientPrediction = class {
514
+ constructor(settings = {}) {
515
+ this.baseFrame = {
516
+ frame: 0,
517
+ timeMs: 0,
518
+ state: defaultPredictionState()
519
+ };
520
+ this.commands = [];
521
+ this.predicted = defaultPredictionState();
522
+ this.settings = { ...DEFAULTS, ...settings };
523
+ this.predicted = this.baseFrame.state ?? defaultPredictionState();
524
+ }
525
+ setAuthoritative(frame) {
526
+ const normalized = normalizeState(frame.state);
527
+ this.baseFrame = { ...frame, state: normalized };
528
+ this.commands = this.commands.filter((cmd) => (cmd.serverFrame ?? Number.MAX_SAFE_INTEGER) > frame.frame);
529
+ return this.recompute();
530
+ }
531
+ enqueueCommand(cmd) {
532
+ this.commands.push(cmd);
533
+ return this.recompute();
534
+ }
535
+ getPredictedState() {
536
+ return this.predicted;
537
+ }
538
+ recompute() {
539
+ let state = normalizeState(this.baseFrame.state);
540
+ for (const cmd of this.commands) {
541
+ state = simulateCommand(state, cmd, this.settings);
542
+ }
543
+ this.predicted = state;
544
+ return state;
545
+ }
546
+ };
547
+ var DEFAULT_SETTINGS = {
548
+ runPitch: 2e-3,
549
+ runRoll: 5e-3,
550
+ bobUp: 5e-3,
551
+ bobPitch: 2e-3,
552
+ bobRoll: 2e-3,
553
+ maxBobHeight: 6,
554
+ maxBobAngle: 1.2
555
+ };
556
+ function clampViewOffset(offset) {
557
+ return {
558
+ x: Math.max(-14, Math.min(14, offset.x)),
559
+ y: Math.max(-14, Math.min(14, offset.y)),
560
+ z: Math.max(-22, Math.min(30, offset.z))
561
+ };
562
+ }
563
+ function computeBobMove(xyspeed, onGround, frameTimeMs) {
564
+ if (!onGround) return 0;
565
+ if (xyspeed > 210) return frameTimeMs / 400;
566
+ if (xyspeed > 100) return frameTimeMs / 800;
567
+ return frameTimeMs / 1600;
568
+ }
569
+ function computeBobValues(previousBobTime, xyspeed, pmFlags, onGround, frameTimeMs) {
570
+ if (xyspeed < 5) {
571
+ return { bobTime: 0, bobCycle: 0, bobCycleRun: 0, bobFracSin: 0 };
572
+ }
573
+ const bobMove = computeBobMove(xyspeed, onGround, frameTimeMs);
574
+ const bobTimeRun = previousBobTime + bobMove;
575
+ const crouched = hasPmFlag(pmFlags, PmFlag.Ducked) && onGround;
576
+ const bobTime = crouched ? bobTimeRun * 4 : bobTimeRun;
577
+ return {
578
+ bobTime: bobTimeRun,
579
+ bobCycle: Math.floor(bobTime),
580
+ bobCycleRun: Math.floor(bobTimeRun),
581
+ bobFracSin: Math.abs(Math.sin(bobTime * Math.PI))
582
+ };
583
+ }
584
+ var ViewEffects = class {
585
+ constructor(settings = {}) {
586
+ this.bobTime = 0;
587
+ this.bobCycle = 0;
588
+ this.bobCycleRun = 0;
589
+ this.bobFracSin = 0;
590
+ this.settings = { ...DEFAULT_SETTINGS, ...settings };
591
+ }
592
+ addKick(kick) {
593
+ if (kick.durationMs <= 0) return;
594
+ this.kick = { ...kick, remainingMs: kick.durationMs };
595
+ }
596
+ get last() {
597
+ return this.lastSample;
598
+ }
599
+ sample(state, frameTimeMs) {
600
+ const { forward, right } = angleVectors(
601
+ clampViewAngles({ pmFlags: state.pmFlags, cmdAngles: state.viewangles, deltaAngles: state.deltaAngles ?? ZERO_VEC3 }).viewangles
602
+ );
603
+ const xyspeed = Math.sqrt(state.velocity.x * state.velocity.x + state.velocity.y * state.velocity.y);
604
+ const onGround = hasPmFlag(state.pmFlags, PmFlag.OnGround);
605
+ const bobValues = computeBobValues(this.bobTime, xyspeed, state.pmFlags, onGround, frameTimeMs);
606
+ this.bobTime = bobValues.bobTime;
607
+ this.bobCycle = bobValues.bobCycle;
608
+ this.bobCycleRun = bobValues.bobCycleRun;
609
+ this.bobFracSin = bobValues.bobFracSin;
610
+ let pitchTilt = dotVec3(state.velocity, forward) * this.settings.runPitch;
611
+ let rollTilt = dotVec3(state.velocity, right) * this.settings.runRoll;
612
+ let pitchDelta = this.bobFracSin * this.settings.bobPitch * xyspeed;
613
+ let rollDelta = this.bobFracSin * this.settings.bobRoll * xyspeed;
614
+ if (hasPmFlag(state.pmFlags, PmFlag.Ducked) && onGround) {
615
+ pitchDelta *= 6;
616
+ rollDelta *= 6;
617
+ }
618
+ pitchTilt += Math.min(pitchDelta, this.settings.maxBobAngle);
619
+ rollDelta = Math.min(rollDelta, this.settings.maxBobAngle);
620
+ if (this.bobCycle & 1) rollDelta = -rollDelta;
621
+ rollTilt += rollDelta;
622
+ const bobHeight = Math.min(this.bobFracSin * xyspeed * this.settings.bobUp, this.settings.maxBobHeight);
623
+ let kickPitch = 0;
624
+ let kickRoll = 0;
625
+ if (this.kick && this.kick.remainingMs > 0) {
626
+ const ratio = Math.max(0, Math.min(1, this.kick.remainingMs / this.kick.durationMs));
627
+ kickPitch += ratio * this.kick.pitch;
628
+ kickRoll += ratio * this.kick.roll;
629
+ this.kick.remainingMs = Math.max(0, this.kick.remainingMs - frameTimeMs);
630
+ if (this.kick.remainingMs === 0) this.kick = void 0;
631
+ }
632
+ const angles = { x: pitchTilt + kickPitch, y: 0, z: rollTilt + kickRoll };
633
+ const offset = { x: 0, y: 0, z: bobHeight };
634
+ const sample = {
635
+ angles,
636
+ offset: clampViewOffset(offset),
637
+ bobCycle: this.bobCycle,
638
+ bobCycleRun: this.bobCycleRun,
639
+ bobFracSin: this.bobFracSin,
640
+ xyspeed
641
+ };
642
+ this.lastSample = sample;
643
+ return sample;
644
+ }
645
+ };
646
+ function normalizeCommand(command) {
647
+ return command.trim().toLowerCase();
648
+ }
649
+ var InputAction = /* @__PURE__ */ ((InputAction2) => {
650
+ InputAction2["Forward"] = "+forward";
651
+ InputAction2["Back"] = "+back";
652
+ InputAction2["MoveLeft"] = "+moveleft";
653
+ InputAction2["MoveRight"] = "+moveright";
654
+ InputAction2["MoveUp"] = "+moveup";
655
+ InputAction2["MoveDown"] = "+movedown";
656
+ InputAction2["Jump"] = "+jump";
657
+ InputAction2["Crouch"] = "+crouch";
658
+ InputAction2["Attack"] = "+attack";
659
+ InputAction2["Use"] = "+use";
660
+ InputAction2["Holster"] = "+holster";
661
+ InputAction2["TurnLeft"] = "+left";
662
+ InputAction2["TurnRight"] = "+right";
663
+ InputAction2["LookUp"] = "+lookup";
664
+ InputAction2["LookDown"] = "+lookdown";
665
+ InputAction2["SpeedModifier"] = "+speed";
666
+ InputAction2["Zoom"] = "+zoom";
667
+ return InputAction2;
668
+ })(InputAction || {});
669
+ var BUTTON_ACTIONS = {
670
+ [
671
+ "+attack"
672
+ /* Attack */
673
+ ]: PlayerButton.Attack,
674
+ [
675
+ "+use"
676
+ /* Use */
677
+ ]: PlayerButton.Use,
678
+ [
679
+ "+holster"
680
+ /* Holster */
681
+ ]: PlayerButton.Holster,
682
+ [
683
+ "+jump"
684
+ /* Jump */
685
+ ]: PlayerButton.Jump,
686
+ [
687
+ "+crouch"
688
+ /* Crouch */
689
+ ]: PlayerButton.Crouch
690
+ };
691
+ var ACTION_LOOKUP = new Map(
692
+ Object.values(InputAction).map((action) => [normalizeCommand(action), action])
693
+ );
28
694
  function createClient(imports) {
695
+ const prediction = new ClientPrediction();
696
+ const view = new ViewEffects();
29
697
  let latestFrame;
698
+ let lastRendered;
699
+ let lastView;
30
700
  return {
31
701
  init(initial) {
32
702
  latestFrame = initial;
703
+ if (initial?.state) {
704
+ prediction.setAuthoritative(initial);
705
+ }
33
706
  void imports.engine.trace({ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
34
707
  },
35
- predict(next) {
36
- const { origin, velocity } = next;
37
- return {
38
- origin: {
39
- x: origin.x + velocity.x,
40
- y: origin.y + velocity.y,
41
- z: origin.z + velocity.z
42
- },
43
- velocity
44
- };
708
+ predict(command) {
709
+ return prediction.enqueueCommand(command);
45
710
  },
46
711
  render(sample) {
47
- latestFrame = sample.latest ?? latestFrame;
712
+ if (sample.latest?.state) {
713
+ prediction.setAuthoritative(sample.latest);
714
+ latestFrame = sample.latest;
715
+ }
716
+ if (sample.previous?.state && sample.latest?.state) {
717
+ lastRendered = interpolatePredictionState(sample.previous.state, sample.latest.state, sample.alpha);
718
+ } else {
719
+ lastRendered = sample.latest?.state ?? sample.previous?.state ?? prediction.getPredictedState();
720
+ }
721
+ const frameTimeMs = sample.latest && sample.previous ? Math.max(0, sample.latest.timeMs - sample.previous.timeMs) : 0;
722
+ lastView = view.sample(lastRendered, frameTimeMs);
723
+ void imports;
48
724
  void sample;
49
725
  },
50
726
  shutdown() {
51
727
  latestFrame = void 0;
728
+ lastRendered = void 0;
729
+ },
730
+ get prediction() {
731
+ return prediction;
732
+ },
733
+ get lastRendered() {
734
+ return lastRendered;
735
+ },
736
+ get view() {
737
+ return view;
738
+ },
739
+ get lastView() {
740
+ return lastView;
52
741
  }
53
742
  };
54
743
  }
@@ -181,71 +870,72 @@ var EngineHost = class {
181
870
  return this.loop.isRunning();
182
871
  }
183
872
  };
184
- var DEG_TO_RAD = Math.PI / 180;
185
- var DEG2RAD_FACTOR = Math.PI / 180;
186
- var RAD2DEG_FACTOR = 180 / Math.PI;
187
- var CONTENTS_SOLID = 1 << 0;
188
- var CONTENTS_WINDOW = 1 << 1;
189
- var CONTENTS_AUX = 1 << 2;
190
- var CONTENTS_LAVA = 1 << 3;
191
- var CONTENTS_SLIME = 1 << 4;
192
- var CONTENTS_WATER = 1 << 5;
193
- var CONTENTS_MIST = 1 << 6;
194
- var CONTENTS_NO_WATERJUMP = 1 << 13;
195
- var CONTENTS_PROJECTILECLIP = 1 << 14;
196
- var CONTENTS_AREAPORTAL = 1 << 15;
197
- var CONTENTS_PLAYERCLIP = 1 << 16;
198
- var CONTENTS_MONSTERCLIP = 1 << 17;
199
- var CONTENTS_CURRENT_0 = 1 << 18;
200
- var CONTENTS_CURRENT_90 = 1 << 19;
201
- var CONTENTS_CURRENT_180 = 1 << 20;
202
- var CONTENTS_CURRENT_270 = 1 << 21;
203
- var CONTENTS_CURRENT_UP = 1 << 22;
204
- var CONTENTS_CURRENT_DOWN = 1 << 23;
205
- var CONTENTS_ORIGIN = 1 << 24;
206
- var CONTENTS_MONSTER = 1 << 25;
207
- var CONTENTS_DEADMONSTER = 1 << 26;
208
- var CONTENTS_DETAIL = 1 << 27;
209
- var CONTENTS_TRANSLUCENT = 1 << 28;
210
- var CONTENTS_LADDER = 1 << 29;
211
- var CONTENTS_PLAYER = 1 << 30;
212
- var CONTENTS_PROJECTILE = 1 << 31;
213
- var SURF_LIGHT = 1 << 0;
214
- var SURF_SLICK = 1 << 1;
215
- var SURF_SKY = 1 << 2;
216
- var SURF_WARP = 1 << 3;
217
- var SURF_TRANS33 = 1 << 4;
218
- var SURF_TRANS66 = 1 << 5;
219
- var SURF_FLOWING = 1 << 6;
220
- var SURF_NODRAW = 1 << 7;
221
- var SURF_ALPHATEST = 1 << 25;
222
- var SURF_N64_UV = 1 << 28;
223
- var SURF_N64_SCROLL_X = 1 << 29;
224
- var SURF_N64_SCROLL_Y = 1 << 30;
225
- var SURF_N64_SCROLL_FLIP = 1 << 31;
226
- var MASK_SOLID = CONTENTS_SOLID | CONTENTS_WINDOW;
227
- var MASK_PLAYERSOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_PLAYER;
228
- var MASK_DEADSOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW;
229
- var MASK_MONSTERSOLID = CONTENTS_SOLID | CONTENTS_MONSTERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_PLAYER;
230
- var MASK_WATER = CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME;
231
- var MASK_OPAQUE = CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA;
232
- var MASK_SHOT = CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_PLAYER | CONTENTS_WINDOW | CONTENTS_DEADMONSTER;
233
- var MASK_CURRENT = CONTENTS_CURRENT_0 | CONTENTS_CURRENT_90 | CONTENTS_CURRENT_180 | CONTENTS_CURRENT_270 | CONTENTS_CURRENT_UP | CONTENTS_CURRENT_DOWN;
234
- var MASK_BLOCK_SIGHT = CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_MONSTER | CONTENTS_PLAYER;
235
- var MASK_NAV_SOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW;
236
- var MASK_LADDER_NAV_SOLID = CONTENTS_SOLID | CONTENTS_WINDOW;
237
- var MASK_WALK_NAV_SOLID = CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTERCLIP;
238
- var MASK_PROJECTILE = MASK_SHOT | CONTENTS_PROJECTILECLIP;
239
- var MAX_CLIENTS = 256;
240
- var MAX_LIGHTSTYLES = 256;
241
- var MAX_MODELS = 8192;
242
- var MAX_SOUNDS = 2048;
243
- var MAX_IMAGES = 512;
244
- var MAX_ITEMS = 256;
245
- var MAX_GENERAL = MAX_CLIENTS * 2;
246
- var MAX_SHADOW_LIGHTS = 256;
247
- var MAX_WHEEL_ITEMS = 32;
248
- var ConfigStringIndex = ((ConfigStringIndex22) => {
873
+ var DEG_TO_RAD2 = Math.PI / 180;
874
+ var DEG2RAD_FACTOR2 = Math.PI / 180;
875
+ var RAD2DEG_FACTOR2 = 180 / Math.PI;
876
+ var CONTENTS_SOLID2 = 1 << 0;
877
+ var CONTENTS_WINDOW2 = 1 << 1;
878
+ var CONTENTS_AUX2 = 1 << 2;
879
+ var CONTENTS_LAVA2 = 1 << 3;
880
+ var CONTENTS_SLIME2 = 1 << 4;
881
+ var CONTENTS_WATER2 = 1 << 5;
882
+ var CONTENTS_MIST2 = 1 << 6;
883
+ var CONTENTS_NO_WATERJUMP2 = 1 << 13;
884
+ var CONTENTS_PROJECTILECLIP2 = 1 << 14;
885
+ var CONTENTS_AREAPORTAL2 = 1 << 15;
886
+ var CONTENTS_PLAYERCLIP2 = 1 << 16;
887
+ var CONTENTS_MONSTERCLIP2 = 1 << 17;
888
+ var CONTENTS_CURRENT_02 = 1 << 18;
889
+ var CONTENTS_CURRENT_902 = 1 << 19;
890
+ var CONTENTS_CURRENT_1802 = 1 << 20;
891
+ var CONTENTS_CURRENT_2702 = 1 << 21;
892
+ var CONTENTS_CURRENT_UP2 = 1 << 22;
893
+ var CONTENTS_CURRENT_DOWN2 = 1 << 23;
894
+ var CONTENTS_ORIGIN2 = 1 << 24;
895
+ var CONTENTS_MONSTER2 = 1 << 25;
896
+ var CONTENTS_DEADMONSTER2 = 1 << 26;
897
+ var CONTENTS_DETAIL2 = 1 << 27;
898
+ var CONTENTS_TRANSLUCENT2 = 1 << 28;
899
+ var CONTENTS_LADDER2 = 1 << 29;
900
+ var CONTENTS_PLAYER2 = 1 << 30;
901
+ var CONTENTS_PROJECTILE2 = 1 << 31;
902
+ var SURF_LIGHT2 = 1 << 0;
903
+ var SURF_SLICK2 = 1 << 1;
904
+ var SURF_SKY2 = 1 << 2;
905
+ var SURF_WARP2 = 1 << 3;
906
+ var SURF_TRANS332 = 1 << 4;
907
+ var SURF_TRANS662 = 1 << 5;
908
+ var SURF_FLOWING2 = 1 << 6;
909
+ var SURF_NODRAW2 = 1 << 7;
910
+ var SURF_ALPHATEST2 = 1 << 25;
911
+ var SURF_N64_UV2 = 1 << 28;
912
+ var SURF_N64_SCROLL_X2 = 1 << 29;
913
+ var SURF_N64_SCROLL_Y2 = 1 << 30;
914
+ var SURF_N64_SCROLL_FLIP2 = 1 << 31;
915
+ var MASK_SOLID2 = CONTENTS_SOLID2 | CONTENTS_WINDOW2;
916
+ var MASK_PLAYERSOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2;
917
+ var MASK_DEADSOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2;
918
+ var MASK_MONSTERSOLID2 = CONTENTS_SOLID2 | CONTENTS_MONSTERCLIP2 | CONTENTS_WINDOW2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2;
919
+ var MASK_WATER2 = CONTENTS_WATER2 | CONTENTS_LAVA2 | CONTENTS_SLIME2;
920
+ var MASK_OPAQUE2 = CONTENTS_SOLID2 | CONTENTS_SLIME2 | CONTENTS_LAVA2;
921
+ var MASK_SHOT2 = CONTENTS_SOLID2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2 | CONTENTS_WINDOW2 | CONTENTS_DEADMONSTER2;
922
+ var MASK_CURRENT2 = CONTENTS_CURRENT_02 | CONTENTS_CURRENT_902 | CONTENTS_CURRENT_1802 | CONTENTS_CURRENT_2702 | CONTENTS_CURRENT_UP2 | CONTENTS_CURRENT_DOWN2;
923
+ var MASK_BLOCK_SIGHT2 = CONTENTS_SOLID2 | CONTENTS_LAVA2 | CONTENTS_SLIME2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2;
924
+ var MASK_NAV_SOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2;
925
+ var MASK_LADDER_NAV_SOLID2 = CONTENTS_SOLID2 | CONTENTS_WINDOW2;
926
+ var MASK_WALK_NAV_SOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2 | CONTENTS_MONSTERCLIP2;
927
+ var MASK_PROJECTILE2 = MASK_SHOT2 | CONTENTS_PROJECTILECLIP2;
928
+ var MAX_CHECKCOUNT2 = Number.MAX_SAFE_INTEGER - 1;
929
+ var MAX_CLIENTS2 = 256;
930
+ var MAX_LIGHTSTYLES2 = 256;
931
+ var MAX_MODELS2 = 8192;
932
+ var MAX_SOUNDS2 = 2048;
933
+ var MAX_IMAGES2 = 512;
934
+ var MAX_ITEMS2 = 256;
935
+ var MAX_GENERAL2 = MAX_CLIENTS2 * 2;
936
+ var MAX_SHADOW_LIGHTS2 = 256;
937
+ var MAX_WHEEL_ITEMS2 = 32;
938
+ var ConfigStringIndex2 = ((ConfigStringIndex22) => {
249
939
  ConfigStringIndex22[ConfigStringIndex22["Name"] = 0] = "Name";
250
940
  ConfigStringIndex22[ConfigStringIndex22["CdTrack"] = 1] = "CdTrack";
251
941
  ConfigStringIndex22[ConfigStringIndex22["Sky"] = 2] = "Sky";
@@ -256,23 +946,23 @@ var ConfigStringIndex = ((ConfigStringIndex22) => {
256
946
  ConfigStringIndex22[ConfigStringIndex22["MaxClients"] = 60] = "MaxClients";
257
947
  ConfigStringIndex22[ConfigStringIndex22["MapChecksum"] = 61] = "MapChecksum";
258
948
  ConfigStringIndex22[ConfigStringIndex22["Models"] = 62] = "Models";
259
- ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS] = "Sounds";
260
- ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS] = "Images";
261
- ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES] = "Lights";
262
- ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES] = "ShadowLights";
263
- ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS] = "Items";
264
- ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS] = "PlayerSkins";
265
- ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS] = "General";
266
- ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL] = "WheelWeapons";
267
- ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS] = "WheelAmmo";
268
- ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS] = "WheelPowerups";
269
- ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS] = "CdLoopCount";
949
+ ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS2] = "Sounds";
950
+ ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS2] = "Images";
951
+ ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES2] = "Lights";
952
+ ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES2] = "ShadowLights";
953
+ ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS2] = "Items";
954
+ ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS2] = "PlayerSkins";
955
+ ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS2] = "General";
956
+ ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL2] = "WheelWeapons";
957
+ ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS2] = "WheelAmmo";
958
+ ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS2] = "WheelPowerups";
959
+ ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS2] = "CdLoopCount";
270
960
  ConfigStringIndex22[ConfigStringIndex22["GameStyle"] = ConfigStringIndex22.CdLoopCount + 1] = "GameStyle";
271
961
  ConfigStringIndex22[ConfigStringIndex22["MaxConfigStrings"] = ConfigStringIndex22.GameStyle + 1] = "MaxConfigStrings";
272
962
  return ConfigStringIndex22;
273
- })(ConfigStringIndex || {});
274
- var MAX_CONFIGSTRINGS = ConfigStringIndex.MaxConfigStrings;
275
- var WATERJUMP_CLEAR = 8 | 16 | 32 | 1024;
963
+ })(ConfigStringIndex2 || {});
964
+ var MAX_CONFIGSTRINGS2 = ConfigStringIndex2.MaxConfigStrings;
965
+ var WATERJUMP_CLEAR2 = 8 | 16 | 32 | 1024;
276
966
  var EngineRuntime = class {
277
967
  constructor(engine, host) {
278
968
  this.engine = engine;
@@ -311,102 +1001,357 @@ function createCrcTable() {
311
1001
  for (let j = 0; j < 8; j += 1) {
312
1002
  crc = (crc & 1) !== 0 ? 3988292384 ^ crc >>> 1 : crc >>> 1;
313
1003
  }
314
- table[i] = crc >>> 0;
1004
+ table[i] = crc >>> 0;
1005
+ }
1006
+ return table;
1007
+ }
1008
+ var CRC_TABLE = createCrcTable();
1009
+ var RERELEASE_KNOWN_PAKS = Object.freeze([
1010
+ // Base campaign
1011
+ { name: "pak0.pak", checksum: 2378051181, description: "Base game assets" },
1012
+ { name: "pak0.pak@baseq2", checksum: 2378051181, description: "Base game assets (baseq2)" },
1013
+ // Mission packs bundled with the rerelease
1014
+ { name: "pak0.pak@rogue", checksum: 3373211245, description: "Ground Zero (rogue) mission pack" },
1015
+ { name: "pak0.pak@xatrix", checksum: 1358269824, description: "The Reckoning (xatrix) mission pack" }
1016
+ ]);
1017
+ var HEADER_SIZE2 = 17 * 4;
1018
+ var FLOAT_BYTES = 4;
1019
+ var STRIDE = 7 * FLOAT_BYTES;
1020
+ var BSP_VERTEX_LAYOUT = [
1021
+ // Position
1022
+ { index: 0, size: 3, type: 5126, stride: STRIDE, offset: 0 },
1023
+ // Diffuse UV
1024
+ { index: 1, size: 2, type: 5126, stride: STRIDE, offset: 3 * FLOAT_BYTES },
1025
+ // Lightmap UV
1026
+ { index: 2, size: 2, type: 5126, stride: STRIDE, offset: 5 * FLOAT_BYTES }
1027
+ ];
1028
+ var SKYBOX_POSITIONS = new Float32Array([
1029
+ // Front
1030
+ -1,
1031
+ -1,
1032
+ 1,
1033
+ 1,
1034
+ -1,
1035
+ 1,
1036
+ 1,
1037
+ 1,
1038
+ 1,
1039
+ -1,
1040
+ -1,
1041
+ 1,
1042
+ 1,
1043
+ 1,
1044
+ 1,
1045
+ -1,
1046
+ 1,
1047
+ 1,
1048
+ // Back
1049
+ -1,
1050
+ -1,
1051
+ -1,
1052
+ -1,
1053
+ 1,
1054
+ -1,
1055
+ 1,
1056
+ 1,
1057
+ -1,
1058
+ -1,
1059
+ -1,
1060
+ -1,
1061
+ 1,
1062
+ 1,
1063
+ -1,
1064
+ 1,
1065
+ -1,
1066
+ -1,
1067
+ // Left
1068
+ -1,
1069
+ -1,
1070
+ -1,
1071
+ -1,
1072
+ -1,
1073
+ 1,
1074
+ -1,
1075
+ 1,
1076
+ 1,
1077
+ -1,
1078
+ -1,
1079
+ -1,
1080
+ -1,
1081
+ 1,
1082
+ 1,
1083
+ -1,
1084
+ 1,
1085
+ -1,
1086
+ // Right
1087
+ 1,
1088
+ -1,
1089
+ -1,
1090
+ 1,
1091
+ 1,
1092
+ -1,
1093
+ 1,
1094
+ 1,
1095
+ 1,
1096
+ 1,
1097
+ -1,
1098
+ -1,
1099
+ 1,
1100
+ 1,
1101
+ 1,
1102
+ 1,
1103
+ -1,
1104
+ 1,
1105
+ // Top
1106
+ -1,
1107
+ 1,
1108
+ -1,
1109
+ -1,
1110
+ 1,
1111
+ 1,
1112
+ 1,
1113
+ 1,
1114
+ 1,
1115
+ -1,
1116
+ 1,
1117
+ -1,
1118
+ 1,
1119
+ 1,
1120
+ 1,
1121
+ 1,
1122
+ 1,
1123
+ -1,
1124
+ // Bottom
1125
+ -1,
1126
+ -1,
1127
+ -1,
1128
+ 1,
1129
+ -1,
1130
+ -1,
1131
+ 1,
1132
+ -1,
1133
+ 1,
1134
+ -1,
1135
+ -1,
1136
+ -1,
1137
+ 1,
1138
+ -1,
1139
+ 1,
1140
+ -1,
1141
+ -1,
1142
+ 1
1143
+ ]);
1144
+ function createEngine(imports) {
1145
+ return {
1146
+ init() {
1147
+ void imports.trace({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 });
1148
+ },
1149
+ shutdown() {
1150
+ },
1151
+ createMainLoop(callbacks, options) {
1152
+ return new FixedTimestepLoop(callbacks, options);
1153
+ }
1154
+ };
1155
+ }
1156
+
1157
+ // ../../packages/game/dist/esm/index.js
1158
+ var ZERO_VEC33 = { x: 0, y: 0, z: 0 };
1159
+ var DEG_TO_RAD3 = Math.PI / 180;
1160
+ var DEG2RAD_FACTOR3 = Math.PI / 180;
1161
+ var RAD2DEG_FACTOR3 = 180 / Math.PI;
1162
+ var STATE_SIZE = 624;
1163
+ var MIDDLE_WORD = 397;
1164
+ var MATRIX_A = 2567483615;
1165
+ var UPPER_MASK = 2147483648;
1166
+ var LOWER_MASK = 2147483647;
1167
+ var TWO_POW_32 = 4294967296;
1168
+ var MersenneTwister19937 = class {
1169
+ constructor(seed = 5489) {
1170
+ this.state = new Uint32Array(STATE_SIZE);
1171
+ this.index = STATE_SIZE;
1172
+ this.seed(seed);
1173
+ }
1174
+ seed(seed) {
1175
+ this.state[0] = seed >>> 0;
1176
+ for (let i = 1; i < STATE_SIZE; i++) {
1177
+ const prev = this.state[i - 1] ^ this.state[i - 1] >>> 30;
1178
+ const next = Math.imul(prev >>> 0, 1812433253) + i;
1179
+ this.state[i] = next >>> 0;
1180
+ }
1181
+ this.index = STATE_SIZE;
1182
+ }
1183
+ nextUint32() {
1184
+ if (this.index >= STATE_SIZE) {
1185
+ this.twist();
1186
+ }
1187
+ let y = this.state[this.index++];
1188
+ y ^= y >>> 11;
1189
+ y ^= y << 7 & 2636928640;
1190
+ y ^= y << 15 & 4022730752;
1191
+ y ^= y >>> 18;
1192
+ return y >>> 0;
1193
+ }
1194
+ twist() {
1195
+ for (let i = 0; i < STATE_SIZE; i++) {
1196
+ const y = this.state[i] & UPPER_MASK | this.state[(i + 1) % STATE_SIZE] & LOWER_MASK;
1197
+ let next = this.state[(i + MIDDLE_WORD) % STATE_SIZE] ^ y >>> 1;
1198
+ if ((y & 1) !== 0) {
1199
+ next ^= MATRIX_A;
1200
+ }
1201
+ this.state[i] = next >>> 0;
1202
+ }
1203
+ this.index = 0;
1204
+ }
1205
+ getState() {
1206
+ return {
1207
+ index: this.index,
1208
+ state: Array.from(this.state)
1209
+ };
1210
+ }
1211
+ setState(snapshot) {
1212
+ if (snapshot.state.length !== STATE_SIZE) {
1213
+ throw new Error(`Expected ${STATE_SIZE} MT state values, received ${snapshot.state.length}`);
1214
+ }
1215
+ this.index = snapshot.index;
1216
+ this.state = Uint32Array.from(snapshot.state, (value) => value >>> 0);
1217
+ }
1218
+ };
1219
+ var RandomGenerator = class {
1220
+ constructor(options = {}) {
1221
+ this.mt = new MersenneTwister19937(options.seed);
1222
+ }
1223
+ /** Uniform float in [0, 1). */
1224
+ frandom() {
1225
+ return this.mt.nextUint32() / TWO_POW_32;
1226
+ }
1227
+ /** Uniform float in [min, max). */
1228
+ frandomRange(minInclusive, maxExclusive) {
1229
+ return minInclusive + (maxExclusive - minInclusive) * this.frandom();
1230
+ }
1231
+ /** Uniform float in [0, max). */
1232
+ frandomMax(maxExclusive) {
1233
+ return this.frandomRange(0, maxExclusive);
1234
+ }
1235
+ /** Uniform float in [-1, 1). */
1236
+ crandom() {
1237
+ return this.frandomRange(-1, 1);
1238
+ }
1239
+ /** Uniform float in (-1, 1). */
1240
+ crandomOpen() {
1241
+ const epsilon = Number.EPSILON;
1242
+ return this.frandomRange(-1 + epsilon, 1);
1243
+ }
1244
+ /** Raw uint32 sample. */
1245
+ irandomUint32() {
1246
+ return this.mt.nextUint32();
1247
+ }
1248
+ /** Uniform integer in [min, max). */
1249
+ irandomRange(minInclusive, maxExclusive) {
1250
+ if (maxExclusive - minInclusive <= 1) {
1251
+ return minInclusive;
1252
+ }
1253
+ const span = maxExclusive - minInclusive;
1254
+ const limit = TWO_POW_32 - TWO_POW_32 % span;
1255
+ let sample;
1256
+ do {
1257
+ sample = this.mt.nextUint32();
1258
+ } while (sample >= limit);
1259
+ return minInclusive + sample % span;
1260
+ }
1261
+ /** Uniform integer in [0, max). */
1262
+ irandom(maxExclusive) {
1263
+ if (maxExclusive <= 0) {
1264
+ return 0;
1265
+ }
1266
+ return this.irandomRange(0, maxExclusive);
315
1267
  }
316
- return table;
317
- }
318
- var CRC_TABLE = createCrcTable();
319
- var HEADER_SIZE2 = 17 * 4;
320
- var FLOAT_BYTES = 4;
321
- var STRIDE = 7 * FLOAT_BYTES;
322
- var BSP_VERTEX_LAYOUT = [
323
- // Position
324
- { index: 0, size: 3, type: 5126, stride: STRIDE, offset: 0 },
325
- // Diffuse UV
326
- { index: 1, size: 2, type: 5126, stride: STRIDE, offset: 3 * FLOAT_BYTES },
327
- // Lightmap UV
328
- { index: 2, size: 2, type: 5126, stride: STRIDE, offset: 5 * FLOAT_BYTES }
329
- ];
330
- function createEngine(imports) {
331
- return {
332
- init() {
333
- void imports.trace({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 });
334
- },
335
- shutdown() {
336
- },
337
- createMainLoop(callbacks, options) {
338
- return new FixedTimestepLoop(callbacks, options);
1268
+ /** Uniform time in milliseconds [min, max). */
1269
+ randomTimeRange(minMs, maxMs) {
1270
+ if (maxMs <= minMs) {
1271
+ return minMs;
339
1272
  }
340
- };
1273
+ return this.irandomRange(minMs, maxMs);
1274
+ }
1275
+ /** Uniform time in milliseconds [0, max). */
1276
+ randomTime(maxMs) {
1277
+ return this.irandom(maxMs);
1278
+ }
1279
+ randomIndex(container) {
1280
+ return this.irandom(container.length);
1281
+ }
1282
+ getState() {
1283
+ return { mt: this.mt.getState() };
1284
+ }
1285
+ setState(snapshot) {
1286
+ this.mt.setState(snapshot.mt);
1287
+ }
1288
+ };
1289
+ function createRandomGenerator(options) {
1290
+ return new RandomGenerator(options);
341
1291
  }
342
-
343
- // ../../packages/game/dist/esm/index.js
344
- var ZERO_VEC3 = { x: 0, y: 0, z: 0 };
345
- var DEG_TO_RAD2 = Math.PI / 180;
346
- var DEG2RAD_FACTOR2 = Math.PI / 180;
347
- var RAD2DEG_FACTOR2 = 180 / Math.PI;
348
- var CONTENTS_SOLID2 = 1 << 0;
349
- var CONTENTS_WINDOW2 = 1 << 1;
350
- var CONTENTS_AUX2 = 1 << 2;
351
- var CONTENTS_LAVA2 = 1 << 3;
352
- var CONTENTS_SLIME2 = 1 << 4;
353
- var CONTENTS_WATER2 = 1 << 5;
354
- var CONTENTS_MIST2 = 1 << 6;
355
- var CONTENTS_NO_WATERJUMP2 = 1 << 13;
356
- var CONTENTS_PROJECTILECLIP2 = 1 << 14;
357
- var CONTENTS_AREAPORTAL2 = 1 << 15;
358
- var CONTENTS_PLAYERCLIP2 = 1 << 16;
359
- var CONTENTS_MONSTERCLIP2 = 1 << 17;
360
- var CONTENTS_CURRENT_02 = 1 << 18;
361
- var CONTENTS_CURRENT_902 = 1 << 19;
362
- var CONTENTS_CURRENT_1802 = 1 << 20;
363
- var CONTENTS_CURRENT_2702 = 1 << 21;
364
- var CONTENTS_CURRENT_UP2 = 1 << 22;
365
- var CONTENTS_CURRENT_DOWN2 = 1 << 23;
366
- var CONTENTS_ORIGIN2 = 1 << 24;
367
- var CONTENTS_MONSTER2 = 1 << 25;
368
- var CONTENTS_DEADMONSTER2 = 1 << 26;
369
- var CONTENTS_DETAIL2 = 1 << 27;
370
- var CONTENTS_TRANSLUCENT2 = 1 << 28;
371
- var CONTENTS_LADDER2 = 1 << 29;
372
- var CONTENTS_PLAYER2 = 1 << 30;
373
- var CONTENTS_PROJECTILE2 = 1 << 31;
374
- var SURF_LIGHT2 = 1 << 0;
375
- var SURF_SLICK2 = 1 << 1;
376
- var SURF_SKY2 = 1 << 2;
377
- var SURF_WARP2 = 1 << 3;
378
- var SURF_TRANS332 = 1 << 4;
379
- var SURF_TRANS662 = 1 << 5;
380
- var SURF_FLOWING2 = 1 << 6;
381
- var SURF_NODRAW2 = 1 << 7;
382
- var SURF_ALPHATEST2 = 1 << 25;
383
- var SURF_N64_UV2 = 1 << 28;
384
- var SURF_N64_SCROLL_X2 = 1 << 29;
385
- var SURF_N64_SCROLL_Y2 = 1 << 30;
386
- var SURF_N64_SCROLL_FLIP2 = 1 << 31;
387
- var MASK_SOLID2 = CONTENTS_SOLID2 | CONTENTS_WINDOW2;
388
- var MASK_PLAYERSOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2;
389
- var MASK_DEADSOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2;
390
- var MASK_MONSTERSOLID2 = CONTENTS_SOLID2 | CONTENTS_MONSTERCLIP2 | CONTENTS_WINDOW2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2;
391
- var MASK_WATER2 = CONTENTS_WATER2 | CONTENTS_LAVA2 | CONTENTS_SLIME2;
392
- var MASK_OPAQUE2 = CONTENTS_SOLID2 | CONTENTS_SLIME2 | CONTENTS_LAVA2;
393
- var MASK_SHOT2 = CONTENTS_SOLID2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2 | CONTENTS_WINDOW2 | CONTENTS_DEADMONSTER2;
394
- var MASK_CURRENT2 = CONTENTS_CURRENT_02 | CONTENTS_CURRENT_902 | CONTENTS_CURRENT_1802 | CONTENTS_CURRENT_2702 | CONTENTS_CURRENT_UP2 | CONTENTS_CURRENT_DOWN2;
395
- var MASK_BLOCK_SIGHT2 = CONTENTS_SOLID2 | CONTENTS_LAVA2 | CONTENTS_SLIME2 | CONTENTS_MONSTER2 | CONTENTS_PLAYER2;
396
- var MASK_NAV_SOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2;
397
- var MASK_LADDER_NAV_SOLID2 = CONTENTS_SOLID2 | CONTENTS_WINDOW2;
398
- var MASK_WALK_NAV_SOLID2 = CONTENTS_SOLID2 | CONTENTS_PLAYERCLIP2 | CONTENTS_WINDOW2 | CONTENTS_MONSTERCLIP2;
399
- var MASK_PROJECTILE2 = MASK_SHOT2 | CONTENTS_PROJECTILECLIP2;
400
- var MAX_CLIENTS2 = 256;
401
- var MAX_LIGHTSTYLES2 = 256;
402
- var MAX_MODELS2 = 8192;
403
- var MAX_SOUNDS2 = 2048;
404
- var MAX_IMAGES2 = 512;
405
- var MAX_ITEMS2 = 256;
406
- var MAX_GENERAL2 = MAX_CLIENTS2 * 2;
407
- var MAX_SHADOW_LIGHTS2 = 256;
408
- var MAX_WHEEL_ITEMS2 = 32;
409
- var ConfigStringIndex2 = ((ConfigStringIndex22) => {
1292
+ var CONTENTS_SOLID3 = 1 << 0;
1293
+ var CONTENTS_WINDOW3 = 1 << 1;
1294
+ var CONTENTS_AUX3 = 1 << 2;
1295
+ var CONTENTS_LAVA3 = 1 << 3;
1296
+ var CONTENTS_SLIME3 = 1 << 4;
1297
+ var CONTENTS_WATER3 = 1 << 5;
1298
+ var CONTENTS_MIST3 = 1 << 6;
1299
+ var CONTENTS_NO_WATERJUMP3 = 1 << 13;
1300
+ var CONTENTS_PROJECTILECLIP3 = 1 << 14;
1301
+ var CONTENTS_AREAPORTAL3 = 1 << 15;
1302
+ var CONTENTS_PLAYERCLIP3 = 1 << 16;
1303
+ var CONTENTS_MONSTERCLIP3 = 1 << 17;
1304
+ var CONTENTS_CURRENT_03 = 1 << 18;
1305
+ var CONTENTS_CURRENT_903 = 1 << 19;
1306
+ var CONTENTS_CURRENT_1803 = 1 << 20;
1307
+ var CONTENTS_CURRENT_2703 = 1 << 21;
1308
+ var CONTENTS_CURRENT_UP3 = 1 << 22;
1309
+ var CONTENTS_CURRENT_DOWN3 = 1 << 23;
1310
+ var CONTENTS_ORIGIN3 = 1 << 24;
1311
+ var CONTENTS_MONSTER3 = 1 << 25;
1312
+ var CONTENTS_DEADMONSTER3 = 1 << 26;
1313
+ var CONTENTS_DETAIL3 = 1 << 27;
1314
+ var CONTENTS_TRANSLUCENT3 = 1 << 28;
1315
+ var CONTENTS_LADDER3 = 1 << 29;
1316
+ var CONTENTS_PLAYER3 = 1 << 30;
1317
+ var CONTENTS_PROJECTILE3 = 1 << 31;
1318
+ var SURF_LIGHT3 = 1 << 0;
1319
+ var SURF_SLICK3 = 1 << 1;
1320
+ var SURF_SKY3 = 1 << 2;
1321
+ var SURF_WARP3 = 1 << 3;
1322
+ var SURF_TRANS333 = 1 << 4;
1323
+ var SURF_TRANS663 = 1 << 5;
1324
+ var SURF_FLOWING3 = 1 << 6;
1325
+ var SURF_NODRAW3 = 1 << 7;
1326
+ var SURF_ALPHATEST3 = 1 << 25;
1327
+ var SURF_N64_UV3 = 1 << 28;
1328
+ var SURF_N64_SCROLL_X3 = 1 << 29;
1329
+ var SURF_N64_SCROLL_Y3 = 1 << 30;
1330
+ var SURF_N64_SCROLL_FLIP3 = 1 << 31;
1331
+ var MASK_SOLID3 = CONTENTS_SOLID3 | CONTENTS_WINDOW3;
1332
+ var MASK_PLAYERSOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3;
1333
+ var MASK_DEADSOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3;
1334
+ var MASK_MONSTERSOLID3 = CONTENTS_SOLID3 | CONTENTS_MONSTERCLIP3 | CONTENTS_WINDOW3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3;
1335
+ var MASK_WATER3 = CONTENTS_WATER3 | CONTENTS_LAVA3 | CONTENTS_SLIME3;
1336
+ var MASK_OPAQUE3 = CONTENTS_SOLID3 | CONTENTS_SLIME3 | CONTENTS_LAVA3;
1337
+ var MASK_SHOT3 = CONTENTS_SOLID3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3 | CONTENTS_WINDOW3 | CONTENTS_DEADMONSTER3;
1338
+ var MASK_CURRENT3 = CONTENTS_CURRENT_03 | CONTENTS_CURRENT_903 | CONTENTS_CURRENT_1803 | CONTENTS_CURRENT_2703 | CONTENTS_CURRENT_UP3 | CONTENTS_CURRENT_DOWN3;
1339
+ var MASK_BLOCK_SIGHT3 = CONTENTS_SOLID3 | CONTENTS_LAVA3 | CONTENTS_SLIME3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3;
1340
+ var MASK_NAV_SOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3;
1341
+ var MASK_LADDER_NAV_SOLID3 = CONTENTS_SOLID3 | CONTENTS_WINDOW3;
1342
+ var MASK_WALK_NAV_SOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3 | CONTENTS_MONSTERCLIP3;
1343
+ var MASK_PROJECTILE3 = MASK_SHOT3 | CONTENTS_PROJECTILECLIP3;
1344
+ var MAX_CHECKCOUNT3 = Number.MAX_SAFE_INTEGER - 1;
1345
+ var MAX_CLIENTS3 = 256;
1346
+ var MAX_LIGHTSTYLES3 = 256;
1347
+ var MAX_MODELS3 = 8192;
1348
+ var MAX_SOUNDS3 = 2048;
1349
+ var MAX_IMAGES3 = 512;
1350
+ var MAX_ITEMS3 = 256;
1351
+ var MAX_GENERAL3 = MAX_CLIENTS3 * 2;
1352
+ var MAX_SHADOW_LIGHTS3 = 256;
1353
+ var MAX_WHEEL_ITEMS3 = 32;
1354
+ var ConfigStringIndex3 = ((ConfigStringIndex22) => {
410
1355
  ConfigStringIndex22[ConfigStringIndex22["Name"] = 0] = "Name";
411
1356
  ConfigStringIndex22[ConfigStringIndex22["CdTrack"] = 1] = "CdTrack";
412
1357
  ConfigStringIndex22[ConfigStringIndex22["Sky"] = 2] = "Sky";
@@ -417,27 +1362,28 @@ var ConfigStringIndex2 = ((ConfigStringIndex22) => {
417
1362
  ConfigStringIndex22[ConfigStringIndex22["MaxClients"] = 60] = "MaxClients";
418
1363
  ConfigStringIndex22[ConfigStringIndex22["MapChecksum"] = 61] = "MapChecksum";
419
1364
  ConfigStringIndex22[ConfigStringIndex22["Models"] = 62] = "Models";
420
- ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS2] = "Sounds";
421
- ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS2] = "Images";
422
- ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES2] = "Lights";
423
- ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES2] = "ShadowLights";
424
- ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS2] = "Items";
425
- ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS2] = "PlayerSkins";
426
- ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS2] = "General";
427
- ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL2] = "WheelWeapons";
428
- ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS2] = "WheelAmmo";
429
- ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS2] = "WheelPowerups";
430
- ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS2] = "CdLoopCount";
1365
+ ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS3] = "Sounds";
1366
+ ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS3] = "Images";
1367
+ ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES3] = "Lights";
1368
+ ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES3] = "ShadowLights";
1369
+ ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS3] = "Items";
1370
+ ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS3] = "PlayerSkins";
1371
+ ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS3] = "General";
1372
+ ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL3] = "WheelWeapons";
1373
+ ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS3] = "WheelAmmo";
1374
+ ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS3] = "WheelPowerups";
1375
+ ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS3] = "CdLoopCount";
431
1376
  ConfigStringIndex22[ConfigStringIndex22["GameStyle"] = ConfigStringIndex22.CdLoopCount + 1] = "GameStyle";
432
1377
  ConfigStringIndex22[ConfigStringIndex22["MaxConfigStrings"] = ConfigStringIndex22.GameStyle + 1] = "MaxConfigStrings";
433
1378
  return ConfigStringIndex22;
434
- })(ConfigStringIndex2 || {});
435
- var MAX_CONFIGSTRINGS2 = ConfigStringIndex2.MaxConfigStrings;
436
- var WATERJUMP_CLEAR2 = 8 | 16 | 32 | 1024;
437
- var ZERO = { ...ZERO_VEC3 };
1379
+ })(ConfigStringIndex3 || {});
1380
+ var MAX_CONFIGSTRINGS3 = ConfigStringIndex3.MaxConfigStrings;
1381
+ var WATERJUMP_CLEAR3 = 8 | 16 | 32 | 1024;
1382
+ var ZERO = { ...ZERO_VEC33 };
438
1383
  function copyVec3() {
439
1384
  return { ...ZERO };
440
1385
  }
1386
+ var DEFAULT_MONSTER_INFO = Object.freeze({ aiflags: 0 });
441
1387
  var Entity = class {
442
1388
  constructor(index) {
443
1389
  this.inUse = false;
@@ -446,17 +1392,20 @@ var Entity = class {
446
1392
  this.linkNext = null;
447
1393
  this.classname = "";
448
1394
  this.spawnflags = 0;
1395
+ this.inventory = {};
449
1396
  this.origin = copyVec3();
450
1397
  this.old_origin = copyVec3();
451
1398
  this.velocity = copyVec3();
452
1399
  this.avelocity = copyVec3();
453
1400
  this.angles = copyVec3();
1401
+ this.viewheight = 0;
454
1402
  this.mins = copyVec3();
455
1403
  this.maxs = copyVec3();
456
1404
  this.size = copyVec3();
457
1405
  this.mass = 0;
458
1406
  this.gravity = 1;
459
1407
  this.movetype = 0;
1408
+ this.movedir = copyVec3();
460
1409
  this.modelindex = 0;
461
1410
  this.frame = 0;
462
1411
  this.skin = 0;
@@ -466,20 +1415,35 @@ var Entity = class {
466
1415
  this.max_health = 0;
467
1416
  this.takedamage = false;
468
1417
  this.dmg = 0;
1418
+ this.speed = 0;
469
1419
  this.deadflag = 0;
1420
+ this.count = 0;
1421
+ this.wait = 0;
1422
+ this.delay = 0;
1423
+ this.timestamp = 0;
1424
+ this.sounds = 0;
1425
+ this.noise_index = 0;
1426
+ this.fly_sound_debounce_time = 0;
470
1427
  this.enemy = null;
471
1428
  this.movetarget = null;
1429
+ this.target_ent = null;
472
1430
  this.goalentity = null;
473
1431
  this.ideal_yaw = 0;
474
1432
  this.yaw_speed = 0;
1433
+ this.search_time = 0;
1434
+ this.attack_finished_time = 0;
1435
+ this.pain_finished_time = 0;
1436
+ this.trail_time = 0;
475
1437
  this.groundentity = null;
476
1438
  this.groundentity_linkcount = 0;
477
1439
  this.waterlevel = 0;
478
1440
  this.watertype = 0;
479
1441
  this.nextthink = 0;
1442
+ this.activator = null;
480
1443
  this.solid = 0;
481
1444
  this.flags = 0;
482
1445
  this.svflags = 0;
1446
+ this.monsterinfo = { ...DEFAULT_MONSTER_INFO };
483
1447
  this.index = index;
484
1448
  }
485
1449
  reset() {
@@ -491,19 +1455,26 @@ var Entity = class {
491
1455
  this.spawnflags = 0;
492
1456
  this.target = void 0;
493
1457
  this.targetname = void 0;
1458
+ this.killtarget = void 0;
494
1459
  this.team = void 0;
495
1460
  this.message = void 0;
1461
+ this.pathtarget = void 0;
1462
+ this.model = void 0;
1463
+ this.item = void 0;
1464
+ this.inventory = {};
496
1465
  this.origin = copyVec3();
497
1466
  this.old_origin = copyVec3();
498
1467
  this.velocity = copyVec3();
499
1468
  this.avelocity = copyVec3();
500
1469
  this.angles = copyVec3();
1470
+ this.viewheight = 0;
501
1471
  this.mins = copyVec3();
502
1472
  this.maxs = copyVec3();
503
1473
  this.size = copyVec3();
504
1474
  this.mass = 0;
505
1475
  this.gravity = 1;
506
1476
  this.movetype = 0;
1477
+ this.movedir = copyVec3();
507
1478
  this.modelindex = 0;
508
1479
  this.frame = 0;
509
1480
  this.skin = 0;
@@ -513,12 +1484,25 @@ var Entity = class {
513
1484
  this.max_health = 0;
514
1485
  this.takedamage = false;
515
1486
  this.dmg = 0;
1487
+ this.speed = 0;
516
1488
  this.deadflag = 0;
1489
+ this.count = 0;
1490
+ this.wait = 0;
1491
+ this.delay = 0;
1492
+ this.timestamp = 0;
1493
+ this.sounds = 0;
1494
+ this.noise_index = 0;
1495
+ this.fly_sound_debounce_time = 0;
517
1496
  this.enemy = null;
518
1497
  this.movetarget = null;
1498
+ this.target_ent = null;
519
1499
  this.goalentity = null;
520
1500
  this.ideal_yaw = 0;
521
1501
  this.yaw_speed = 0;
1502
+ this.search_time = 0;
1503
+ this.attack_finished_time = 0;
1504
+ this.pain_finished_time = 0;
1505
+ this.trail_time = 0;
522
1506
  this.groundentity = null;
523
1507
  this.groundentity_linkcount = 0;
524
1508
  this.waterlevel = 0;
@@ -529,11 +1513,80 @@ var Entity = class {
529
1513
  this.use = void 0;
530
1514
  this.pain = void 0;
531
1515
  this.die = void 0;
1516
+ this.activator = null;
532
1517
  this.solid = 0;
533
1518
  this.flags = 0;
534
1519
  this.svflags = 0;
1520
+ this.monsterinfo = { ...DEFAULT_MONSTER_INFO };
535
1521
  }
536
1522
  };
1523
+ var ENTITY_FIELD_METADATA = [
1524
+ { name: "classname", type: "string", save: true },
1525
+ { name: "spawnflags", type: "int", save: true },
1526
+ { name: "target", type: "string", save: true },
1527
+ { name: "targetname", type: "string", save: true },
1528
+ { name: "killtarget", type: "string", save: true },
1529
+ { name: "team", type: "string", save: true },
1530
+ { name: "message", type: "string", save: true },
1531
+ { name: "pathtarget", type: "string", save: true },
1532
+ { name: "model", type: "string", save: true },
1533
+ { name: "item", type: "string", save: true },
1534
+ { name: "inventory", type: "inventory", save: true },
1535
+ { name: "origin", type: "vec3", save: true },
1536
+ { name: "old_origin", type: "vec3", save: true },
1537
+ { name: "velocity", type: "vec3", save: true },
1538
+ { name: "avelocity", type: "vec3", save: true },
1539
+ { name: "angles", type: "vec3", save: true },
1540
+ { name: "viewheight", type: "int", save: true },
1541
+ { name: "mins", type: "vec3", save: true },
1542
+ { name: "maxs", type: "vec3", save: true },
1543
+ { name: "size", type: "vec3", save: true },
1544
+ { name: "mass", type: "int", save: true },
1545
+ { name: "gravity", type: "float", save: true },
1546
+ { name: "movetype", type: "int", save: true },
1547
+ { name: "movedir", type: "vec3", save: true },
1548
+ { name: "modelindex", type: "int", save: true },
1549
+ { name: "frame", type: "int", save: true },
1550
+ { name: "skin", type: "int", save: true },
1551
+ { name: "effects", type: "int", save: true },
1552
+ { name: "renderfx", type: "int", save: true },
1553
+ { name: "health", type: "int", save: true },
1554
+ { name: "max_health", type: "int", save: true },
1555
+ { name: "takedamage", type: "boolean", save: true },
1556
+ { name: "dmg", type: "int", save: true },
1557
+ { name: "speed", type: "float", save: true },
1558
+ { name: "deadflag", type: "int", save: true },
1559
+ { name: "count", type: "int", save: true },
1560
+ { name: "wait", type: "float", save: true },
1561
+ { name: "delay", type: "float", save: true },
1562
+ { name: "timestamp", type: "float", save: true },
1563
+ { name: "sounds", type: "int", save: true },
1564
+ { name: "noise_index", type: "int", save: true },
1565
+ { name: "fly_sound_debounce_time", type: "float", save: true },
1566
+ { name: "enemy", type: "entity", save: true },
1567
+ { name: "movetarget", type: "entity", save: true },
1568
+ { name: "target_ent", type: "entity", save: true },
1569
+ { name: "goalentity", type: "entity", save: true },
1570
+ { name: "ideal_yaw", type: "float", save: true },
1571
+ { name: "yaw_speed", type: "float", save: true },
1572
+ { name: "search_time", type: "float", save: true },
1573
+ { name: "attack_finished_time", type: "float", save: true },
1574
+ { name: "pain_finished_time", type: "float", save: true },
1575
+ { name: "trail_time", type: "float", save: true },
1576
+ { name: "groundentity", type: "entity", save: true },
1577
+ { name: "groundentity_linkcount", type: "int", save: true },
1578
+ { name: "waterlevel", type: "int", save: true },
1579
+ { name: "watertype", type: "int", save: true },
1580
+ { name: "nextthink", type: "float", save: true },
1581
+ { name: "solid", type: "int", save: true },
1582
+ { name: "flags", type: "int", save: true },
1583
+ { name: "svflags", type: "int", save: true },
1584
+ { name: "think", type: "callback", save: false },
1585
+ { name: "touch", type: "callback", save: false },
1586
+ { name: "use", type: "callback", save: false },
1587
+ { name: "pain", type: "callback", save: false },
1588
+ { name: "die", type: "callback", save: false }
1589
+ ];
537
1590
  var MAX_EDICTS = 2048;
538
1591
  var WORLD_INDEX = 0;
539
1592
  var EntityPool = class {
@@ -605,6 +1658,17 @@ var EntityPool = class {
605
1658
  entity.freePending = true;
606
1659
  this.pendingFree.push(entity.index);
607
1660
  }
1661
+ freeImmediate(entity) {
1662
+ if (entity.index === WORLD_INDEX) {
1663
+ throw new Error("Cannot free world entity");
1664
+ }
1665
+ if (!entity.inUse) {
1666
+ return;
1667
+ }
1668
+ this.unlink(entity);
1669
+ entity.reset();
1670
+ this.freeList.push(entity.index);
1671
+ }
608
1672
  flushFreeList() {
609
1673
  if (this.pendingFree.length === 0) {
610
1674
  return;
@@ -616,6 +1680,69 @@ var EntityPool = class {
616
1680
  }
617
1681
  this.pendingFree.length = 0;
618
1682
  }
1683
+ createSnapshot() {
1684
+ const activeOrder = Array.from(this, (entity) => entity.index);
1685
+ return {
1686
+ capacity: this.entities.length,
1687
+ activeOrder,
1688
+ freeList: [...this.freeList],
1689
+ pendingFree: [...this.pendingFree]
1690
+ };
1691
+ }
1692
+ restore(snapshot) {
1693
+ if (snapshot.capacity !== this.entities.length) {
1694
+ throw new Error(`Snapshot capacity ${snapshot.capacity} does not match pool capacity ${this.entities.length}`);
1695
+ }
1696
+ const seen = /* @__PURE__ */ new Set();
1697
+ const noteIndex = (index, label) => {
1698
+ if (index < 0 || index >= this.entities.length) {
1699
+ throw new Error(`Invalid entity index ${index} in ${label}`);
1700
+ }
1701
+ if (seen.has(index)) {
1702
+ throw new Error(`Duplicate entity index ${index} in snapshot`);
1703
+ }
1704
+ seen.add(index);
1705
+ };
1706
+ for (const index of snapshot.activeOrder) {
1707
+ noteIndex(index, "activeOrder");
1708
+ }
1709
+ for (const index of snapshot.freeList) {
1710
+ noteIndex(index, "freeList");
1711
+ }
1712
+ for (const index of snapshot.pendingFree) {
1713
+ noteIndex(index, "pendingFree");
1714
+ }
1715
+ this.activeHead = null;
1716
+ this.freeList.length = 0;
1717
+ this.pendingFree.length = 0;
1718
+ for (const entity of this.entities) {
1719
+ entity.reset();
1720
+ }
1721
+ for (let i = snapshot.activeOrder.length - 1; i >= 0; i -= 1) {
1722
+ const entity = this.entities[snapshot.activeOrder[i]];
1723
+ entity.inUse = true;
1724
+ this.link(entity);
1725
+ }
1726
+ for (const index of snapshot.pendingFree) {
1727
+ const entity = this.entities[index];
1728
+ entity.inUse = false;
1729
+ entity.freePending = true;
1730
+ entity.linkNext = null;
1731
+ entity.linkPrevious = null;
1732
+ this.pendingFree.push(index);
1733
+ }
1734
+ for (const index of snapshot.freeList) {
1735
+ const entity = this.entities[index];
1736
+ entity.inUse = false;
1737
+ entity.freePending = false;
1738
+ entity.linkNext = null;
1739
+ entity.linkPrevious = null;
1740
+ this.freeList.push(index);
1741
+ }
1742
+ if (!snapshot.activeOrder.includes(WORLD_INDEX)) {
1743
+ throw new Error("Snapshot must include the world entity as active");
1744
+ }
1745
+ }
619
1746
  link(entity) {
620
1747
  entity.linkNext = this.activeHead;
621
1748
  if (this.activeHead) {
@@ -657,6 +1784,19 @@ var ThinkScheduler = class {
657
1784
  }
658
1785
  }
659
1786
  }
1787
+ snapshot() {
1788
+ return this.queue.map(({ time, entity }) => ({ time, entityIndex: entity.index }));
1789
+ }
1790
+ restore(entries, resolver) {
1791
+ this.queue.length = 0;
1792
+ for (const entry of entries) {
1793
+ const entity = resolver(entry.entityIndex);
1794
+ if (!entity) {
1795
+ continue;
1796
+ }
1797
+ this.schedule(entity, entry.time);
1798
+ }
1799
+ }
660
1800
  runDueThinks(currentTimeSeconds) {
661
1801
  while (this.queue.length > 0) {
662
1802
  const next = this.queue[0];
@@ -695,8 +1835,41 @@ function computeBounds(entity) {
695
1835
  function boundsIntersect(a, b) {
696
1836
  return !(a.min.x > b.max.x || a.max.x < b.min.x || a.min.y > b.max.y || a.max.y < b.min.y || a.min.z > b.max.z || a.max.z < b.min.z);
697
1837
  }
1838
+ var SERIALIZABLE_FIELDS = ENTITY_FIELD_METADATA.filter(
1839
+ (field) => field.save
1840
+ );
1841
+ var DESCRIPTORS = new Map(SERIALIZABLE_FIELDS.map((descriptor) => [descriptor.name, descriptor]));
1842
+ function serializeVec3(vec) {
1843
+ return [vec.x, vec.y, vec.z];
1844
+ }
1845
+ function deserializeVec3(value) {
1846
+ const vec = value;
1847
+ if (!Array.isArray(vec) || vec.length !== 3) {
1848
+ throw new Error("Invalid vec3 serialization");
1849
+ }
1850
+ const [x, y, z] = vec;
1851
+ return { x, y, z };
1852
+ }
1853
+ function assignField(entity, name, value) {
1854
+ entity[name] = value;
1855
+ }
1856
+ function serializeInventory(inventory) {
1857
+ return { ...inventory };
1858
+ }
1859
+ function deserializeInventory(value) {
1860
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
1861
+ throw new Error("Invalid inventory serialization");
1862
+ }
1863
+ const parsed = {};
1864
+ for (const [key, entry] of Object.entries(value)) {
1865
+ parsed[key] = Number(entry);
1866
+ }
1867
+ return parsed;
1868
+ }
698
1869
  var EntitySystem = class {
699
1870
  constructor(maxEntities) {
1871
+ this.targetNameIndex = /* @__PURE__ */ new Map();
1872
+ this.random = createRandomGenerator();
700
1873
  this.currentTimeSeconds = 0;
701
1874
  this.pool = new EntityPool(maxEntities);
702
1875
  this.thinkScheduler = new ThinkScheduler();
@@ -715,24 +1888,179 @@ var EntitySystem = class {
715
1888
  callback(entity);
716
1889
  }
717
1890
  }
718
- spawn() {
719
- return this.pool.spawn();
1891
+ spawn() {
1892
+ return this.pool.spawn();
1893
+ }
1894
+ free(entity) {
1895
+ this.unregisterTarget(entity);
1896
+ this.thinkScheduler.cancel(entity);
1897
+ this.pool.deferFree(entity);
1898
+ }
1899
+ freeImmediate(entity) {
1900
+ this.unregisterTarget(entity);
1901
+ this.thinkScheduler.cancel(entity);
1902
+ this.pool.freeImmediate(entity);
1903
+ }
1904
+ scheduleThink(entity, nextThinkSeconds) {
1905
+ this.thinkScheduler.schedule(entity, nextThinkSeconds);
1906
+ }
1907
+ beginFrame(timeSeconds) {
1908
+ this.currentTimeSeconds = timeSeconds;
1909
+ }
1910
+ finalizeSpawn(entity) {
1911
+ if (!entity.inUse || entity.freePending) {
1912
+ return;
1913
+ }
1914
+ this.registerTarget(entity);
1915
+ }
1916
+ findByClassname(classname) {
1917
+ const matches = [];
1918
+ for (const entity of this.pool) {
1919
+ if (entity.classname === classname && entity.inUse && !entity.freePending) {
1920
+ matches.push(entity);
1921
+ }
1922
+ }
1923
+ return matches;
1924
+ }
1925
+ findByTargetName(targetname) {
1926
+ const matches = this.targetNameIndex.get(targetname);
1927
+ if (!matches) {
1928
+ return [];
1929
+ }
1930
+ return Array.from(matches).filter((entity) => entity.inUse && !entity.freePending);
720
1931
  }
721
- free(entity) {
722
- this.thinkScheduler.cancel(entity);
723
- this.pool.deferFree(entity);
1932
+ pickTarget(targetname) {
1933
+ if (!targetname) {
1934
+ return null;
1935
+ }
1936
+ const matches = this.findByTargetName(targetname);
1937
+ if (matches.length === 0) {
1938
+ return null;
1939
+ }
1940
+ const choice = this.random.randomIndex(matches);
1941
+ return matches[choice] ?? null;
724
1942
  }
725
- scheduleThink(entity, nextThinkSeconds) {
726
- this.thinkScheduler.schedule(entity, nextThinkSeconds);
1943
+ killBox(entity) {
1944
+ const targetBounds = computeBounds(entity);
1945
+ for (const other of this.pool) {
1946
+ if (other === entity || other === this.pool.world) {
1947
+ continue;
1948
+ }
1949
+ if (!other.inUse || other.freePending || other.solid === 0) {
1950
+ continue;
1951
+ }
1952
+ if (other.svflags & 2) {
1953
+ continue;
1954
+ }
1955
+ if (!boundsIntersect(targetBounds, computeBounds(other))) {
1956
+ continue;
1957
+ }
1958
+ other.health = 0;
1959
+ other.deadflag = 2;
1960
+ this.free(other);
1961
+ }
727
1962
  }
728
- beginFrame(timeSeconds) {
729
- this.currentTimeSeconds = timeSeconds;
1963
+ useTargets(entity, activator = null) {
1964
+ if (entity.delay > 0) {
1965
+ const delayed = this.spawn();
1966
+ delayed.classname = "DelayedUse";
1967
+ delayed.target = entity.target;
1968
+ delayed.killtarget = entity.killtarget;
1969
+ delayed.message = entity.message;
1970
+ delayed.think = (self) => {
1971
+ this.useTargetsImmediate(self, activator ?? entity);
1972
+ this.free(self);
1973
+ };
1974
+ this.scheduleThink(delayed, this.currentTimeSeconds + entity.delay);
1975
+ return;
1976
+ }
1977
+ this.useTargetsImmediate(entity, activator ?? entity);
730
1978
  }
731
1979
  runFrame() {
732
1980
  this.thinkScheduler.runDueThinks(this.currentTimeSeconds);
733
1981
  this.runTouches();
734
1982
  this.pool.flushFreeList();
735
1983
  }
1984
+ createSnapshot() {
1985
+ const entities = [];
1986
+ for (const entity of this.pool) {
1987
+ const fields = {};
1988
+ for (const descriptor of SERIALIZABLE_FIELDS) {
1989
+ const value = entity[descriptor.name];
1990
+ switch (descriptor.type) {
1991
+ case "vec3":
1992
+ fields[descriptor.name] = serializeVec3(value);
1993
+ break;
1994
+ case "entity":
1995
+ fields[descriptor.name] = value?.index ?? null;
1996
+ break;
1997
+ case "inventory":
1998
+ fields[descriptor.name] = serializeInventory(value);
1999
+ break;
2000
+ default:
2001
+ fields[descriptor.name] = value ?? null;
2002
+ break;
2003
+ }
2004
+ }
2005
+ entities.push({
2006
+ index: entity.index,
2007
+ fields
2008
+ });
2009
+ }
2010
+ return {
2011
+ timeSeconds: this.currentTimeSeconds,
2012
+ pool: this.pool.createSnapshot(),
2013
+ entities,
2014
+ thinks: this.thinkScheduler.snapshot()
2015
+ };
2016
+ }
2017
+ restore(snapshot) {
2018
+ this.currentTimeSeconds = snapshot.timeSeconds;
2019
+ this.pool.restore(snapshot.pool);
2020
+ const indexToEntity = /* @__PURE__ */ new Map();
2021
+ for (const entity of this.pool) {
2022
+ indexToEntity.set(entity.index, entity);
2023
+ }
2024
+ const pendingEntityRefs = [];
2025
+ for (const serialized of snapshot.entities) {
2026
+ const entity = indexToEntity.get(serialized.index);
2027
+ if (!entity) {
2028
+ continue;
2029
+ }
2030
+ for (const [name, value] of Object.entries(serialized.fields)) {
2031
+ const descriptor = DESCRIPTORS.get(name);
2032
+ if (!descriptor || value === void 0) {
2033
+ continue;
2034
+ }
2035
+ switch (descriptor.type) {
2036
+ case "vec3":
2037
+ assignField(entity, name, deserializeVec3(value));
2038
+ break;
2039
+ case "entity":
2040
+ pendingEntityRefs.push({
2041
+ entity,
2042
+ name: descriptor.name,
2043
+ targetIndex: value
2044
+ });
2045
+ break;
2046
+ case "inventory":
2047
+ assignField(entity, name, deserializeInventory(value));
2048
+ break;
2049
+ case "boolean":
2050
+ assignField(entity, name, Boolean(value));
2051
+ break;
2052
+ default:
2053
+ assignField(entity, name, value);
2054
+ break;
2055
+ }
2056
+ }
2057
+ }
2058
+ for (const ref of pendingEntityRefs) {
2059
+ const target = ref.targetIndex === null ? null : indexToEntity.get(ref.targetIndex) ?? null;
2060
+ assignField(ref.entity, ref.name, target);
2061
+ }
2062
+ this.thinkScheduler.restore(snapshot.thinks, (index) => indexToEntity.get(index));
2063
+ }
736
2064
  runTouches() {
737
2065
  const world = this.pool.world;
738
2066
  const activeEntities = [];
@@ -740,7 +2068,7 @@ var EntitySystem = class {
740
2068
  if (entity === world) {
741
2069
  continue;
742
2070
  }
743
- if (!entity.inUse || entity.freePending) {
2071
+ if (!entity.inUse || entity.freePending || entity.solid === 0) {
744
2072
  continue;
745
2073
  }
746
2074
  activeEntities.push(entity);
@@ -769,7 +2097,97 @@ var EntitySystem = class {
769
2097
  }
770
2098
  }
771
2099
  }
2100
+ registerTarget(entity) {
2101
+ if (!entity.targetname) {
2102
+ return;
2103
+ }
2104
+ let bucket = this.targetNameIndex.get(entity.targetname);
2105
+ if (!bucket) {
2106
+ bucket = /* @__PURE__ */ new Set();
2107
+ this.targetNameIndex.set(entity.targetname, bucket);
2108
+ }
2109
+ bucket.add(entity);
2110
+ }
2111
+ unregisterTarget(entity) {
2112
+ if (!entity.targetname) {
2113
+ return;
2114
+ }
2115
+ const bucket = this.targetNameIndex.get(entity.targetname);
2116
+ if (!bucket) {
2117
+ return;
2118
+ }
2119
+ bucket.delete(entity);
2120
+ if (bucket.size === 0) {
2121
+ this.targetNameIndex.delete(entity.targetname);
2122
+ }
2123
+ }
2124
+ useTargetsImmediate(entity, activator) {
2125
+ if (entity.target) {
2126
+ for (const target of this.findByTargetName(entity.target)) {
2127
+ if (target === entity) {
2128
+ continue;
2129
+ }
2130
+ target.use?.(target, entity, activator);
2131
+ }
2132
+ }
2133
+ if (entity.killtarget) {
2134
+ for (const victim of this.findByTargetName(entity.killtarget)) {
2135
+ if (victim === entity) {
2136
+ continue;
2137
+ }
2138
+ this.free(victim);
2139
+ }
2140
+ }
2141
+ }
2142
+ };
2143
+ var FRAME_TIME_SECONDS = 1 / 40;
2144
+ var TRIGGER_SPAWNFLAGS = {
2145
+ Monster: 1 << 0,
2146
+ NotPlayer: 1 << 1,
2147
+ Triggered: 1 << 2,
2148
+ Toggle: 1 << 3,
2149
+ Latched: 1 << 4,
2150
+ Clip: 1 << 5
772
2151
  };
2152
+ var RELAY_SPAWNFLAGS = {
2153
+ NoSound: 1 << 0
2154
+ };
2155
+ var COUNTER_SPAWNFLAGS = {
2156
+ NoMessage: 1 << 0
2157
+ };
2158
+ var PUSH_SPAWNFLAGS = {
2159
+ Once: 1 << 0,
2160
+ Plus: 1 << 1,
2161
+ Silent: 1 << 2,
2162
+ StartOff: 1 << 3,
2163
+ Clip: 1 << 4
2164
+ };
2165
+ var HURT_SPAWNFLAGS = {
2166
+ StartOff: 1 << 0,
2167
+ Toggle: 1 << 1,
2168
+ Silent: 1 << 2,
2169
+ NoProtection: 1 << 3,
2170
+ Slow: 1 << 4,
2171
+ NoPlayers: 1 << 5,
2172
+ NoMonsters: 1 << 6,
2173
+ Clip: 1 << 7
2174
+ };
2175
+ var TELEPORT_SPAWNFLAGS = {
2176
+ StartOn: 1 << 3
2177
+ };
2178
+ var GRAVITY_SPAWNFLAGS = {
2179
+ Toggle: 1 << 0,
2180
+ StartOff: 1 << 1,
2181
+ Clip: 1 << 2
2182
+ };
2183
+ var MONSTERJUMP_SPAWNFLAGS = {
2184
+ Toggle: 1 << 0,
2185
+ StartOff: 1 << 1,
2186
+ Clip: 1 << 2
2187
+ };
2188
+ var FIELD_LOOKUP = new Map(
2189
+ ENTITY_FIELD_METADATA.map((field) => [field.name, field])
2190
+ );
773
2191
  var orderedStageNames = [
774
2192
  "prep",
775
2193
  "simulate",
@@ -902,8 +2320,391 @@ var LevelClock = class {
902
2320
  get current() {
903
2321
  return this.state;
904
2322
  }
2323
+ restore(state) {
2324
+ this.state = { ...state };
2325
+ }
905
2326
  };
906
- var ZERO_VEC32 = { x: 0, y: 0, z: 0 };
2327
+ var FL_NOVISIBLE = 1 << 24;
2328
+ var SPAWNFLAG_MONSTER_AMBUSH = 1 << 0;
2329
+ var SAVE_FORMAT_VERSION = 1;
2330
+ var MIN_SUPPORTED_VERSION = 1;
2331
+ function ensureObject(value, label) {
2332
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2333
+ throw new Error(`${label} must be an object`);
2334
+ }
2335
+ return value;
2336
+ }
2337
+ function ensureNumber(value, label) {
2338
+ if (typeof value !== "number" || !Number.isFinite(value)) {
2339
+ throw new Error(`${label} must be a finite number`);
2340
+ }
2341
+ return value;
2342
+ }
2343
+ function ensureNumberOrDefault(value, label, defaultValue) {
2344
+ if (value === void 0) {
2345
+ return defaultValue;
2346
+ }
2347
+ return ensureNumber(value, label);
2348
+ }
2349
+ function ensureString(value, label) {
2350
+ if (typeof value !== "string") {
2351
+ throw new Error(`${label} must be a string`);
2352
+ }
2353
+ return value;
2354
+ }
2355
+ function ensureNumberArray(value, label) {
2356
+ if (!Array.isArray(value)) {
2357
+ throw new Error(`${label} must be an array`);
2358
+ }
2359
+ for (const element of value) {
2360
+ ensureNumber(element, `${label} element`);
2361
+ }
2362
+ return value;
2363
+ }
2364
+ function parseLevelState(raw) {
2365
+ if (raw === void 0) {
2366
+ return { frameNumber: 0, timeSeconds: 0, previousTimeSeconds: 0, deltaSeconds: 0 };
2367
+ }
2368
+ const level = ensureObject(raw, "level");
2369
+ return {
2370
+ frameNumber: ensureNumberOrDefault(level.frameNumber, "level.frameNumber", 0),
2371
+ timeSeconds: ensureNumberOrDefault(level.timeSeconds, "level.timeSeconds", 0),
2372
+ previousTimeSeconds: ensureNumberOrDefault(level.previousTimeSeconds, "level.previousTimeSeconds", 0),
2373
+ deltaSeconds: ensureNumberOrDefault(level.deltaSeconds, "level.deltaSeconds", 0)
2374
+ };
2375
+ }
2376
+ function parseRngState(raw) {
2377
+ if (raw === void 0) {
2378
+ return new RandomGenerator().getState();
2379
+ }
2380
+ const rng = ensureObject(raw, "rng");
2381
+ const mt = ensureObject(rng.mt, "rng.mt");
2382
+ const state = ensureNumberArray(mt.state, "rng.mt.state");
2383
+ return {
2384
+ mt: {
2385
+ index: ensureNumber(mt.index, "rng.mt.index"),
2386
+ state
2387
+ }
2388
+ };
2389
+ }
2390
+ function parseThinkEntries(raw) {
2391
+ if (raw === void 0) {
2392
+ return [];
2393
+ }
2394
+ if (!Array.isArray(raw)) {
2395
+ throw new Error("thinks must be an array");
2396
+ }
2397
+ return raw.map((entry, idx) => {
2398
+ const think = ensureObject(entry, `thinks[${idx}]`);
2399
+ return {
2400
+ time: ensureNumber(think.time, `thinks[${idx}].time`),
2401
+ entityIndex: ensureNumber(think.entityIndex, `thinks[${idx}].entityIndex`)
2402
+ };
2403
+ });
2404
+ }
2405
+ function parseEntityFields(raw) {
2406
+ if (raw === void 0) {
2407
+ return {};
2408
+ }
2409
+ const fields = ensureObject(raw, "entity.fields");
2410
+ const parsed = {};
2411
+ for (const [name, value] of Object.entries(fields)) {
2412
+ if (value === null) {
2413
+ parsed[name] = null;
2414
+ continue;
2415
+ }
2416
+ switch (typeof value) {
2417
+ case "number":
2418
+ case "string":
2419
+ case "boolean":
2420
+ parsed[name] = value;
2421
+ break;
2422
+ default: {
2423
+ if (!Array.isArray(value)) {
2424
+ const object = ensureObject(value, name);
2425
+ const inventory = {};
2426
+ for (const [entryName, entryValue] of Object.entries(object)) {
2427
+ inventory[entryName] = ensureNumber(entryValue, `${name}.${entryName}`);
2428
+ }
2429
+ parsed[name] = inventory;
2430
+ break;
2431
+ }
2432
+ if (Array.isArray(value) && value.length === 3) {
2433
+ const [x, y, z] = value;
2434
+ parsed[name] = [
2435
+ ensureNumber(x, `${name}[0]`),
2436
+ ensureNumber(y, `${name}[1]`),
2437
+ ensureNumber(z, `${name}[2]`)
2438
+ ];
2439
+ break;
2440
+ }
2441
+ throw new Error(`Unsupported entity field value for ${name}`);
2442
+ }
2443
+ }
2444
+ }
2445
+ return parsed;
2446
+ }
2447
+ function parseEntities(raw) {
2448
+ if (!Array.isArray(raw)) {
2449
+ throw new Error("entities must be an array");
2450
+ }
2451
+ return raw.map((entry, idx) => {
2452
+ const entity = ensureObject(entry, `entities[${idx}]`);
2453
+ return {
2454
+ index: ensureNumber(entity.index, `entities[${idx}].index`),
2455
+ fields: parseEntityFields(entity.fields)
2456
+ };
2457
+ });
2458
+ }
2459
+ function parsePool(raw) {
2460
+ const pool = ensureObject(raw, "pool");
2461
+ return {
2462
+ capacity: ensureNumber(pool.capacity, "pool.capacity"),
2463
+ activeOrder: ensureNumberArray(pool.activeOrder, "pool.activeOrder"),
2464
+ freeList: ensureNumberArray(pool.freeList, "pool.freeList"),
2465
+ pendingFree: ensureNumberArray(pool.pendingFree, "pool.pendingFree")
2466
+ };
2467
+ }
2468
+ function parseEntitySnapshot(raw) {
2469
+ const snapshot = ensureObject(raw, "entities");
2470
+ return {
2471
+ timeSeconds: ensureNumber(snapshot.timeSeconds, "entities.timeSeconds"),
2472
+ pool: parsePool(snapshot.pool),
2473
+ entities: parseEntities(snapshot.entities),
2474
+ thinks: parseThinkEntries(snapshot.thinks)
2475
+ };
2476
+ }
2477
+ function parseCvars(raw) {
2478
+ if (raw === void 0) {
2479
+ return [];
2480
+ }
2481
+ if (!Array.isArray(raw)) {
2482
+ throw new Error("cvars must be an array");
2483
+ }
2484
+ return raw.map((entry, idx) => {
2485
+ const cvar = ensureObject(entry, `cvars[${idx}]`);
2486
+ return {
2487
+ name: ensureString(cvar.name, `cvars[${idx}].name`),
2488
+ value: ensureString(cvar.value, `cvars[${idx}].value`),
2489
+ flags: ensureNumber(cvar.flags, `cvars[${idx}].flags`)
2490
+ };
2491
+ });
2492
+ }
2493
+ function parseConfigstrings(raw) {
2494
+ if (raw === void 0) {
2495
+ return [];
2496
+ }
2497
+ if (!Array.isArray(raw)) {
2498
+ throw new Error("configstrings must be an array");
2499
+ }
2500
+ return raw.map((value, idx) => ensureString(value, `configstrings[${idx}]`));
2501
+ }
2502
+ function parseGameState(raw) {
2503
+ if (raw === void 0) {
2504
+ return {};
2505
+ }
2506
+ return ensureObject(raw, "gameState");
2507
+ }
2508
+ function parseSaveFile(serialized, options = {}) {
2509
+ const { allowNewerVersion = true } = options;
2510
+ const raw = typeof serialized === "string" ? JSON.parse(serialized) : serialized;
2511
+ const save = ensureObject(raw, "save");
2512
+ const versionValue = save.version ?? SAVE_FORMAT_VERSION;
2513
+ const version = ensureNumber(versionValue, "version");
2514
+ if (version < MIN_SUPPORTED_VERSION) {
2515
+ throw new Error(`Unsupported save version ${version}`);
2516
+ }
2517
+ if (version > SAVE_FORMAT_VERSION && !allowNewerVersion) {
2518
+ throw new Error(`Save version ${version} is newer than supported ${SAVE_FORMAT_VERSION}`);
2519
+ }
2520
+ return {
2521
+ version,
2522
+ timestamp: ensureNumber(save.timestamp, "timestamp"),
2523
+ map: ensureString(save.map, "map"),
2524
+ difficulty: ensureNumber(save.difficulty, "difficulty"),
2525
+ playtimeSeconds: ensureNumber(save.playtimeSeconds, "playtimeSeconds"),
2526
+ gameState: parseGameState(save.gameState),
2527
+ level: parseLevelState(save.level),
2528
+ rng: parseRngState(save.rng),
2529
+ entities: parseEntitySnapshot(save.entities),
2530
+ cvars: parseCvars(save.cvars),
2531
+ configstrings: parseConfigstrings(save.configstrings)
2532
+ };
2533
+ }
2534
+ var TEXT_ENCODER_CTOR = globalThis.TextEncoder;
2535
+ function cloneSave(save) {
2536
+ return parseSaveFile({ ...save }, { allowNewerVersion: true });
2537
+ }
2538
+ function estimateSizeBytes(save) {
2539
+ if (TEXT_ENCODER_CTOR) {
2540
+ const encoder = new TEXT_ENCODER_CTOR();
2541
+ return encoder.encode(JSON.stringify(save)).length;
2542
+ }
2543
+ return JSON.stringify(save).length;
2544
+ }
2545
+ var MemorySaveAdapter = class {
2546
+ constructor() {
2547
+ this.records = /* @__PURE__ */ new Map();
2548
+ }
2549
+ async init() {
2550
+ return Promise.resolve();
2551
+ }
2552
+ async put(record) {
2553
+ const copy = {
2554
+ id: record.id,
2555
+ metadata: { ...record.metadata },
2556
+ save: cloneSave(record.save)
2557
+ };
2558
+ this.records.set(record.id, copy);
2559
+ }
2560
+ async get(id) {
2561
+ const record = this.records.get(id);
2562
+ if (!record) {
2563
+ return null;
2564
+ }
2565
+ return {
2566
+ id: record.id,
2567
+ metadata: { ...record.metadata },
2568
+ save: cloneSave(record.save)
2569
+ };
2570
+ }
2571
+ async delete(id) {
2572
+ return this.records.delete(id);
2573
+ }
2574
+ async list() {
2575
+ return Array.from(this.records.values()).map((record) => ({
2576
+ id: record.id,
2577
+ metadata: { ...record.metadata },
2578
+ save: cloneSave(record.save)
2579
+ }));
2580
+ }
2581
+ };
2582
+ var IndexedDbSaveAdapter = class {
2583
+ constructor(indexedDB2, dbName, storeName) {
2584
+ this.indexedDB = indexedDB2;
2585
+ this.dbName = dbName;
2586
+ this.storeName = storeName;
2587
+ this.db = null;
2588
+ }
2589
+ async init() {
2590
+ if (this.db) {
2591
+ return;
2592
+ }
2593
+ this.db = await new Promise((resolve, reject) => {
2594
+ const request = this.indexedDB.open(this.dbName, 1);
2595
+ request.onupgradeneeded = () => {
2596
+ request.result.createObjectStore(this.storeName, { keyPath: "id" });
2597
+ };
2598
+ request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
2599
+ request.onsuccess = () => resolve(request.result);
2600
+ });
2601
+ }
2602
+ async runTransaction(mode, operation) {
2603
+ await this.init();
2604
+ const database = this.db;
2605
+ return new Promise((resolve, reject) => {
2606
+ const transaction = database.transaction(this.storeName, mode);
2607
+ const store = transaction.objectStore(this.storeName);
2608
+ const request = operation(store);
2609
+ request.onsuccess = () => resolve(request.result);
2610
+ request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
2611
+ });
2612
+ }
2613
+ async put(record) {
2614
+ await this.runTransaction("readwrite", (store) => store.put(record));
2615
+ }
2616
+ async get(id) {
2617
+ const record = await this.runTransaction("readonly", (store) => store.get(id));
2618
+ if (!record) {
2619
+ return null;
2620
+ }
2621
+ return {
2622
+ id: record.id,
2623
+ metadata: { ...record.metadata },
2624
+ save: cloneSave(record.save)
2625
+ };
2626
+ }
2627
+ async delete(id) {
2628
+ const existing = await this.get(id);
2629
+ if (!existing) {
2630
+ return false;
2631
+ }
2632
+ await this.runTransaction("readwrite", (store) => store.delete(id));
2633
+ return true;
2634
+ }
2635
+ async list() {
2636
+ const all = await this.runTransaction("readonly", (store) => store.getAll());
2637
+ return all.map((record) => ({
2638
+ id: record.id,
2639
+ metadata: { ...record.metadata },
2640
+ save: cloneSave(record.save)
2641
+ }));
2642
+ }
2643
+ };
2644
+ var _SaveStorage = class _SaveStorage2 {
2645
+ constructor(options = {}) {
2646
+ const { dbName = _SaveStorage2.DEFAULT_DB_NAME, storeName = _SaveStorage2.DEFAULT_STORE } = options;
2647
+ const indexedDBFactory = options.indexedDB ?? globalThis.indexedDB;
2648
+ if (indexedDBFactory) {
2649
+ this.adapter = new IndexedDbSaveAdapter(indexedDBFactory, dbName, storeName);
2650
+ } else {
2651
+ this.adapter = new MemorySaveAdapter();
2652
+ }
2653
+ }
2654
+ async save(slotId, save, options = {}) {
2655
+ const normalized = cloneSave(save);
2656
+ const metadata = {
2657
+ id: slotId,
2658
+ name: options.name ?? slotId,
2659
+ map: normalized.map,
2660
+ difficulty: normalized.difficulty,
2661
+ playtimeSeconds: normalized.playtimeSeconds,
2662
+ timestamp: normalized.timestamp,
2663
+ version: normalized.version,
2664
+ bytes: estimateSizeBytes(normalized)
2665
+ };
2666
+ await this.adapter.init();
2667
+ await this.adapter.put({ id: slotId, metadata, save: normalized });
2668
+ return metadata;
2669
+ }
2670
+ async load(slotId, options = {}) {
2671
+ await this.adapter.init();
2672
+ const record = await this.adapter.get(slotId);
2673
+ if (!record) {
2674
+ throw new Error(`Save slot ${slotId} not found`);
2675
+ }
2676
+ return parseSaveFile(record.save, options);
2677
+ }
2678
+ async delete(slotId) {
2679
+ await this.adapter.init();
2680
+ return this.adapter.delete(slotId);
2681
+ }
2682
+ async list() {
2683
+ await this.adapter.init();
2684
+ const records = await this.adapter.list();
2685
+ return records.map((record) => ({ ...record.metadata })).sort((a, b) => b.timestamp - a.timestamp || a.id.localeCompare(b.id));
2686
+ }
2687
+ async quickSave(save) {
2688
+ return this.save(_SaveStorage2.QUICK_SLOT, save, { name: "Quick Save" });
2689
+ }
2690
+ async quickLoad(options = {}) {
2691
+ return this.load(_SaveStorage2.QUICK_SLOT, options);
2692
+ }
2693
+ };
2694
+ _SaveStorage.DEFAULT_DB_NAME = "quake2ts-saves";
2695
+ _SaveStorage.DEFAULT_STORE = "saves";
2696
+ _SaveStorage.QUICK_SLOT = "quicksave";
2697
+ var AmmoType = /* @__PURE__ */ ((AmmoType2) => {
2698
+ AmmoType2[AmmoType2["Bullets"] = 0] = "Bullets";
2699
+ AmmoType2[AmmoType2["Shells"] = 1] = "Shells";
2700
+ AmmoType2[AmmoType2["Rockets"] = 2] = "Rockets";
2701
+ AmmoType2[AmmoType2["Grenades"] = 3] = "Grenades";
2702
+ AmmoType2[AmmoType2["Cells"] = 4] = "Cells";
2703
+ AmmoType2[AmmoType2["Slugs"] = 5] = "Slugs";
2704
+ return AmmoType2;
2705
+ })(AmmoType || {});
2706
+ var AMMO_TYPE_COUNT = Object.keys(AmmoType).length / 2;
2707
+ var ZERO_VEC322 = { x: 0, y: 0, z: 0 };
907
2708
  function createGame(engine, options) {
908
2709
  const gravity = options.gravity;
909
2710
  const levelClock = new LevelClock();
@@ -926,8 +2727,8 @@ function createGame(engine, options) {
926
2727
  };
927
2728
  entities.runFrame();
928
2729
  });
929
- let origin = { ...ZERO_VEC32 };
930
- let velocity = { ...ZERO_VEC32 };
2730
+ let origin = { ...ZERO_VEC322 };
2731
+ let velocity = { ...ZERO_VEC322 };
931
2732
  const snapshot = (frame) => ({
932
2733
  frame,
933
2734
  timeMs: frameLoop.time,
@@ -945,8 +2746,8 @@ function createGame(engine, options) {
945
2746
  const resetState = (startTimeMs) => {
946
2747
  frameLoop.reset(startTimeMs);
947
2748
  levelClock.start(startTimeMs);
948
- origin = { ...ZERO_VEC32 };
949
- velocity = { ...ZERO_VEC32 };
2749
+ origin = { ...ZERO_VEC322 };
2750
+ velocity = { ...ZERO_VEC322 };
950
2751
  entities.beginFrame(startTimeMs / 1e3);
951
2752
  entities.runFrame();
952
2753
  };
@@ -969,72 +2770,73 @@ function createGame(engine, options) {
969
2770
  }
970
2771
 
971
2772
  // ../../packages/shared/dist/esm/index.js
972
- var ZERO_VEC33 = { x: 0, y: 0, z: 0 };
973
- var DEG_TO_RAD3 = Math.PI / 180;
974
- var DEG2RAD_FACTOR3 = Math.PI / 180;
975
- var RAD2DEG_FACTOR3 = 180 / Math.PI;
976
- var CONTENTS_SOLID3 = 1 << 0;
977
- var CONTENTS_WINDOW3 = 1 << 1;
978
- var CONTENTS_AUX3 = 1 << 2;
979
- var CONTENTS_LAVA3 = 1 << 3;
980
- var CONTENTS_SLIME3 = 1 << 4;
981
- var CONTENTS_WATER3 = 1 << 5;
982
- var CONTENTS_MIST3 = 1 << 6;
983
- var CONTENTS_NO_WATERJUMP3 = 1 << 13;
984
- var CONTENTS_PROJECTILECLIP3 = 1 << 14;
985
- var CONTENTS_AREAPORTAL3 = 1 << 15;
986
- var CONTENTS_PLAYERCLIP3 = 1 << 16;
987
- var CONTENTS_MONSTERCLIP3 = 1 << 17;
988
- var CONTENTS_CURRENT_03 = 1 << 18;
989
- var CONTENTS_CURRENT_903 = 1 << 19;
990
- var CONTENTS_CURRENT_1803 = 1 << 20;
991
- var CONTENTS_CURRENT_2703 = 1 << 21;
992
- var CONTENTS_CURRENT_UP3 = 1 << 22;
993
- var CONTENTS_CURRENT_DOWN3 = 1 << 23;
994
- var CONTENTS_ORIGIN3 = 1 << 24;
995
- var CONTENTS_MONSTER3 = 1 << 25;
996
- var CONTENTS_DEADMONSTER3 = 1 << 26;
997
- var CONTENTS_DETAIL3 = 1 << 27;
998
- var CONTENTS_TRANSLUCENT3 = 1 << 28;
999
- var CONTENTS_LADDER3 = 1 << 29;
1000
- var CONTENTS_PLAYER3 = 1 << 30;
1001
- var CONTENTS_PROJECTILE3 = 1 << 31;
1002
- var SURF_LIGHT3 = 1 << 0;
1003
- var SURF_SLICK3 = 1 << 1;
1004
- var SURF_SKY3 = 1 << 2;
1005
- var SURF_WARP3 = 1 << 3;
1006
- var SURF_TRANS333 = 1 << 4;
1007
- var SURF_TRANS663 = 1 << 5;
1008
- var SURF_FLOWING3 = 1 << 6;
1009
- var SURF_NODRAW3 = 1 << 7;
1010
- var SURF_ALPHATEST3 = 1 << 25;
1011
- var SURF_N64_UV3 = 1 << 28;
1012
- var SURF_N64_SCROLL_X3 = 1 << 29;
1013
- var SURF_N64_SCROLL_Y3 = 1 << 30;
1014
- var SURF_N64_SCROLL_FLIP3 = 1 << 31;
1015
- var MASK_SOLID3 = CONTENTS_SOLID3 | CONTENTS_WINDOW3;
1016
- var MASK_PLAYERSOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3;
1017
- var MASK_DEADSOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3;
1018
- var MASK_MONSTERSOLID3 = CONTENTS_SOLID3 | CONTENTS_MONSTERCLIP3 | CONTENTS_WINDOW3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3;
1019
- var MASK_WATER3 = CONTENTS_WATER3 | CONTENTS_LAVA3 | CONTENTS_SLIME3;
1020
- var MASK_OPAQUE3 = CONTENTS_SOLID3 | CONTENTS_SLIME3 | CONTENTS_LAVA3;
1021
- var MASK_SHOT3 = CONTENTS_SOLID3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3 | CONTENTS_WINDOW3 | CONTENTS_DEADMONSTER3;
1022
- var MASK_CURRENT3 = CONTENTS_CURRENT_03 | CONTENTS_CURRENT_903 | CONTENTS_CURRENT_1803 | CONTENTS_CURRENT_2703 | CONTENTS_CURRENT_UP3 | CONTENTS_CURRENT_DOWN3;
1023
- var MASK_BLOCK_SIGHT3 = CONTENTS_SOLID3 | CONTENTS_LAVA3 | CONTENTS_SLIME3 | CONTENTS_MONSTER3 | CONTENTS_PLAYER3;
1024
- var MASK_NAV_SOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3;
1025
- var MASK_LADDER_NAV_SOLID3 = CONTENTS_SOLID3 | CONTENTS_WINDOW3;
1026
- var MASK_WALK_NAV_SOLID3 = CONTENTS_SOLID3 | CONTENTS_PLAYERCLIP3 | CONTENTS_WINDOW3 | CONTENTS_MONSTERCLIP3;
1027
- var MASK_PROJECTILE3 = MASK_SHOT3 | CONTENTS_PROJECTILECLIP3;
1028
- var MAX_CLIENTS3 = 256;
1029
- var MAX_LIGHTSTYLES3 = 256;
1030
- var MAX_MODELS3 = 8192;
1031
- var MAX_SOUNDS3 = 2048;
1032
- var MAX_IMAGES3 = 512;
1033
- var MAX_ITEMS3 = 256;
1034
- var MAX_GENERAL3 = MAX_CLIENTS3 * 2;
1035
- var MAX_SHADOW_LIGHTS3 = 256;
1036
- var MAX_WHEEL_ITEMS3 = 32;
1037
- var ConfigStringIndex3 = ((ConfigStringIndex22) => {
2773
+ var ZERO_VEC34 = { x: 0, y: 0, z: 0 };
2774
+ var DEG_TO_RAD4 = Math.PI / 180;
2775
+ var DEG2RAD_FACTOR4 = Math.PI / 180;
2776
+ var RAD2DEG_FACTOR4 = 180 / Math.PI;
2777
+ var CONTENTS_SOLID4 = 1 << 0;
2778
+ var CONTENTS_WINDOW4 = 1 << 1;
2779
+ var CONTENTS_AUX4 = 1 << 2;
2780
+ var CONTENTS_LAVA4 = 1 << 3;
2781
+ var CONTENTS_SLIME4 = 1 << 4;
2782
+ var CONTENTS_WATER4 = 1 << 5;
2783
+ var CONTENTS_MIST4 = 1 << 6;
2784
+ var CONTENTS_NO_WATERJUMP4 = 1 << 13;
2785
+ var CONTENTS_PROJECTILECLIP4 = 1 << 14;
2786
+ var CONTENTS_AREAPORTAL4 = 1 << 15;
2787
+ var CONTENTS_PLAYERCLIP4 = 1 << 16;
2788
+ var CONTENTS_MONSTERCLIP4 = 1 << 17;
2789
+ var CONTENTS_CURRENT_04 = 1 << 18;
2790
+ var CONTENTS_CURRENT_904 = 1 << 19;
2791
+ var CONTENTS_CURRENT_1804 = 1 << 20;
2792
+ var CONTENTS_CURRENT_2704 = 1 << 21;
2793
+ var CONTENTS_CURRENT_UP4 = 1 << 22;
2794
+ var CONTENTS_CURRENT_DOWN4 = 1 << 23;
2795
+ var CONTENTS_ORIGIN4 = 1 << 24;
2796
+ var CONTENTS_MONSTER4 = 1 << 25;
2797
+ var CONTENTS_DEADMONSTER4 = 1 << 26;
2798
+ var CONTENTS_DETAIL4 = 1 << 27;
2799
+ var CONTENTS_TRANSLUCENT4 = 1 << 28;
2800
+ var CONTENTS_LADDER4 = 1 << 29;
2801
+ var CONTENTS_PLAYER4 = 1 << 30;
2802
+ var CONTENTS_PROJECTILE4 = 1 << 31;
2803
+ var SURF_LIGHT4 = 1 << 0;
2804
+ var SURF_SLICK4 = 1 << 1;
2805
+ var SURF_SKY4 = 1 << 2;
2806
+ var SURF_WARP4 = 1 << 3;
2807
+ var SURF_TRANS334 = 1 << 4;
2808
+ var SURF_TRANS664 = 1 << 5;
2809
+ var SURF_FLOWING4 = 1 << 6;
2810
+ var SURF_NODRAW4 = 1 << 7;
2811
+ var SURF_ALPHATEST4 = 1 << 25;
2812
+ var SURF_N64_UV4 = 1 << 28;
2813
+ var SURF_N64_SCROLL_X4 = 1 << 29;
2814
+ var SURF_N64_SCROLL_Y4 = 1 << 30;
2815
+ var SURF_N64_SCROLL_FLIP4 = 1 << 31;
2816
+ var MASK_SOLID4 = CONTENTS_SOLID4 | CONTENTS_WINDOW4;
2817
+ var MASK_PLAYERSOLID4 = CONTENTS_SOLID4 | CONTENTS_PLAYERCLIP4 | CONTENTS_WINDOW4 | CONTENTS_MONSTER4 | CONTENTS_PLAYER4;
2818
+ var MASK_DEADSOLID4 = CONTENTS_SOLID4 | CONTENTS_PLAYERCLIP4 | CONTENTS_WINDOW4;
2819
+ var MASK_MONSTERSOLID4 = CONTENTS_SOLID4 | CONTENTS_MONSTERCLIP4 | CONTENTS_WINDOW4 | CONTENTS_MONSTER4 | CONTENTS_PLAYER4;
2820
+ var MASK_WATER4 = CONTENTS_WATER4 | CONTENTS_LAVA4 | CONTENTS_SLIME4;
2821
+ var MASK_OPAQUE4 = CONTENTS_SOLID4 | CONTENTS_SLIME4 | CONTENTS_LAVA4;
2822
+ var MASK_SHOT4 = CONTENTS_SOLID4 | CONTENTS_MONSTER4 | CONTENTS_PLAYER4 | CONTENTS_WINDOW4 | CONTENTS_DEADMONSTER4;
2823
+ var MASK_CURRENT4 = CONTENTS_CURRENT_04 | CONTENTS_CURRENT_904 | CONTENTS_CURRENT_1804 | CONTENTS_CURRENT_2704 | CONTENTS_CURRENT_UP4 | CONTENTS_CURRENT_DOWN4;
2824
+ var MASK_BLOCK_SIGHT4 = CONTENTS_SOLID4 | CONTENTS_LAVA4 | CONTENTS_SLIME4 | CONTENTS_MONSTER4 | CONTENTS_PLAYER4;
2825
+ var MASK_NAV_SOLID4 = CONTENTS_SOLID4 | CONTENTS_PLAYERCLIP4 | CONTENTS_WINDOW4;
2826
+ var MASK_LADDER_NAV_SOLID4 = CONTENTS_SOLID4 | CONTENTS_WINDOW4;
2827
+ var MASK_WALK_NAV_SOLID4 = CONTENTS_SOLID4 | CONTENTS_PLAYERCLIP4 | CONTENTS_WINDOW4 | CONTENTS_MONSTERCLIP4;
2828
+ var MASK_PROJECTILE4 = MASK_SHOT4 | CONTENTS_PROJECTILECLIP4;
2829
+ var MAX_CHECKCOUNT4 = Number.MAX_SAFE_INTEGER - 1;
2830
+ var MAX_CLIENTS4 = 256;
2831
+ var MAX_LIGHTSTYLES4 = 256;
2832
+ var MAX_MODELS4 = 8192;
2833
+ var MAX_SOUNDS4 = 2048;
2834
+ var MAX_IMAGES4 = 512;
2835
+ var MAX_ITEMS4 = 256;
2836
+ var MAX_GENERAL4 = MAX_CLIENTS4 * 2;
2837
+ var MAX_SHADOW_LIGHTS4 = 256;
2838
+ var MAX_WHEEL_ITEMS4 = 32;
2839
+ var ConfigStringIndex4 = ((ConfigStringIndex22) => {
1038
2840
  ConfigStringIndex22[ConfigStringIndex22["Name"] = 0] = "Name";
1039
2841
  ConfigStringIndex22[ConfigStringIndex22["CdTrack"] = 1] = "CdTrack";
1040
2842
  ConfigStringIndex22[ConfigStringIndex22["Sky"] = 2] = "Sky";
@@ -1045,23 +2847,23 @@ var ConfigStringIndex3 = ((ConfigStringIndex22) => {
1045
2847
  ConfigStringIndex22[ConfigStringIndex22["MaxClients"] = 60] = "MaxClients";
1046
2848
  ConfigStringIndex22[ConfigStringIndex22["MapChecksum"] = 61] = "MapChecksum";
1047
2849
  ConfigStringIndex22[ConfigStringIndex22["Models"] = 62] = "Models";
1048
- ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS3] = "Sounds";
1049
- ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS3] = "Images";
1050
- ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES3] = "Lights";
1051
- ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES3] = "ShadowLights";
1052
- ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS3] = "Items";
1053
- ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS3] = "PlayerSkins";
1054
- ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS3] = "General";
1055
- ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL3] = "WheelWeapons";
1056
- ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS3] = "WheelAmmo";
1057
- ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS3] = "WheelPowerups";
1058
- ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS3] = "CdLoopCount";
2850
+ ConfigStringIndex22[ConfigStringIndex22["Sounds"] = 62 + MAX_MODELS4] = "Sounds";
2851
+ ConfigStringIndex22[ConfigStringIndex22["Images"] = ConfigStringIndex22.Sounds + MAX_SOUNDS4] = "Images";
2852
+ ConfigStringIndex22[ConfigStringIndex22["Lights"] = ConfigStringIndex22.Images + MAX_IMAGES4] = "Lights";
2853
+ ConfigStringIndex22[ConfigStringIndex22["ShadowLights"] = ConfigStringIndex22.Lights + MAX_LIGHTSTYLES4] = "ShadowLights";
2854
+ ConfigStringIndex22[ConfigStringIndex22["Items"] = ConfigStringIndex22.ShadowLights + MAX_SHADOW_LIGHTS4] = "Items";
2855
+ ConfigStringIndex22[ConfigStringIndex22["PlayerSkins"] = ConfigStringIndex22.Items + MAX_ITEMS4] = "PlayerSkins";
2856
+ ConfigStringIndex22[ConfigStringIndex22["General"] = ConfigStringIndex22.PlayerSkins + MAX_CLIENTS4] = "General";
2857
+ ConfigStringIndex22[ConfigStringIndex22["WheelWeapons"] = ConfigStringIndex22.General + MAX_GENERAL4] = "WheelWeapons";
2858
+ ConfigStringIndex22[ConfigStringIndex22["WheelAmmo"] = ConfigStringIndex22.WheelWeapons + MAX_WHEEL_ITEMS4] = "WheelAmmo";
2859
+ ConfigStringIndex22[ConfigStringIndex22["WheelPowerups"] = ConfigStringIndex22.WheelAmmo + MAX_WHEEL_ITEMS4] = "WheelPowerups";
2860
+ ConfigStringIndex22[ConfigStringIndex22["CdLoopCount"] = ConfigStringIndex22.WheelPowerups + MAX_WHEEL_ITEMS4] = "CdLoopCount";
1059
2861
  ConfigStringIndex22[ConfigStringIndex22["GameStyle"] = ConfigStringIndex22.CdLoopCount + 1] = "GameStyle";
1060
2862
  ConfigStringIndex22[ConfigStringIndex22["MaxConfigStrings"] = ConfigStringIndex22.GameStyle + 1] = "MaxConfigStrings";
1061
2863
  return ConfigStringIndex22;
1062
- })(ConfigStringIndex3 || {});
1063
- var MAX_CONFIGSTRINGS3 = ConfigStringIndex3.MaxConfigStrings;
1064
- var WATERJUMP_CLEAR3 = 8 | 16 | 32 | 1024;
2864
+ })(ConfigStringIndex4 || {});
2865
+ var MAX_CONFIGSTRINGS4 = ConfigStringIndex4.MaxConfigStrings;
2866
+ var WATERJUMP_CLEAR4 = 8 | 16 | 32 | 1024;
1065
2867
 
1066
2868
  // src/index.ts
1067
2869
  function bootstrapViewer() {
@@ -1074,8 +2876,8 @@ function bootstrapViewer() {
1074
2876
  trace(start, end) {
1075
2877
  return { start, end, fraction: 1 };
1076
2878
  }
1077
- }, { gravity: ZERO_VEC33 });
1078
- const client = createClient({ engine: { trace: () => ({ start: ZERO_VEC33, end: ZERO_VEC33, fraction: 1 }) } });
2879
+ }, { gravity: ZERO_VEC34 });
2880
+ const client = createClient({ engine: { trace: () => ({ start: ZERO_VEC34, end: ZERO_VEC34, fraction: 1 }) } });
1079
2881
  const runtime = createEngineRuntime(engine, game, client);
1080
2882
  runtime.start();
1081
2883
  return { engine, game, client, runtime };