@vimp-games/snakes 0.7.3 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,25 +19,39 @@ Mouse and touch are the second way to play, and the only one a phone has:
19
19
  faster than the keys would turn it; **double tap and keep holding** — boost,
20
20
  for as long as the finger stays down. Releasing hands the snake back to
21
21
  whatever heading it had, and taking hold of `A`/`D` cancels the pointer
22
- target. The channel is muted while the chat, the stat table or a vote is
23
- open, so typing a message never steers the snake.
22
+ target. The channel is muted while the chat or the stat table is open, so
23
+ typing a message never steers the snake.
24
24
 
25
25
  Three ways it ends and only one of them is your fault:
26
26
 
27
27
  - your head touches the boundary of the disc — you crash;
28
- - your head touches **another** snake's body — you crash, and everything you
29
- were carrying scatters over the map where you died;
28
+ - your head runs into **another** snake **in front of you** — you crash, and
29
+ everything you were carrying scatters over the map where you died. The
30
+ crash is only ever the one who drove into it: a snake that swings into you
31
+ from the side or from behind takes itself out and leaves you alone (two
32
+ snakes that meet head on are both driving into each other, and both die);
30
33
  - your head touches **your own** tail — nothing happens, it passes over.
31
34
 
32
- Three numbers follow you, and none of them is reset by a crash: **eaten**
33
- (crystals swallowed), **kills** (snakes that ran into you) and **score**, which
34
- is the crystals you ate plus the entire score of everyone you killed. Killing
35
- the leader is worth the double: you take their whole score, and their crystals
36
- scatter on the map on top of it. The HUD shows all three; what you are carrying
37
- right now is told by the size of your snake.
35
+ One number follows you and a crash does not reset it: **score** — the crystals
36
+ you have eaten plus a flat **15** per snake that ran into you. The victim keeps
37
+ its own score; what it was carrying scatters on the map for whoever gets there
38
+ first, so killing the leader is still worth it, just not twice. The HUD shows
39
+ the score alone; what you are carrying right now is told by the size of your
40
+ snake. A kill is also worth a point of **rank**, the number `/rank` reports and
41
+ the one that survives the session.
42
+
43
+ The first two seconds of a life are yours: a fresh snake appears whole — body
44
+ and all, not a head that has to grow one — stands still and blinks, kills
45
+ nobody and cannot be killed. Long enough to read the arena, and
46
+ long enough for whoever was flying at that spot to steer around you.
47
+
48
+ The heavier you get the wider you steer: 3.4 rad/s empty, falling with the
49
+ square root of the crystals down to a floor of 1.4. A leader stays steerable
50
+ and stops being nimble — the fastest snake in the arena is a small one.
38
51
 
39
52
  The stat table (`Tab`) is a single leaderboard ranked by score, ties broken by
40
- crystals eaten. Everyone is a player; there are no teams.
53
+ rank. Everyone is a player: there are no teams, no spectators and nothing to
54
+ vote on.
41
55
 
42
56
  ## Run it
43
57
 
@@ -177,6 +191,23 @@ ready-made placeholders in `assets/sounds/`: when `build/sounds/` is absent,
177
191
  on a bare machine. The two cues are `pickup` and `death`, both played
178
192
  positionally by `src/client/parts/Snake.js`.
179
193
 
194
+ ## Documentation
195
+
196
+ Full documentation lives in [docs/en/](docs/en/README.md):
197
+
198
+ - [Local setup](docs/en/getting-started.md)
199
+ - [Architecture](docs/en/architecture.md)
200
+ - [Gameplay](docs/en/gameplay.md)
201
+ - [Rust core](docs/en/core.md)
202
+ - [Configuration](docs/en/configuration.md)
203
+ - [Extending the game (models, tiers, sounds, parts)](docs/en/extending.md)
204
+
205
+ [Русская версия](docs/ru/README.md)
206
+
207
+ For engine-side concepts (transport, master server, plugin contract), see the
208
+ engine's own docs:
209
+ [vimp-engine/docs/en/](https://github.com/lgick/vimp-engine/blob/main/docs/en/README.md).
210
+
180
211
  ## Engine
181
212
 
182
213
  The engine versions this game builds against are the pins themselves —
@@ -0,0 +1,8 @@
1
+ import{Container as z,Graphics as P,Sprite as ee,Rectangle as te}from"pixi.js";const ne=3,re='#panel-score:before{content:"★ ";color:#ffd76b}#panel-crystals,#panel-dead,#panel-mode,#panel-time{display:none!important}#snakes-gameover{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background:#060a149e;font:400 16px/1.5 system-ui,sans-serif;color:#e6ecf5}#snakes-gameover[hidden]{display:none}.snakes-gameover-card{min-width:260px;padding:28px 32px;border:1px solid #39507f;border-radius:12px;background:#141c30;box-shadow:0 18px 48px #00000073;text-align:center}.snakes-gameover-card h2{margin:0 0 4px;font-size:22px;font-weight:600;letter-spacing:.02em}.snakes-gameover-score{margin:0 0 6px;opacity:.75}.snakes-gameover-total{margin:0 0 22px;font-size:15px;letter-spacing:.02em;opacity:.6}.snakes-gameover-total span{font-weight:700;color:#ffd76b}.snakes-gameover-score span{font-size:40px;font-weight:700;color:#7ef9ff;vertical-align:-2px}.snakes-gameover-card button{min-width:120px;padding:10px 20px;border:0;border-radius:8px;background:#3ab7ff;color:#06182a;font:inherit;font-weight:600;cursor:pointer}.snakes-gameover-card button:hover,.snakes-gameover-card button:focus-visible{background:#7ed0ff}',se={background:856608,floor:1317936,edge:3756159,edgeWidth:10,rings:4,ringColor:1911111},v={innerScale:.62,innerDarken:.55,smoothing:4,eye:16251903,pupil:1054760,boostGlow:16771466},oe=.5;class ie extends z{constructor(e){super(),this.zIndex=0,!(Array.isArray(e)||e.type==="dynamic")&&this._draw(e)}_draw({map:e,step:t}){const n=e.length,_=(e[0]?.length??0)*t,i=n*t,c=Math.min(_,i)/2,f=_/2,a=i/2,{background:l,floor:d,edge:u,edgeWidth:b,rings:m,ringColor:Q}=se,w=new P;w.rect(-_,-i,_*3,i*3),w.fill(l),w.circle(f,a,c),w.fill(d);for(let I=1;I<m;I+=1)w.circle(f,a,c*I/m),w.stroke({color:Q,width:2,alpha:oe});w.circle(f,a,c),w.stroke({color:u,width:b,alignment:1}),this.addChild(w)}update(){}destroy(){super.destroy({children:!0})}}const G=[16731469,16752412,16765503,10214972,3065014,3848191,5531903,11623679,16735432,16250871,8250065,16753828],D=[8321535,10146047,13154047,12386267,16771466,16757702],Y=[{value:1,radius:8},{value:3,radius:13},{value:8,radius:20}],X=16,S=X*2,E={ANGLE:S,RADIUS:S+1,CRYSTALS:S+2,COLOR:S+3,FLAGS:S+4},ce=1,_e=2,ae=4,$=.25,le=.85;function fe(r){const e=(Math.sin(r/1e3*ae*Math.PI*2)+1)/2;return $+(le-$)*e}function de(r,e){const t=Math.round((r>>16&255)*e),n=Math.round((r>>8&255)*e),o=Math.round((r&255)*e);return t<<16|n<<8|o}function pe(r,e){const t=r.length-1;if(t<1)return r;const n=[r[0]];for(let o=0;o<t;o+=1){const _=r[Math.max(o-1,0)],i=r[o],c=r[o+1],f=r[Math.min(o+2,t)];for(let a=1;a<=e;a+=1){const l=a/e,d=l*l,u=d*l;n.push([.5*(2*i[0]+(-_[0]+c[0])*l+(2*_[0]-5*i[0]+4*c[0]-f[0])*d+(-_[0]+3*i[0]-3*c[0]+f[0])*u),.5*(2*i[1]+(-_[1]+c[1])*l+(2*_[1]-5*i[1]+4*c[1]-f[1])*d+(-_[1]+3*i[1]-3*c[1]+f[1])*u)])}}return n}class ue extends z{constructor(e,t,n={},o={}){super(),this.zIndex=3,this._sound=n.soundManager,this._localPlayer=n.localPlayer,this._id=o.id??null,this._body=new P,this._head=new P,this.addChild(this._body,this._head),this._headAt=[0,0],this._crystals=null,this.update(e)}update(e){const t=e[E.RADIUS]||1,n=e[E.ANGLE]||0,o=e[E.CRYSTALS]||0,_=e[E.FLAGS]||0,i=(_&ce)!==0,c=(_&_e)!==0,f=G[(e[E.COLOR]||0)%G.length],a=[];for(let l=0;l<X;l+=1)a.push([e[l*2]||0,e[l*2+1]||0]);this.alpha=c?fe(performance.now()):1,this._drawBody(a,t,f,i),this._drawHead(a[0],n,t,f),this._crystals!==null&&o>this._crystals&&this._play("pickup",a[0]),this._crystals=o,this._headAt=a[0]}_drawBody(e,t,n,o){const _=pe(e,v.smoothing),i=this._body;i.clear(),i.moveTo(_[0][0],_[0][1]);for(let c=1;c<_.length;c+=1)i.lineTo(_[c][0],_[c][1]);o&&i.stroke({color:v.boostGlow,width:t*2.6,alpha:.22,cap:"round",join:"round"}),i.stroke({color:n,width:t*2,cap:"round",join:"round"}),i.stroke({color:de(n,v.innerDarken),width:t*2*v.innerScale,alpha:.45,cap:"round",join:"round"})}_drawHead([e,t],n,o,_){const i=this._head;i.clear(),i.circle(e,t,o),i.fill(_);const c=Math.cos(n),f=Math.sin(n),a=o*.5,l=o*.42,d=o*.32;for(const u of[-1,1]){const b=e+c*l-f*a*u,m=t+f*l+c*a*u;i.circle(b,m,d),i.fill(v.eye),i.circle(b+c*d*.35,m+f*d*.35,d*.5),i.fill(v.pupil)}}_isLocal(){return this._localPlayer?this._localPlayer.is(this._id):(this._warned||(this._warned=!0,console.error("[snakes] the `localPlayer` service is missing: engine too old, game cues stay silent")),!1)}_play(e,[t,n]){!this._sound||!this._isLocal()||this._sound.registerSound(e,{position:{x:t,y:n}})}destroy(){this._play("death",this._headAt),super.destroy({children:!0})}}const O={X:0,Y:1,TIER:2,COLOR:3},he=32;class ge extends z{constructor(e,t){super(),this.zIndex=2,this._sprite=new ee(t.crystalGem),this._sprite.anchor.set(.5),this.addChild(this._sprite),this.update(e)}update(e){this.x=e[O.X]||0,this.y=e[O.Y]||0;const t=Y[e[O.TIER]||0]??Y[0];this._sprite.scale.set(t.radius/he),this._sprite.tint=D[(e[O.COLOR]||0)%D.length],this._sprite.rotation=(this.x+this.y)%360*(Math.PI/180)}destroy(){super.destroy({children:!0})}}const be={Arena:ie,Snake:ue,Crystal:ge};function we(r,e){const{radius:t,facets:n}=r,o=t*2,_=new P,i=(l,d,u=0)=>{const b=(d+u)/n*Math.PI*2-Math.PI/2;return[t+Math.cos(b)*l,t+Math.sin(b)*l]},c=[];for(let l=0;l<n;l+=1)c.push(i(t*.94,l));_.poly(c.flat()),_.fill({color:16777215,alpha:.85});const f=[];for(let l=0;l<n;l+=1)f.push(i(t*.5,l,.5));_.poly(f.flat()),_.fill({color:16777215,alpha:1});const a=e.generateTexture({target:_,frame:new te(0,0,o,o)});return _.destroy(!0),a}const ye={crystalGem:we},x="snakes-gameover",me=82,B="d",U="s";function ve(r,e){const t=new KeyboardEvent(r,{keyCode:e,bubbles:!0});t.keyCode!==e&&(Object.defineProperty(t,"keyCode",{value:e}),Object.defineProperty(t,"which",{value:e})),window.dispatchEvent(t)}function xe(r){const e={};for(const t of r??[]){const n=String(t).indexOf(":");n>0&&(e[t.slice(0,n)]=Number(t.slice(n+1)))}return e}class Ae{constructor(){this._root=null,this._crystals=null,this._total=null,this._visible=!1,this._lastScore=0}mount(){if(this._root||typeof document>"u")return;const e=document.createElement("div");e.id=x,e.hidden=!0,e.innerHTML=`
2
+ <div class="${x}-card">
3
+ <h2>You crashed</h2>
4
+ <p class="${x}-score"><span>0</span> crystals</p>
5
+ <p class="${x}-total">Total score: <span>0</span></p>
6
+ <button type="button">OK</button>
7
+ </div>
8
+ `,this._crystals=e.querySelector(`.${x}-score span`),this._total=e.querySelector(`.${x}-total span`),e.querySelector("button").addEventListener("click",()=>this._respawn()),document.body.appendChild(e),this._root=e}onPanel(e){if(!this._root)return;const t=xe(e);if(U in t&&(this._lastScore=t[U]),!(B in t))return;const n=t[B];n>0?this._show(n-1):this._hide()}reset(){this._hide(),this._lastScore=0}_show(e){this._visible||(this._visible=!0,this._crystals.textContent=String(e),this._total.textContent=String(this._lastScore),this._root.hidden=!1)}_hide(){this._visible&&(this._visible=!1,this._root.hidden=!0)}_respawn(){this._hide();for(const e of["keydown","keyup"])ve(e,me)}}const Se="modulepreload",Ee=function(r){return"/"+r},K={},ke=function(e,t,n){let o=Promise.resolve();if(t&&t.length>0){let f=function(a){return Promise.all(a.map(l=>Promise.resolve(l).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),c=i?.nonce||i?.getAttribute("nonce");o=f(t.map(a=>{if(a=Ee(a),a in K)return;K[a]=!0;const l=a.endsWith(".css"),d=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${a}"]${d}`))return;const u=document.createElement("link");if(u.rel=l?"stylesheet":Se,l||(u.as="script"),u.crossOrigin="",u.href=a,c&&u.setAttribute("nonce",c),document.head.appendChild(u),l)return new Promise((b,m)=>{u.addEventListener("load",b),u.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${a}`)))})}))}function _(i){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=i,window.dispatchEvent(c),!c.defaultPrevented)throw i}return o.then(i=>{for(const c of i||[])c.status==="rejected"&&_(c.reason);return e().catch(_)})},Ce=r=>(r??"").endsWith(".js"),Re=r=>import(r),Oe=()=>ke(()=>Promise.resolve().then(()=>Fe),[]),M=new Ae,ze={id:"snakes",engineApi:ne,async createClientCore(r,{wasmUrl:e}={}){if(Ce(e)){const _=await Re(e);return{core:new _.ClientCore(r),memory:null}}const{default:t,ClientCore:n}=await Oe(),o=await t({module_or_path:e});return{core:new n(r),memory:o.memory}},parts:be,bakers:ye,styles:re,hooks:{onAuth(r,e){r.set_model(e.model),M.mount(),M.reset()},onPanel(r,e){r.sync_panel(JSON.stringify(e)),M.onPanel(e)},onLocalAction(){return null}}};class N{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,q.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_clientcore_free(e,0)}apply_aim(e,t,n,o){s.clientcore_apply_aim(this.__wbg_ptr,e,t,n,o)}apply_input(e,t,n){const o=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),_=p,i=h(t,s.__wbindgen_malloc,s.__wbindgen_realloc),c=p;s.clientcore_apply_input(this.__wbg_ptr,o,_,i,c,n)}debug_json(){let e,t;try{const n=s.clientcore_debug_json(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}decode_frame(e){let t,n;try{const o=j(e,s.__wbindgen_malloc),_=p,i=s.clientcore_decode_frame(this.__wbg_ptr,o,_);return t=i[0],n=i[1],g(i[0],i[1])}finally{s.__wbindgen_free(t,n,1)}}hot_ptr(){return s.clientcore_hot_ptr(this.__wbg_ptr)>>>0}hot_values(){const e=s.clientcore_hot_values(this.__wbg_ptr);var t=F(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}my_game_id(){return s.clientcore_my_game_id(this.__wbg_ptr)}constructor(e){const t=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=p,o=s.clientcore_new(t,n);if(o[2])throw y(o[1]);return this.__wbg_ptr=o[0],q.register(this,this.__wbg_ptr,this),this}offset(){return s.clientcore_offset(this.__wbg_ptr)}push_frame(e,t){const n=j(e,s.__wbindgen_malloc),o=p;return s.clientcore_push_frame(this.__wbg_ptr,n,o,t)!==0}reset(){s.clientcore_reset(this.__wbg_ptr)}resync(){s.clientcore_resync(this.__wbg_ptr)}sample(e){return s.clientcore_sample(this.__wbg_ptr,e)>>>0}set_active(e){s.clientcore_set_active(this.__wbg_ptr,e)}set_map(e){const t=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=p,o=s.clientcore_set_map(this.__wbg_ptr,t,n);if(o[1])throw y(o[0])}set_model(e){const t=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=p;s.clientcore_set_model(this.__wbg_ptr,t,n)}sync_panel(e){const t=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=p;s.clientcore_sync_panel(this.__wbg_ptr,t,n)}take_divergence(){let e,t;try{const n=s.clientcore_take_divergence(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}take_frames(){let e,t;try{const n=s.clientcore_take_frames(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(N.prototype[Symbol.dispose]=N.prototype.free);class W{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,H.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_gamecore_free(e,0)}alive_players(){const e=s.gamecore_alive_players(this.__wbg_ptr);var t=F(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}apply_aim(e,t,n,o,_){s.gamecore_apply_aim(this.__wbg_ptr,e,t,n,o,_)}apply_input(e,t,n,o){const _=h(n,s.__wbindgen_malloc,s.__wbindgen_realloc),i=p,c=h(o,s.__wbindgen_malloc,s.__wbindgen_realloc),f=p;s.gamecore_apply_input(this.__wbg_ptr,e,t,_,i,c,f)}body_has_events(){return s.gamecore_body_has_events(this.__wbg_ptr)!==0}clear(){s.gamecore_clear(this.__wbg_ptr)}debug_json(){let e,t;try{const n=s.gamecore_debug_json(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}deserialize_state(e){const t=j(e,s.__wbindgen_malloc),n=p,o=s.gamecore_deserialize_state(this.__wbg_ptr,t,n);if(o[1])throw y(o[0])}frame_bytes(){const e=s.gamecore_frame_bytes(this.__wbg_ptr);var t=V(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}frame_ptr(){return s.gamecore_frame_ptr(this.__wbg_ptr)>>>0}is_alive(e){return s.gamecore_is_alive(this.__wbg_ptr,e)!==0}last_input_seq(e){return s.gamecore_last_input_seq(this.__wbg_ptr,e)>>>0}load_map(e){const t=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=p,o=s.gamecore_load_map(this.__wbg_ptr,t,n);if(o[1])throw y(o[0])}map_info(){let e,t;try{const n=s.gamecore_map_info(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}constructor(e){const t=h(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=p,o=s.gamecore_new(t,n);if(o[2])throw y(o[1]);return this.__wbg_ptr=o[0],H.register(this,this.__wbg_ptr,this),this}pack_body(){const e=s.gamecore_pack_body(this.__wbg_ptr);if(e[1])throw y(e[0])}pack_frame(e,t,n,o,_,i,c,f){var a=Pe(c)?0:h(c,s.__wbindgen_malloc,s.__wbindgen_realloc),l=p;return s.gamecore_pack_frame(this.__wbg_ptr,e,t,n,o,_,i,a,l,f)>>>0}players_data(){let e,t;try{const n=s.gamecore_players_data(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}position_of(e){const t=s.gamecore_position_of(this.__wbg_ptr,e);var n=F(t[0],t[1]).slice();return s.__wbindgen_free(t[0],t[1]*4,4),n}remove_actor(e){s.gamecore_remove_actor(this.__wbg_ptr,e)}remove_players_and_shots(){let e,t;try{const n=s.gamecore_remove_players_and_shots(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}remove_scripted_actor(e){s.gamecore_remove_scripted_actor(this.__wbg_ptr,e)}reset_actor(e,t,n,o,_){s.gamecore_reset_actor(this.__wbg_ptr,e,t,n,o,_)}reset_all_vitals(){s.gamecore_reset_all_vitals(this.__wbg_ptr)}serialize_state(){const e=s.gamecore_serialize_state(this.__wbg_ptr);if(e[3])throw y(e[2]);var t=V(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}spawn_actor(e,t,n,o,_,i){const c=h(t,s.__wbindgen_malloc,s.__wbindgen_realloc),f=p,a=s.gamecore_spawn_actor(this.__wbg_ptr,e,c,f,n,o,_,i);if(a[1])throw y(a[0])}spawn_scripted_actor(e,t,n,o,_,i){const c=h(t,s.__wbindgen_malloc,s.__wbindgen_realloc),f=p,a=s.gamecore_spawn_scripted_actor(this.__wbg_ptr,e,c,f,n,o,_,i);if(a[1])throw y(a[0])}step(e){s.gamecore_step(this.__wbg_ptr,e)}take_events(){let e,t;try{const n=s.gamecore_take_events(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(W.prototype[Symbol.dispose]=W.prototype.free);function Z(){return{__proto__:null,"./vimp_snakes_core_bg.js":{__proto__:null,__wbg_Error_408e67f47ca7b58b:function(e,t){return Error(g(e,t))},__wbg___wbindgen_throw_bb96b2010945f0bc:function(e,t){throw new Error(g(e,t))},__wbindgen_init_externref_table:function(){const e=s.__wbindgen_externrefs,t=e.grow(4);e.set(0,void 0),e.set(t+0,void 0),e.set(t+1,null),e.set(t+2,!0),e.set(t+3,!1)}}}}const q=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(r=>s.__wbg_clientcore_free(r,1)),H=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(r=>s.__wbg_gamecore_free(r,1));function F(r,e){return r=r>>>0,Le().subarray(r/4,r/4+e)}function V(r,e){return r=r>>>0,A().subarray(r/1,r/1+e)}let k=null;function Le(){return(k===null||k.byteLength===0)&&(k=new Float32Array(s.memory.buffer)),k}function g(r,e){return Me(r>>>0,e)}let C=null;function A(){return(C===null||C.byteLength===0)&&(C=new Uint8Array(s.memory.buffer)),C}function Pe(r){return r==null}function j(r,e){const t=e(r.length*1,1)>>>0;return A().set(r,t/1),p=r.length,t}function h(r,e,t){if(t===void 0){const c=R.encode(r),f=e(c.length,1)>>>0;return A().subarray(f,f+c.length).set(c),p=c.length,f}let n=r.length,o=e(n,1)>>>0;const _=A();let i=0;for(;i<n;i++){const c=r.charCodeAt(i);if(c>127)break;_[o+i]=c}if(i!==n){i!==0&&(r=r.slice(i)),o=t(o,n,n=i+r.length*3,1)>>>0;const c=A().subarray(o+i,o+n),f=R.encodeInto(r,c);i+=f.written,o=t(o,n,i,1)>>>0}return p=i,o}function y(r){const e=s.__wbindgen_externrefs.get(r);return s.__externref_table_dealloc(r),e}let L=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});L.decode();const Ie=2146435072;let T=0;function Me(r,e){return T+=e,T>=Ie&&(L=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),L.decode(),T=e),L.decode(A().subarray(r,r+e))}const R=new TextEncoder;"encodeInto"in R||(R.encodeInto=function(r,e){const t=R.encode(r);return e.set(t),{read:r.length,written:t.length}});let p=0,s;function J(r,e){return s=r.exports,k=null,C=null,s.__wbindgen_start(),s}async function Te(r,e){if(typeof Response=="function"&&r instanceof Response){if(!r.ok)throw new Error(`failed to fetch Wasm: ${r.status} ${r.statusText} fetching '${r.url}'`);if(typeof WebAssembly.instantiateStreaming=="function")try{return await WebAssembly.instantiateStreaming(r,e)}catch(o){if(t(r.type)&&r.headers.get("Content-Type")!=="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",o);else throw o}const n=await r.arrayBuffer();return await WebAssembly.instantiate(n,e)}else{const n=await WebAssembly.instantiate(r,e);return n instanceof WebAssembly.Instance?{instance:n,module:r}:n}function t(n){switch(n){case"basic":case"cors":case"default":return!0}return!1}}function Ne(r){if(s!==void 0)return s;r!==void 0&&(Object.getPrototypeOf(r)===Object.prototype?{module:r}=r:console.warn("using deprecated parameters for `initSync()`; pass a single object instead"));const e=Z();r instanceof WebAssembly.Module||(r=new WebAssembly.Module(r));const t=new WebAssembly.Instance(r,e);return J(t)}async function We(r){if(s!==void 0)return s;r!==void 0&&(Object.getPrototypeOf(r)===Object.prototype?{module_or_path:r}=r:console.warn("using deprecated parameters for the initialization function; pass a single object instead")),r===void 0&&(r=new URL("/assets/vimp_snakes_core_bg-DkZbe0aC.wasm",import.meta.url));const e=Z();(typeof r=="string"||typeof Request=="function"&&r instanceof Request||typeof URL=="function"&&r instanceof URL)&&(r=fetch(r));const{instance:t,module:n}=await Te(await r,e);return J(t)}const Fe=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:N,GameCore:W,default:We,initSync:Ne},Symbol.toStringTag,{value:"Module"}));export{ze as default};
@@ -0,0 +1 @@
1
+ const K=Array.from({length:16},(n,e)=>[{name:`p${e}x`,ty:"f32",interp:"lerp"},{name:`p${e}y`,ty:"f32",interp:"lerp"}]).flat(),Z={s1:{id:1,kind:"indexed8",class:"hot",fields:[...K,{name:"angle",ty:"f32",interp:"lerpAngle"},{name:"radius",ty:"f32",interp:"lerp"},{name:"crystals",ty:"u16"},{name:"color",ty:"u8"},{name:"boost",ty:"u8"}]},cr:{id:2,kind:"indexed32",class:"event",fields:[{name:"x",ty:"f32"},{name:"y",ty:"f32"},{name:"tier",ty:"u8"},{name:"color",ty:"u8"}]},c1:{id:3,kind:"indexedNoNull8",class:"hot",fields:[{name:"x",ty:"f32",interp:"lerp"},{name:"y",ty:"f32",interp:"lerp"},{name:"angle",ty:"f32",interp:"lerpAngle"}]}},X=[{value:1,radius:8},{value:3,radius:13},{value:8,radius:20}],A={s1:{baseSpeed:260,boostFactor:1.9,turnSpeed:3.4,turnSpeedFalloff:.18,turnSpeedMin:1.4,baseRadius:14,radiusGain:1.6,baseLength:150,lengthPerCrystal:9,pointSpacing:6,boostDrainPerSecond:6,boostMinCrystals:2,world:{maxCrystals:60,spawnInterval:.35,tierWeights:[70,25,5],tiers:X,dropRatio:.8,edgeMargin:60,startCrystals:0,spawnGraceSeconds:2}}},Q={},W=128,I=1,J=20,D=8,E=4,k=64,ee=Math.PI*(3-Math.sqrt(5)),te=.72,re=25;function R(n){const e=Math.ceil(Math.max(n,0)/E)*E,t=Math.max(e,D);return Math.round(J*Math.sqrt(t/D))}const B=Math.log2(k);if(!Number.isInteger(B))throw new Error(`RESPAWN_COUNT must be a power of two (the order is bit-reversed), got ${k}`);function ne(n){let e=0;for(let t=0;t<B;t+=1)e=e<<1|n>>t&1;return e}function se(n){const e=n*W/2,t=e;return Array.from({length:k},(r,a)=>{const o=ne(a),i=e*te*Math.sqrt((o+.5)/k),_=o*ee,c=t+Math.cos(_)*i,l=t+Math.sin(_)*i,h=(a*.6180339887%1*2-1)*re,m=_*180/Math.PI+180+h;return[Math.round(c),Math.round(l),Math.round((m%360+360)%360)]})}function U(n=0){const e=R(n);return{setId:"c1",scale:1,step:W,physicsStatic:[],physicsDynamic:[],layers:{1:[I]},map:Array.from({length:e},()=>Array.from({length:e},()=>I)),respawns:{players:se(e)}}}const ae=U(0),ie={arena:ae},oe={title:"Vimp Snakes",parts:{models:A,weapons:Q,friendlyFire:!1},snapshot:Z,soundCues:{roundStart:null,victory:null,defeat:null,frag:null,death:null},maps:ie,currentMap:"arena",mapScale:1,mapSetId:"c1",mapsInVote:1,timers:{timeStep:1e3/120,networkSendRate:4,roundTime:36e5,mapTime:36e5,roomTimeMin:1e4,roomTimeMax:36e5,voteTime:1e4,timeBlockedVote:3e4,teamChangeGracePeriod:1e4,roundRestartDelay:5e3,mapChangeDelay:2e3,rttPingInterval:3e3,idleCheckInterval:3e4},playerState:{defaultState:{best:0,eaten:0}},noSpectators:!0,endlessRound:!0,teams:{players:1},scripted:{namePrefix:"Snake",defaultModel:"s1"},playerKeys:{left:{key:1},right:{key:2},boost:{key:4},respawn:{key:8,type:1}},panel:{fields:{crystals:{key:"c",value:0},score:{key:"s",value:0},dead:{key:"d",value:0}},activeKey:"wa"},stat:{name:{key:0,bodyMethod:"=",headSync:!0,headMethod:"#"},status:{key:1,bodyMethod:"=",bodyValue:"",headValue:""},rank:{key:2,bodyMethod:"=",bodyValue:0},score:{key:3,bodyMethod:"=",bodyValue:0,headMethod:"+",headValue:0},latency:{key:4,bodyMethod:"="}},roomDefaults:{maxPlayers:32},roomForm:[{name:"maxPlayers",control:"text",label:"Max players",numeric:!0},{name:"map",control:"select",label:"Map",source:"maps"}]},_e={elems:{authId:"auth",fieldsId:"auth-fields",errorId:"auth-error",enterId:"auth-enter",titleId:"auth-title",informsId:"auth-informs"},texts:{title:"Vimp Snakes",sections:[{heading:"How to play",lines:[{keys:"a, d",text:"turn"},{keys:"w",text:"boost (burns crystals)"},{keys:"r",text:"respawn after a crash"},{separator:!0},{keys:"",text:"eat crystals to grow"},{keys:"",text:"the edge and other snakes kill you"},{keys:"",text:"your own tail does not"},{separator:!0},{keys:"c",text:"chat"},{keys:"<Tab>",text:"stats",last:!0}]}]},params:[{name:"model",value:"s1",options:{control:"select",label:"Snake",options:Object.keys(A),validator:"isValidModel",storage:"model"}}],validators:{isValidModel:n=>n in A}},ce={pickup:{file:"shot",priority:80,volume:.35},death:{file:"death",priority:150,volume:.5}},le={codecList:["webm","mp3"],sounds:ce},pe={parts:{gameSets:{s1:["Snake"],cr:["Crystal"],c1:["Arena"]},entitiesOnCanvas:{Arena:"vimp",Snake:"vimp",Crystal:"vimp"},bakedAssets:{vimp:[{name:"crystalGem",component:"Crystal",params:{radius:32,facets:6}}]},componentDependencies:{soundManager:["Snake"],localPlayer:["Snake"]},sounds:le},initIdList:["vimp","panel","chat"],modules:{canvasManager:{canvases:{vimp:{width:960,height:600,aspectRatio:"16:10",baseScale:"1:1",dynamicCamera:!0,shakeCamera:!1}}},controls:{modes:{77:""},keySetList:[{78:"nextPlayer",80:"prevPlayer"},{65:"left",68:"right",87:"boost",82:"respawn"}],pointer:{keySets:[1],doubleTapMs:300,doubleTapPx:40,sendIntervalMs:50}},chat:{params:{messages:{s:["The arena is full. You will join as soon as a place frees up","You are already in the arena","You are in the arena","You are watching the arena","{0} crashed into {1}","{0} joined the game","{0} left the game"],v:["A vote has been created","Voting has started","Your vote has been accepted","Voting is temporarily unavailable","Vote passed","Vote failed"],m:["Current map: {0}","Next map: {0}"],c:["Command not found","Your rank: {0}"],n:["Invalid name","{0} changed name to {1}"],g:["Bot snakes in the arena: {0}","Invalid bot count"]}}},panel:{keys:{s:"score",c:"crystals",d:"dead",wa:"mode",t:"time"},fields:[{name:"score",elem:"panel-score",type:"value"},{name:"crystals",elem:"panel-crystals",type:"value"},{name:"dead",elem:"panel-dead",type:"value"},{name:"mode",elem:"panel-mode",type:"weapon"},{name:"time",elem:"panel-time",type:"time"}]},stat:{params:{columns:["snake","status","rank","score","ping"],heads:{1:"players"},bodies:{1:"players"},sortList:{players:[[3,!0],[2,!0]]}}}},gameInform:{list:["{0} WINS!","SLITHER!","GAME OVER!"]}};class de{constructor({participants:e,coreAdapter:t,socketManager:r},a){this._participants=e,this._coreAdapter=t,this._socketManager=r,this._scriptedManager=a,this._vimp=null,this._population=null,this._size=null,this._mapData=null,this._delivered=new Map}onCoreEvent(e,t={}){t.vimp&&(this._vimp=t.vimp),!(!e||e.type!=="population")&&this._apply(Number(e.count)||0)}_apply(e){const t=this._sizeFor(e);if(t!==this._size){this._size=t,this._population=e;const r=U(e);this._coreAdapter.createMap(r),this._scriptedManager?.createMap(r),this._vimp?.overrideMapData?.(r),this._mapData=r,this._delivered.clear()}this._broadcast()}_sizeFor(e){if(this._size===null)return R(e);const t=R(e);return t>this._size||e<=this._population-E?t:this._size}_broadcast(){if(!this._mapData)return;const e=this._participants.getHumans();for(const t of e)!t.isReady||this._delivered.get(t.gameId)===this._size||(this._delivered.set(t.gameId,this._size),this._socketManager.sendMap(t.socketId,this._mapData));if(this._delivered.size>e.length){const t=new Set(e.map(r=>r.gameId));for(const r of this._delivered.keys())t.has(r)||this._delivered.delete(r)}}reapply(){this._mapData&&(this._vimp?.overrideMapData?.(this._mapData),this._coreAdapter.createMap(this._mapData),this._scriptedManager?.createMap(this._mapData),this._broadcast())}get mapData(){return this._mapData??null}}class ue{constructor({participants:e,coreAdapter:t,panel:r,stat:a,scripted:o}){this._participants=e,this._coreAdapter=t,this._panel=r,this._stat=a,this._model=o.defaultModel,this._respawns=null}createMap(e){this._respawns=e.respawns}getCountsPerTeam(){const e={};for(const t of this._participants.getScripted())e[t.team]=(e[t.team]??0)+1;return e}createScripted(e,t=null){if(!this._respawns)return 0;const r=this._participants.getPlayableTeams();let a=0;for(let o=0;o<e&&!this._participants.isFull;o+=1){const i=t??this._pickTeam(r);if(!i||!this._hasRoom(i))break;const _=this._participants.createScripted({team:i,model:this._model}),c=this._participants.get(_);this._stat.addUser(_,c.teamId,{name:c.name,status:"",latency:"BOT"}),this._panel.addUser(_),a+=1}return a}_hasRoom(e){const t=this._respawns[e];return!!(t&&this._participants.getTeamSize(e)<t.length)}_pickTeam(e){return[...e].sort((t,r)=>this._participants.getTeamSize(t)-this._participants.getTeamSize(r)).find(t=>this._hasRoom(t))??null}removeScripted(e=null){const t=this._participants.getScripted();(e?t.filter(a=>a.team===e):t).forEach(a=>this._remove(a.gameId))}removeOneForHuman(e){for(const t of this._participants.getScripted())if(t.team===e)return this._remove(t.gameId),!0;return!1}_remove(e){const t=this._participants.get(e);!t||!t.isScripted||(this._stat.removeUser(e,t.teamId),this._panel.removeUser(e),this._coreAdapter.removePlayer(e),this._participants.remove(e))}}const he=15,F=25,fe=6e4;class me{constructor({participants:e,stat:t}){this._participants=e,this._stat=t,this._totals=new Map,this._lastFlush=0,this._rankDirty=!1}onCoreEvent(e,t={}){if(!e||typeof e!="object")return;const{vimp:r,panel:a}=t,o=String(e.id);switch(e.type){case"crystals":this._onCrystals(o,Number(e.gained)||0,r,a);break;case"death":this._onDeath(o,e,r,a);break;case"population":this._publishNewcomers(r,a),this._maybeFlush(r);break}}reset(e){this._totals.delete(e)}_onCrystals(e,t,r,a){const o=this._record(e);if(!(!o||t<=0)){for(o.eaten+=t,o.score+=t;o.eaten-o.rankedEaten>=F;)o.rankedEaten+=F,this._addRank(e,1,r);this._publish(e,o,r,a),this._maybeFlush(r)}}_onDeath(e,t,r,a){const o=this._record(e);if(!o)return;const i=t.killer===null||t.killer===void 0?null:String(t.killer);if(i!==null&&i!==e){const _=this._record(i);_&&(_.kills+=1,_.score+=he,this._addRank(i,1,r),this._publish(i,_,r,a))}this._publish(e,o,r,a),this._recordBest(e,o,r),this._maybeFlush(r)}_addRank(e,t,r){r?.addPlayerRank?.(e,t),this._rankDirty=!0}_maybeFlush(e){if(!this._rankDirty||!e?.flushPlayerData)return;const t=Date.now();t-this._lastFlush<fe||(this._lastFlush=t,this._rankDirty=!1,e.flushPlayerData())}_record(e){const t=this._participants.get(e);if(!t)return null;const r=this._totals.get(e);if(r&&r.participant===t)return r;const a={participant:t,eaten:0,kills:0,score:0,flushedEaten:0,rankedEaten:0,published:!1};return this._totals.set(e,a),a}_publishNewcomers(e,t){for(const r of this._participants.getAll()){const a=r.gameId,o=this._totals.get(a),i=o?.participant===r?o:this._record(a);i&&!i.published&&this._publish(a,i,e,t)}}_publish(e,t,r,a){const{score:o}=t,i={score:o},_=r?.isPlayerRankLoaded?.(e)??!1;_&&(i.rank=r.getPlayerRank(e)),t.published=_,this._stat.updateUser(e,t.participant.teamId,i),a&&a.updateUser(e,"score",o,"set")}_recordBest(e,t,r){if(!r?.getPlayerState)return;const a=r.getPlayerState(e);if(!a)return;const o=t.eaten-t.flushedEaten;t.flushedEaten=t.eaten;const i=Math.max(Number(a.best)||0,t.score),_=(Number(a.eaten)||0)+o;r.setPlayerState(e,{...a,best:i,eaten:_})}}let V=null,j=null;function ge(n){const e=new ue(n);return V=new me(n),j=new de(n,e),{scripted:e}}function ye(){return V}function G(){return j}const be={name:"/bot",handler(n,e,t){const r=Number(t[0]);if(t[0]===void 0||!Number.isFinite(r)||r<0){n.chat.pushSystemByUser(e,"BOT_COUNT_INVALID");return}const{maxPlayers:a}=n.participants,o=Math.trunc(r),i=a>0?Math.min(o,a):o;n.scripted.removeScripted();const _=i>0?n.scripted.createScripted(i):0;n.chat.pushSystem("BOTS_SET",[_]),_>0&&(n.roundManager.initiateNewRound(),G()?.reapply())}},we={name:"/name",handler(n,e,t){n.roundManager.changeName(e,t.join(" "))}},ve={name:"/nr",handler(n,e){n.isDevMode?n.roundManager.initiateNewRound():n.chat.pushSystemByUser(e,"COMMANDS_NOT_FOUND")}},Se={name:"/rank",handler(n,e){n.chat.pushSystemByUser(e,"RANK",[n.playerDataSync.getRank(e)])}},ke={BOTS_SET:"g:0",BOT_COUNT_INVALID:"g:1"},Me="modulepreload",Ae=function(n){return"/"+n},O={},Ee=function(e,t,r){let a=Promise.resolve();if(t&&t.length>0){let c=function(l){return Promise.all(l.map(h=>Promise.resolve(h).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),_=i?.nonce||i?.getAttribute("nonce");a=c(t.map(l=>{if(l=Ae(l),l in O)return;O[l]=!0;const h=l.endsWith(".css"),m=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${l}"]${m}`))return;const g=document.createElement("link");if(g.rel=h?"stylesheet":Me,h||(g.as="script"),g.crossOrigin="",g.href=l,_&&g.setAttribute("nonce",_),document.head.appendChild(g),h)return new Promise(($,H)=>{g.addEventListener("load",$),g.addEventListener("error",()=>H(new Error(`Unable to preload CSS for ${l}`)))})}))}function o(i){const _=new Event("vite:preloadError",{cancelable:!0});if(_.payload=i,window.dispatchEvent(_),!_.defaultPrevented)throw i}return a.then(i=>{for(const _ of i||[])_.status==="rejected"&&o(_.reason);return e().catch(o)})},Re=n=>(n??"").endsWith(".js"),Ce=n=>import(n),Te=()=>Ee(()=>Promise.resolve().then(()=>Le),[]),ze={id:"snakes",engineApi:3,async createCore(n,{wasmUrl:e}={}){if(Re(e)){const a=await Ce(e);return new a.GameCore(n)}const{default:t,GameCore:r}=await Te();return await t({module_or_path:e}),new r(n)},gameConfig:oe,authSchema:_e,chatCommands:[be,we,ve,Se],systemMessages:ke,createModules:ge,buildClientGameConfig:()=>pe,onCoreEvent(n,e={}){ye()?.onCoreEvent(n,e),G()?.onCoreEvent(n,e)}};class C{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,x.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_clientcore_free(e,0)}apply_aim(e,t,r,a){s.clientcore_apply_aim(this.__wbg_ptr,e,t,r,a)}apply_input(e,t,r){const a=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),o=p,i=d(t,s.__wbindgen_malloc,s.__wbindgen_realloc),_=p;s.clientcore_apply_input(this.__wbg_ptr,a,o,i,_,r)}debug_json(){let e,t;try{const r=s.clientcore_debug_json(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}decode_frame(e){let t,r;try{const a=N(e,s.__wbindgen_malloc),o=p,i=s.clientcore_decode_frame(this.__wbg_ptr,a,o);return t=i[0],r=i[1],u(i[0],i[1])}finally{s.__wbindgen_free(t,r,1)}}hot_ptr(){return s.clientcore_hot_ptr(this.__wbg_ptr)>>>0}hot_values(){const e=s.clientcore_hot_values(this.__wbg_ptr);var t=P(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}my_game_id(){return s.clientcore_my_game_id(this.__wbg_ptr)}constructor(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=p,a=s.clientcore_new(t,r);if(a[2])throw f(a[1]);return this.__wbg_ptr=a[0],x.register(this,this.__wbg_ptr,this),this}offset(){return s.clientcore_offset(this.__wbg_ptr)}push_frame(e,t){const r=N(e,s.__wbindgen_malloc),a=p;return s.clientcore_push_frame(this.__wbg_ptr,r,a,t)!==0}reset(){s.clientcore_reset(this.__wbg_ptr)}resync(){s.clientcore_resync(this.__wbg_ptr)}sample(e){return s.clientcore_sample(this.__wbg_ptr,e)>>>0}set_active(e){s.clientcore_set_active(this.__wbg_ptr,e)}set_map(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=p,a=s.clientcore_set_map(this.__wbg_ptr,t,r);if(a[1])throw f(a[0])}set_model(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=p;s.clientcore_set_model(this.__wbg_ptr,t,r)}sync_panel(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=p;s.clientcore_sync_panel(this.__wbg_ptr,t,r)}take_divergence(){let e,t;try{const r=s.clientcore_take_divergence(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}take_frames(){let e,t;try{const r=s.clientcore_take_frames(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(C.prototype[Symbol.dispose]=C.prototype.free);class T{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,L.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_gamecore_free(e,0)}alive_players(){const e=s.gamecore_alive_players(this.__wbg_ptr);var t=P(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}apply_aim(e,t,r,a,o){s.gamecore_apply_aim(this.__wbg_ptr,e,t,r,a,o)}apply_input(e,t,r,a){const o=d(r,s.__wbindgen_malloc,s.__wbindgen_realloc),i=p,_=d(a,s.__wbindgen_malloc,s.__wbindgen_realloc),c=p;s.gamecore_apply_input(this.__wbg_ptr,e,t,o,i,_,c)}body_has_events(){return s.gamecore_body_has_events(this.__wbg_ptr)!==0}clear(){s.gamecore_clear(this.__wbg_ptr)}debug_json(){let e,t;try{const r=s.gamecore_debug_json(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}deserialize_state(e){const t=N(e,s.__wbindgen_malloc),r=p,a=s.gamecore_deserialize_state(this.__wbg_ptr,t,r);if(a[1])throw f(a[0])}frame_bytes(){const e=s.gamecore_frame_bytes(this.__wbg_ptr);var t=z(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}frame_ptr(){return s.gamecore_frame_ptr(this.__wbg_ptr)>>>0}is_alive(e){return s.gamecore_is_alive(this.__wbg_ptr,e)!==0}last_input_seq(e){return s.gamecore_last_input_seq(this.__wbg_ptr,e)>>>0}load_map(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=p,a=s.gamecore_load_map(this.__wbg_ptr,t,r);if(a[1])throw f(a[0])}map_info(){let e,t;try{const r=s.gamecore_map_info(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}constructor(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=p,a=s.gamecore_new(t,r);if(a[2])throw f(a[1]);return this.__wbg_ptr=a[0],L.register(this,this.__wbg_ptr,this),this}pack_body(){const e=s.gamecore_pack_body(this.__wbg_ptr);if(e[1])throw f(e[0])}pack_frame(e,t,r,a,o,i,_,c){var l=Ne(_)?0:d(_,s.__wbindgen_malloc,s.__wbindgen_realloc),h=p;return s.gamecore_pack_frame(this.__wbg_ptr,e,t,r,a,o,i,l,h,c)>>>0}players_data(){let e,t;try{const r=s.gamecore_players_data(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}position_of(e){const t=s.gamecore_position_of(this.__wbg_ptr,e);var r=P(t[0],t[1]).slice();return s.__wbindgen_free(t[0],t[1]*4,4),r}remove_actor(e){s.gamecore_remove_actor(this.__wbg_ptr,e)}remove_players_and_shots(){let e,t;try{const r=s.gamecore_remove_players_and_shots(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}remove_scripted_actor(e){s.gamecore_remove_scripted_actor(this.__wbg_ptr,e)}reset_actor(e,t,r,a,o){s.gamecore_reset_actor(this.__wbg_ptr,e,t,r,a,o)}reset_all_vitals(){s.gamecore_reset_all_vitals(this.__wbg_ptr)}serialize_state(){const e=s.gamecore_serialize_state(this.__wbg_ptr);if(e[3])throw f(e[2]);var t=z(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}spawn_actor(e,t,r,a,o,i){const _=d(t,s.__wbindgen_malloc,s.__wbindgen_realloc),c=p,l=s.gamecore_spawn_actor(this.__wbg_ptr,e,_,c,r,a,o,i);if(l[1])throw f(l[0])}spawn_scripted_actor(e,t,r,a,o,i){const _=d(t,s.__wbindgen_malloc,s.__wbindgen_realloc),c=p,l=s.gamecore_spawn_scripted_actor(this.__wbg_ptr,e,_,c,r,a,o,i);if(l[1])throw f(l[0])}step(e){s.gamecore_step(this.__wbg_ptr,e)}take_events(){let e,t;try{const r=s.gamecore_take_events(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(T.prototype[Symbol.dispose]=T.prototype.free);function Y(){return{__proto__:null,"./vimp_snakes_core_bg.js":{__proto__:null,__wbg_Error_408e67f47ca7b58b:function(e,t){return Error(u(e,t))},__wbg___wbindgen_throw_bb96b2010945f0bc:function(e,t){throw new Error(u(e,t))},__wbindgen_init_externref_table:function(){const e=s.__wbindgen_externrefs,t=e.grow(4);e.set(0,void 0),e.set(t+0,void 0),e.set(t+1,null),e.set(t+2,!0),e.set(t+3,!1)}}}}const x=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(n=>s.__wbg_clientcore_free(n,1)),L=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(n=>s.__wbg_gamecore_free(n,1));function P(n,e){return n=n>>>0,Pe().subarray(n/4,n/4+e)}function z(n,e){return n=n>>>0,y().subarray(n/1,n/1+e)}let b=null;function Pe(){return(b===null||b.byteLength===0)&&(b=new Float32Array(s.memory.buffer)),b}function u(n,e){return De(n>>>0,e)}let w=null;function y(){return(w===null||w.byteLength===0)&&(w=new Uint8Array(s.memory.buffer)),w}function Ne(n){return n==null}function N(n,e){const t=e(n.length*1,1)>>>0;return y().set(n,t/1),p=n.length,t}function d(n,e,t){if(t===void 0){const _=v.encode(n),c=e(_.length,1)>>>0;return y().subarray(c,c+_.length).set(_),p=_.length,c}let r=n.length,a=e(r,1)>>>0;const o=y();let i=0;for(;i<r;i++){const _=n.charCodeAt(i);if(_>127)break;o[a+i]=_}if(i!==r){i!==0&&(n=n.slice(i)),a=t(a,r,r=i+n.length*3,1)>>>0;const _=y().subarray(a+i,a+r),c=v.encodeInto(n,_);i+=c.written,a=t(a,r,i,1)>>>0}return p=i,a}function f(n){const e=s.__wbindgen_externrefs.get(n);return s.__externref_table_dealloc(n),e}let S=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});S.decode();const Ie=2146435072;let M=0;function De(n,e){return M+=e,M>=Ie&&(S=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),S.decode(),M=e),S.decode(y().subarray(n,n+e))}const v=new TextEncoder;"encodeInto"in v||(v.encodeInto=function(n,e){const t=v.encode(n);return e.set(t),{read:n.length,written:t.length}});let p=0,s;function q(n,e){return s=n.exports,b=null,w=null,s.__wbindgen_start(),s}async function Fe(n,e){if(typeof Response=="function"&&n instanceof Response){if(!n.ok)throw new Error(`failed to fetch Wasm: ${n.status} ${n.statusText} fetching '${n.url}'`);if(typeof WebAssembly.instantiateStreaming=="function")try{return await WebAssembly.instantiateStreaming(n,e)}catch(a){if(t(n.type)&&n.headers.get("Content-Type")!=="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",a);else throw a}const r=await n.arrayBuffer();return await WebAssembly.instantiate(r,e)}else{const r=await WebAssembly.instantiate(n,e);return r instanceof WebAssembly.Instance?{instance:r,module:n}:r}function t(r){switch(r){case"basic":case"cors":case"default":return!0}return!1}}function Oe(n){if(s!==void 0)return s;n!==void 0&&(Object.getPrototypeOf(n)===Object.prototype?{module:n}=n:console.warn("using deprecated parameters for `initSync()`; pass a single object instead"));const e=Y();n instanceof WebAssembly.Module||(n=new WebAssembly.Module(n));const t=new WebAssembly.Instance(n,e);return q(t)}async function xe(n){if(s!==void 0)return s;n!==void 0&&(Object.getPrototypeOf(n)===Object.prototype?{module_or_path:n}=n:console.warn("using deprecated parameters for the initialization function; pass a single object instead")),n===void 0&&(n=new URL("/assets/vimp_snakes_core_bg-DkZbe0aC.wasm",import.meta.url));const e=Y();(typeof n=="string"||typeof Request=="function"&&n instanceof Request||typeof URL=="function"&&n instanceof URL)&&(n=fetch(n));const{instance:t,module:r}=await Fe(await n,e);return q(t)}const Le=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:C,GameCore:T,default:xe,initSync:Oe},Symbol.toStringTag,{value:"Module"}));export{ze as default};
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "id": "snakes",
3
3
  "engineApi": 3,
4
- "version": "110511bf53cd9307",
4
+ "version": "b8f962fbe9339b52",
5
5
  "title": "Snakes",
6
6
  "entries": {
7
- "client": "/games/snakes/client-BaQIShJH.js",
8
- "host": "/games/snakes/host-DDabM4t-.js",
9
- "wasm": "/games/snakes/assets/vimp_snakes_core_bg-3ggUM5Py.wasm",
7
+ "client": "/games/snakes/client-DM9o4LDg.js",
8
+ "host": "/games/snakes/host-CwdOIyzB.js",
9
+ "wasm": "/games/snakes/assets/vimp_snakes_core_bg-DkZbe0aC.wasm",
10
10
  "wasmNode": "./core-node/vimp_snakes_core.js"
11
11
  },
12
12
  "assetsBase": "/games/snakes/",
13
13
  "maps": {
14
- "version": "06b6ec4320792b57",
14
+ "version": "d66bf1f388d9ba49",
15
15
  "list": [
16
16
  "arena"
17
17
  ]
@@ -1 +1 @@
1
- {"setId":"c1","scale":1,"step":128,"physicsStatic":[],"physicsDynamic":[],"layers":{"1":[1]},"map":[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],"respawns":{"players":[[1361,1280,180],[1176,1375,318],[1296,1099,95],[1411,1451,233],[1039,1237,10],[1508,1135,148],[1204,1564,285],[1135,1000,63],[1595,1395,200],[952,1415,338],[1438,942,115],[1397,1653,253],[928,1076,30],[1693,1189,168],[1028,1639,305],[1222,830,83],[1638,1582,220],[798,1300,358],[1631,930,135],[1257,1788,273],[946,880,50],[1809,1351,188],[831,1592,325],[1403,735,103],[1563,1775,240],[726,1103,18],[1818,1031,155],[1047,1837,293],[1072,701,70],[1834,1571,208],[665,1442,345],[1630,736,123],[1391,1927,260],[753,872,38],[1954,1224,175],[814,1784,313],[1283,584,90],[1754,1802,228],[568,1214,5],[1857,842,143],[1149,2001,280],[885,652,58],[2004,1479,195],[604,1627,333],[1547,559,110],[1573,2000,248],[570,944,25],[2039,1046,163],[874,1972,300],[1110,488,78],[1947,1754,215],[460,1382,353],[1821,644,130],[1311,2122,268],[683,674,45],[2137,1324,183],[612,1832,320],[1401,415,98],[1780,2006,235],[414,1081,13],[2060,838,150],[1001,2139,288],[902,451,65],[2125,1639,203]]}}
1
+ {"setId":"c1","scale":1,"step":128,"physicsStatic":[],"physicsDynamic":[],"layers":{"1":[1]},"map":[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],"respawns":{"players":[[1361,1280,155],[1391,1927,266],[1638,1582,207],[874,1972,318],[1595,1395,199],[1149,2001,260],[1563,1775,251],[612,1832,312],[1039,1237,32],[1283,584,93],[946,880,34],[1821,644,145],[928,1076,26],[1547,559,87],[1072,701,78],[2060,838,139],[1296,1099,114],[1954,1224,176],[1631,930,116],[1947,1754,228],[1438,942,108],[2004,1479,219],[1818,1031,160],[1780,2006,221],[1204,1564,302],[568,1214,3],[831,1592,304],[683,674,55],[1028,1639,295],[570,944,47],[665,1442,347],[902,451,48],[1176,1375,331],[753,872,33],[798,1300,333],[1110,488,84],[952,1415,325],[885,652,76],[726,1103,17],[1401,415,78],[1508,1135,159],[1754,1802,220],[1809,1351,211],[1311,2122,272],[1693,1189,152],[1573,2000,263],[1834,1571,204],[1001,2139,265],[1411,1451,241],[814,1784,302],[1257,1788,293],[460,1382,354],[1397,1653,234],[604,1627,346],[1047,1837,286],[414,1081,38],[1135,1000,68],[1857,842,129],[1403,735,120],[2137,1324,181],[1222,830,62],[2039,1046,173],[1630,736,114],[2125,1639,225]]}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vimp-games/snakes",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
4
4
  "description": "Vimp Snakes — a VIMP game plugin",
5
5
  "author": "lgick",
6
6
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  "globals": "^16.2.0",
47
47
  "happy-dom": "^20.10.6",
48
48
  "pixi.js": "^8.14.0",
49
- "vimp-engine": "^0.18.1",
49
+ "vimp-engine": "^0.20.0",
50
50
  "vite": "^7.1.11",
51
51
  "vitest": "^4.1.9"
52
52
  }
@@ -1,8 +0,0 @@
1
- import{Container as F,Graphics as P,Sprite as Z,Rectangle as ee}from"pixi.js";const te=3,ne='#panel-eaten:before{content:"◆ ";color:#7ef9ff}#panel-kills:before{content:"☠ ";color:#ff7a8a}#panel-score:before{content:"★ ";color:#ffd76b}#panel-crystals,#panel-dead,#panel-mode,#panel-time{display:none!important}#stat .stat-head span:nth-child(1),#stat table td:nth-child(1){width:34%}#stat .stat-head span:nth-child(2),#stat table td:nth-child(2){width:12%;text-align:center}#stat .stat-head span:nth-child(3),#stat table td:nth-child(3),#stat .stat-head span:nth-child(4),#stat table td:nth-child(4),#stat .stat-head span:nth-child(5),#stat table td:nth-child(5),#stat .stat-head span:nth-child(6),#stat table td:nth-child(6){width:13.5%;text-align:right}#snakes-gameover{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background:#060a149e;font:400 16px/1.5 system-ui,sans-serif;color:#e6ecf5}#snakes-gameover[hidden]{display:none}.snakes-gameover-card{min-width:260px;padding:28px 32px;border:1px solid #39507f;border-radius:12px;background:#141c30;box-shadow:0 18px 48px #00000073;text-align:center}.snakes-gameover-card h2{margin:0 0 4px;font-size:22px;font-weight:600;letter-spacing:.02em}.snakes-gameover-score{margin:0 0 6px;opacity:.75}.snakes-gameover-total{margin:0 0 22px;font-size:15px;letter-spacing:.02em;opacity:.6}.snakes-gameover-total span{font-weight:700;color:#ffd76b}.snakes-gameover-score span{font-size:40px;font-weight:700;color:#7ef9ff;vertical-align:-2px}.snakes-gameover-card button{min-width:120px;padding:10px 20px;border:0;border-radius:8px;background:#3ab7ff;color:#06182a;font:inherit;font-weight:600;cursor:pointer}.snakes-gameover-card button:hover,.snakes-gameover-card button:focus-visible{background:#7ed0ff}',re={background:856608,floor:1317936,edge:3756159,edgeWidth:10,rings:4,ringColor:1911111},v={innerScale:.62,innerDarken:.55,smoothing:4,eye:16251903,pupil:1054760,boostGlow:16771466},se=.5;class oe extends F{constructor(e){super(),this.zIndex=0,!(Array.isArray(e)||e.type==="dynamic")&&this._draw(e)}_draw({map:e,step:t}){const n=e.length,a=(e[0]?.length??0)*t,i=n*t,c=Math.min(a,i)/2,_=a/2,l=i/2,{background:d,floor:f,edge:p,edgeWidth:b,rings:m,ringColor:Q}=re,w=new P;w.rect(-a,-i,a*3,i*3),w.fill(d),w.circle(_,l,c),w.fill(f);for(let T=1;T<m;T+=1)w.circle(_,l,c*T/m),w.stroke({color:Q,width:2,alpha:se});w.circle(_,l,c),w.stroke({color:p,width:b,alignment:1}),this.addChild(w)}update(){}destroy(){super.destroy({children:!0})}}const D=[16731469,16752412,16765503,10214972,3065014,3848191,5531903,11623679,16735432,16250871,8250065,16753828],G=[8321535,10146047,13154047,12386267,16771466,16757702],U=[{value:1,radius:8},{value:3,radius:13},{value:8,radius:20}],V=16,k=V*2,A={ANGLE:k,RADIUS:k+1,CRYSTALS:k+2,COLOR:k+3,BOOST:k+4};function ie(r,e){const t=Math.round((r>>16&255)*e),n=Math.round((r>>8&255)*e),o=Math.round((r&255)*e);return t<<16|n<<8|o}function ce(r,e){const t=r.length-1;if(t<1)return r;const n=[r[0]];for(let o=0;o<t;o+=1){const a=r[Math.max(o-1,0)],i=r[o],c=r[o+1],_=r[Math.min(o+2,t)];for(let l=1;l<=e;l+=1){const d=l/e,f=d*d,p=f*d;n.push([.5*(2*i[0]+(-a[0]+c[0])*d+(2*a[0]-5*i[0]+4*c[0]-_[0])*f+(-a[0]+3*i[0]-3*c[0]+_[0])*p),.5*(2*i[1]+(-a[1]+c[1])*d+(2*a[1]-5*i[1]+4*c[1]-_[1])*f+(-a[1]+3*i[1]-3*c[1]+_[1])*p)])}}return n}class ae extends F{constructor(e,t,n={},o={}){super(),this.zIndex=3,this._sound=n.soundManager,this._localPlayer=n.localPlayer,this._id=o.id??null,this._body=new P,this._head=new P,this.addChild(this._body,this._head),this._headAt=[0,0],this._crystals=null,this.update(e)}update(e){const t=e[A.RADIUS]||1,n=e[A.ANGLE]||0,o=e[A.CRYSTALS]||0,a=!!e[A.BOOST],i=D[(e[A.COLOR]||0)%D.length],c=[];for(let _=0;_<V;_+=1)c.push([e[_*2]||0,e[_*2+1]||0]);this._drawBody(c,t,i,a),this._drawHead(c[0],n,t,i),this._crystals!==null&&o>this._crystals&&this._play("pickup",c[0]),this._crystals=o,this._headAt=c[0]}_drawBody(e,t,n,o){const a=ce(e,v.smoothing),i=this._body;i.clear(),i.moveTo(a[0][0],a[0][1]);for(let c=1;c<a.length;c+=1)i.lineTo(a[c][0],a[c][1]);o&&i.stroke({color:v.boostGlow,width:t*2.6,alpha:.22,cap:"round",join:"round"}),i.stroke({color:n,width:t*2,cap:"round",join:"round"}),i.stroke({color:ie(n,v.innerDarken),width:t*2*v.innerScale,alpha:.45,cap:"round",join:"round"})}_drawHead([e,t],n,o,a){const i=this._head;i.clear(),i.circle(e,t,o),i.fill(a);const c=Math.cos(n),_=Math.sin(n),l=o*.5,d=o*.42,f=o*.32;for(const p of[-1,1]){const b=e+c*d-_*l*p,m=t+_*d+c*l*p;i.circle(b,m,f),i.fill(v.eye),i.circle(b+c*f*.35,m+_*f*.35,f*.5),i.fill(v.pupil)}}_isLocal(){return this._localPlayer?this._localPlayer.is(this._id):(this._warned||(this._warned=!0,console.error("[snakes] the `localPlayer` service is missing: engine too old, game cues stay silent")),!1)}_play(e,[t,n]){!this._sound||!this._isLocal()||this._sound.registerSound(e,{position:{x:t,y:n}})}destroy(){this._play("death",this._headAt),super.destroy({children:!0})}}const R={X:0,Y:1,TIER:2,COLOR:3},_e=32;class le extends F{constructor(e,t){super(),this.zIndex=2,this._sprite=new Z(t.crystalGem),this._sprite.anchor.set(.5),this.addChild(this._sprite),this.update(e)}update(e){this.x=e[R.X]||0,this.y=e[R.Y]||0;const t=U[e[R.TIER]||0]??U[0];this._sprite.scale.set(t.radius/_e),this._sprite.tint=G[(e[R.COLOR]||0)%G.length],this._sprite.rotation=(this.x+this.y)%360*(Math.PI/180)}destroy(){super.destroy({children:!0})}}const de={Arena:oe,Snake:ae,Crystal:le};function fe(r,e){const{radius:t,facets:n}=r,o=t*2,a=new P,i=(d,f,p=0)=>{const b=(f+p)/n*Math.PI*2-Math.PI/2;return[t+Math.cos(b)*d,t+Math.sin(b)*d]},c=[];for(let d=0;d<n;d+=1)c.push(i(t*.94,d));a.poly(c.flat()),a.fill({color:16777215,alpha:.85});const _=[];for(let d=0;d<n;d+=1)_.push(i(t*.5,d,.5));a.poly(_.flat()),a.fill({color:16777215,alpha:1});const l=e.generateTexture({target:a,frame:new ee(0,0,o,o)});return a.destroy(!0),l}const he={crystalGem:fe},x="snakes-gameover",pe=82,Y="d",$="s";function ue(r,e){const t=new KeyboardEvent(r,{keyCode:e,bubbles:!0});t.keyCode!==e&&(Object.defineProperty(t,"keyCode",{value:e}),Object.defineProperty(t,"which",{value:e})),window.dispatchEvent(t)}function ge(r){const e={};for(const t of r??[]){const n=String(t).indexOf(":");n>0&&(e[t.slice(0,n)]=Number(t.slice(n+1)))}return e}class be{constructor(){this._root=null,this._crystals=null,this._total=null,this._visible=!1,this._lastScore=0}mount(){if(this._root||typeof document>"u")return;const e=document.createElement("div");e.id=x,e.hidden=!0,e.innerHTML=`
2
- <div class="${x}-card">
3
- <h2>You crashed</h2>
4
- <p class="${x}-score"><span>0</span> crystals</p>
5
- <p class="${x}-total">Total score: <span>0</span></p>
6
- <button type="button">OK</button>
7
- </div>
8
- `,this._crystals=e.querySelector(`.${x}-score span`),this._total=e.querySelector(`.${x}-total span`),e.querySelector("button").addEventListener("click",()=>this._respawn()),document.body.appendChild(e),this._root=e}onPanel(e){if(!this._root)return;const t=ge(e);if($ in t&&(this._lastScore=t[$]),!(Y in t))return;const n=t[Y];n>0?this._show(n-1):this._hide()}reset(){this._hide(),this._lastScore=0}_show(e){this._visible||(this._visible=!0,this._crystals.textContent=String(e),this._total.textContent=String(this._lastScore),this._root.hidden=!1)}_hide(){this._visible&&(this._visible=!1,this._root.hidden=!0)}_respawn(){this._hide();for(const e of["keydown","keyup"])ue(e,pe)}}const we="modulepreload",ye=function(r){return"/"+r},B={},me=function(e,t,n){let o=Promise.resolve();if(t&&t.length>0){let _=function(l){return Promise.all(l.map(d=>Promise.resolve(d).then(f=>({status:"fulfilled",value:f}),f=>({status:"rejected",reason:f}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),c=i?.nonce||i?.getAttribute("nonce");o=_(t.map(l=>{if(l=ye(l),l in B)return;B[l]=!0;const d=l.endsWith(".css"),f=d?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${l}"]${f}`))return;const p=document.createElement("link");if(p.rel=d?"stylesheet":we,d||(p.as="script"),p.crossOrigin="",p.href=l,c&&p.setAttribute("nonce",c),document.head.appendChild(p),d)return new Promise((b,m)=>{p.addEventListener("load",b),p.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${l}`)))})}))}function a(i){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=i,window.dispatchEvent(c),!c.defaultPrevented)throw i}return o.then(i=>{for(const c of i||[])c.status==="rejected"&&a(c.reason);return e().catch(a)})},ve=r=>(r??"").endsWith(".js"),xe=r=>import(r),Se=()=>me(()=>Promise.resolve().then(()=>Pe),[]),I=new be,Ie={id:"snakes",engineApi:te,async createClientCore(r,{wasmUrl:e}={}){if(ve(e)){const a=await xe(e);return{core:new a.ClientCore(r),memory:null}}const{default:t,ClientCore:n}=await Se(),o=await t({module_or_path:e});return{core:new n(r),memory:o.memory}},parts:de,bakers:he,styles:ne,hooks:{onAuth(r,e){r.set_model(e.model),I.mount(),I.reset()},onPanel(r,e){r.sync_panel(JSON.stringify(e)),I.onPanel(e)},onLocalAction(){return null}}};class W{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,q.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_clientcore_free(e,0)}apply_aim(e,t,n,o){s.clientcore_apply_aim(this.__wbg_ptr,e,t,n,o)}apply_input(e,t,n){const o=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),a=h,i=u(t,s.__wbindgen_malloc,s.__wbindgen_realloc),c=h;s.clientcore_apply_input(this.__wbg_ptr,o,a,i,c,n)}debug_json(){let e,t;try{const n=s.clientcore_debug_json(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}decode_frame(e){let t,n;try{const o=z(e,s.__wbindgen_malloc),a=h,i=s.clientcore_decode_frame(this.__wbg_ptr,o,a);return t=i[0],n=i[1],g(i[0],i[1])}finally{s.__wbindgen_free(t,n,1)}}hot_ptr(){return s.clientcore_hot_ptr(this.__wbg_ptr)>>>0}hot_values(){const e=s.clientcore_hot_values(this.__wbg_ptr);var t=j(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}my_game_id(){return s.clientcore_my_game_id(this.__wbg_ptr)}constructor(e){const t=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.clientcore_new(t,n);if(o[2])throw y(o[1]);return this.__wbg_ptr=o[0],q.register(this,this.__wbg_ptr,this),this}offset(){return s.clientcore_offset(this.__wbg_ptr)}push_frame(e,t){const n=z(e,s.__wbindgen_malloc),o=h;return s.clientcore_push_frame(this.__wbg_ptr,n,o,t)!==0}reset(){s.clientcore_reset(this.__wbg_ptr)}resync(){s.clientcore_resync(this.__wbg_ptr)}sample(e){return s.clientcore_sample(this.__wbg_ptr,e)>>>0}set_active(e){s.clientcore_set_active(this.__wbg_ptr,e)}set_map(e){const t=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.clientcore_set_map(this.__wbg_ptr,t,n);if(o[1])throw y(o[0])}set_model(e){const t=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h;s.clientcore_set_model(this.__wbg_ptr,t,n)}sync_panel(e){const t=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h;s.clientcore_sync_panel(this.__wbg_ptr,t,n)}take_divergence(){let e,t;try{const n=s.clientcore_take_divergence(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}take_frames(){let e,t;try{const n=s.clientcore_take_frames(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(W.prototype[Symbol.dispose]=W.prototype.free);class N{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,K.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_gamecore_free(e,0)}alive_players(){const e=s.gamecore_alive_players(this.__wbg_ptr);var t=j(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}apply_aim(e,t,n,o,a){s.gamecore_apply_aim(this.__wbg_ptr,e,t,n,o,a)}apply_input(e,t,n,o){const a=u(n,s.__wbindgen_malloc,s.__wbindgen_realloc),i=h,c=u(o,s.__wbindgen_malloc,s.__wbindgen_realloc),_=h;s.gamecore_apply_input(this.__wbg_ptr,e,t,a,i,c,_)}body_has_events(){return s.gamecore_body_has_events(this.__wbg_ptr)!==0}clear(){s.gamecore_clear(this.__wbg_ptr)}debug_json(){let e,t;try{const n=s.gamecore_debug_json(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}deserialize_state(e){const t=z(e,s.__wbindgen_malloc),n=h,o=s.gamecore_deserialize_state(this.__wbg_ptr,t,n);if(o[1])throw y(o[0])}frame_bytes(){const e=s.gamecore_frame_bytes(this.__wbg_ptr);var t=H(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}frame_ptr(){return s.gamecore_frame_ptr(this.__wbg_ptr)>>>0}is_alive(e){return s.gamecore_is_alive(this.__wbg_ptr,e)!==0}last_input_seq(e){return s.gamecore_last_input_seq(this.__wbg_ptr,e)>>>0}load_map(e){const t=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.gamecore_load_map(this.__wbg_ptr,t,n);if(o[1])throw y(o[0])}map_info(){let e,t;try{const n=s.gamecore_map_info(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}constructor(e){const t=u(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.gamecore_new(t,n);if(o[2])throw y(o[1]);return this.__wbg_ptr=o[0],K.register(this,this.__wbg_ptr,this),this}pack_body(){const e=s.gamecore_pack_body(this.__wbg_ptr);if(e[1])throw y(e[0])}pack_frame(e,t,n,o,a,i,c,_){var l=Ae(c)?0:u(c,s.__wbindgen_malloc,s.__wbindgen_realloc),d=h;return s.gamecore_pack_frame(this.__wbg_ptr,e,t,n,o,a,i,l,d,_)>>>0}players_data(){let e,t;try{const n=s.gamecore_players_data(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}position_of(e){const t=s.gamecore_position_of(this.__wbg_ptr,e);var n=j(t[0],t[1]).slice();return s.__wbindgen_free(t[0],t[1]*4,4),n}remove_actor(e){s.gamecore_remove_actor(this.__wbg_ptr,e)}remove_players_and_shots(){let e,t;try{const n=s.gamecore_remove_players_and_shots(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}remove_scripted_actor(e){s.gamecore_remove_scripted_actor(this.__wbg_ptr,e)}reset_actor(e,t,n,o,a){s.gamecore_reset_actor(this.__wbg_ptr,e,t,n,o,a)}reset_all_vitals(){s.gamecore_reset_all_vitals(this.__wbg_ptr)}serialize_state(){const e=s.gamecore_serialize_state(this.__wbg_ptr);if(e[3])throw y(e[2]);var t=H(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}spawn_actor(e,t,n,o,a,i){const c=u(t,s.__wbindgen_malloc,s.__wbindgen_realloc),_=h,l=s.gamecore_spawn_actor(this.__wbg_ptr,e,c,_,n,o,a,i);if(l[1])throw y(l[0])}spawn_scripted_actor(e,t,n,o,a,i){const c=u(t,s.__wbindgen_malloc,s.__wbindgen_realloc),_=h,l=s.gamecore_spawn_scripted_actor(this.__wbg_ptr,e,c,_,n,o,a,i);if(l[1])throw y(l[0])}step(e){s.gamecore_step(this.__wbg_ptr,e)}take_events(){let e,t;try{const n=s.gamecore_take_events(this.__wbg_ptr);return e=n[0],t=n[1],g(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(N.prototype[Symbol.dispose]=N.prototype.free);function X(){return{__proto__:null,"./vimp_snakes_core_bg.js":{__proto__:null,__wbg_Error_408e67f47ca7b58b:function(e,t){return Error(g(e,t))},__wbg___wbindgen_throw_bb96b2010945f0bc:function(e,t){throw new Error(g(e,t))},__wbindgen_init_externref_table:function(){const e=s.__wbindgen_externrefs,t=e.grow(4);e.set(0,void 0),e.set(t+0,void 0),e.set(t+1,null),e.set(t+2,!0),e.set(t+3,!1)}}}}const q=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(r=>s.__wbg_clientcore_free(r,1)),K=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(r=>s.__wbg_gamecore_free(r,1));function j(r,e){return r=r>>>0,ke().subarray(r/4,r/4+e)}function H(r,e){return r=r>>>0,S().subarray(r/1,r/1+e)}let E=null;function ke(){return(E===null||E.byteLength===0)&&(E=new Float32Array(s.memory.buffer)),E}function g(r,e){return Oe(r>>>0,e)}let O=null;function S(){return(O===null||O.byteLength===0)&&(O=new Uint8Array(s.memory.buffer)),O}function Ae(r){return r==null}function z(r,e){const t=e(r.length*1,1)>>>0;return S().set(r,t/1),h=r.length,t}function u(r,e,t){if(t===void 0){const c=C.encode(r),_=e(c.length,1)>>>0;return S().subarray(_,_+c.length).set(c),h=c.length,_}let n=r.length,o=e(n,1)>>>0;const a=S();let i=0;for(;i<n;i++){const c=r.charCodeAt(i);if(c>127)break;a[o+i]=c}if(i!==n){i!==0&&(r=r.slice(i)),o=t(o,n,n=i+r.length*3,1)>>>0;const c=S().subarray(o+i,o+n),_=C.encodeInto(r,c);i+=_.written,o=t(o,n,i,1)>>>0}return h=i,o}function y(r){const e=s.__wbindgen_externrefs.get(r);return s.__externref_table_dealloc(r),e}let L=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});L.decode();const Ee=2146435072;let M=0;function Oe(r,e){return M+=e,M>=Ee&&(L=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),L.decode(),M=e),L.decode(S().subarray(r,r+e))}const C=new TextEncoder;"encodeInto"in C||(C.encodeInto=function(r,e){const t=C.encode(r);return e.set(t),{read:r.length,written:t.length}});let h=0,s;function J(r,e){return s=r.exports,E=null,O=null,s.__wbindgen_start(),s}async function Ce(r,e){if(typeof Response=="function"&&r instanceof Response){if(!r.ok)throw new Error(`failed to fetch Wasm: ${r.status} ${r.statusText} fetching '${r.url}'`);if(typeof WebAssembly.instantiateStreaming=="function")try{return await WebAssembly.instantiateStreaming(r,e)}catch(o){if(t(r.type)&&r.headers.get("Content-Type")!=="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",o);else throw o}const n=await r.arrayBuffer();return await WebAssembly.instantiate(n,e)}else{const n=await WebAssembly.instantiate(r,e);return n instanceof WebAssembly.Instance?{instance:n,module:r}:n}function t(n){switch(n){case"basic":case"cors":case"default":return!0}return!1}}function Re(r){if(s!==void 0)return s;r!==void 0&&(Object.getPrototypeOf(r)===Object.prototype?{module:r}=r:console.warn("using deprecated parameters for `initSync()`; pass a single object instead"));const e=X();r instanceof WebAssembly.Module||(r=new WebAssembly.Module(r));const t=new WebAssembly.Instance(r,e);return J(t)}async function Le(r){if(s!==void 0)return s;r!==void 0&&(Object.getPrototypeOf(r)===Object.prototype?{module_or_path:r}=r:console.warn("using deprecated parameters for the initialization function; pass a single object instead")),r===void 0&&(r=new URL("/assets/vimp_snakes_core_bg-3ggUM5Py.wasm",import.meta.url));const e=X();(typeof r=="string"||typeof Request=="function"&&r instanceof Request||typeof URL=="function"&&r instanceof URL)&&(r=fetch(r));const{instance:t,module:n}=await Ce(await r,e);return J(t)}const Pe=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:W,GameCore:N,default:Le,initSync:Re},Symbol.toStringTag,{value:"Module"}));export{Ie as default};
@@ -1 +0,0 @@
1
- const q=Array.from({length:16},(n,e)=>[{name:`p${e}x`,ty:"f32",interp:"lerp"},{name:`p${e}y`,ty:"f32",interp:"lerp"}]).flat(),$={s1:{id:1,kind:"indexed8",class:"hot",fields:[...q,{name:"angle",ty:"f32",interp:"lerpAngle"},{name:"radius",ty:"f32",interp:"lerp"},{name:"crystals",ty:"u16"},{name:"color",ty:"u8"},{name:"boost",ty:"u8"}]},cr:{id:2,kind:"indexed32",class:"event",fields:[{name:"x",ty:"f32"},{name:"y",ty:"f32"},{name:"tier",ty:"u8"},{name:"color",ty:"u8"}]},c1:{id:3,kind:"indexedNoNull8",class:"hot",fields:[{name:"x",ty:"f32",interp:"lerp"},{name:"y",ty:"f32",interp:"lerp"},{name:"angle",ty:"f32",interp:"lerpAngle"}]}},H=[{value:1,radius:8},{value:3,radius:13},{value:8,radius:20}],M={s1:{baseSpeed:260,boostFactor:1.9,turnSpeed:3.4,baseRadius:14,radiusGain:1.6,baseLength:150,lengthPerCrystal:9,pointSpacing:6,boostDrainPerSecond:6,boostMinCrystals:2,world:{maxCrystals:60,spawnInterval:.35,tierWeights:[70,25,5],tiers:H,dropRatio:.8,edgeMargin:60,startCrystals:0}}},K={},B=128,I=1,X=20,N=8,C=4,x=64,Z=Math.PI*(3-Math.sqrt(5)),Q=.72;function A(n){const e=Math.ceil(Math.max(n,0)/C)*C,t=Math.max(e,N);return Math.round(X*Math.sqrt(t/N))}function J(n){const e=n*B/2,t=e;return Array.from({length:x},(r,a)=>{const o=e*Q*Math.sqrt((a+.5)/x),i=a*Z,_=t+Math.cos(i)*o,c=t+Math.sin(i)*o;return[Math.round(_),Math.round(c),Math.round(((i*180/Math.PI+180)%360+360)%360)]})}function V(n=0){const e=A(n);return{setId:"c1",scale:1,step:B,physicsStatic:[],physicsDynamic:[],layers:{1:[I]},map:Array.from({length:e},()=>Array.from({length:e},()=>I)),respawns:{players:J(e)}}}const ee=V(0),te={arena:ee},re={title:"Vimp Snakes",parts:{models:M,weapons:K,friendlyFire:!1},snapshot:$,soundCues:{roundStart:null,victory:null,defeat:null,frag:null,death:null},initialVote:"teamChange",maps:te,currentMap:"arena",mapScale:1,mapSetId:"c1",mapsInVote:1,timers:{timeStep:1e3/120,networkSendRate:4,roundTime:36e5,mapTime:36e5,roomTimeMin:1e4,roomTimeMax:36e5,voteTime:1e4,timeBlockedVote:3e4,teamChangeGracePeriod:1e4,roundRestartDelay:5e3,mapChangeDelay:2e3,rttPingInterval:3e3,idleCheckInterval:3e4},playerState:{defaultState:{best:0,eaten:0}},spectatorTeam:"spectators",teams:{players:1,spectators:2},scripted:{namePrefix:"Snake",defaultModel:"s1"},playerKeys:{left:{key:1},right:{key:2},boost:{key:4},respawn:{key:8,type:1}},panel:{fields:{crystals:{key:"c",value:0},eaten:{key:"e",value:0},kills:{key:"k",value:0},score:{key:"s",value:0},dead:{key:"d",value:0}},activeKey:"wa"},stat:{name:{key:0,bodyMethod:"=",headSync:!0,headMethod:"#"},status:{key:1,bodyMethod:"=",bodyValue:"",headValue:""},eaten:{key:2,bodyMethod:"=",bodyValue:0,headMethod:"+",headValue:0},kills:{key:3,bodyMethod:"=",bodyValue:0,headMethod:"+",headValue:0},score:{key:4,bodyMethod:"=",bodyValue:0,headMethod:"+",headValue:0},latency:{key:5,bodyMethod:"="}},roomDefaults:{maxPlayers:32},roomForm:[{name:"maxPlayers",control:"text",label:"Max players",numeric:!0},{name:"map",control:"select",label:"Map",source:"maps"}]},ne={elems:{authId:"auth",fieldsId:"auth-fields",errorId:"auth-error",enterId:"auth-enter",titleId:"auth-title",informsId:"auth-informs"},texts:{title:"Vimp Snakes",sections:[{heading:"How to play",lines:[{keys:"a, d",text:"turn"},{keys:"w",text:"boost (burns crystals)"},{keys:"r",text:"respawn after a crash"},{separator:!0},{keys:"",text:"eat crystals to grow"},{keys:"",text:"the edge and other snakes kill you"},{keys:"",text:"your own tail does not"},{separator:!0},{keys:"c",text:"chat"},{keys:"m",text:"vote"},{keys:"<Tab>",text:"stats",last:!0}]}]},params:[{name:"model",value:"s1",options:{control:"select",label:"Snake",options:Object.keys(M),validator:"isValidModel",storage:"model"}}],validators:{isValidModel:n=>n in M}},se={pickup:{file:"shot",priority:80,volume:.35},death:{file:"death",priority:150,volume:.5}},ae={codecList:["webm","mp3"],sounds:se},ie={parts:{gameSets:{s1:["Snake"],cr:["Crystal"],c1:["Arena"]},entitiesOnCanvas:{Arena:"vimp",Snake:"vimp",Crystal:"vimp"},bakedAssets:{vimp:[{name:"crystalGem",component:"Crystal",params:{radius:32,facets:6}}]},componentDependencies:{soundManager:["Snake"],localPlayer:["Snake"]},sounds:ae},initIdList:["vimp","panel","chat"],modules:{canvasManager:{canvases:{vimp:{width:960,height:600,aspectRatio:"16:10",baseScale:"1:1",dynamicCamera:!0,shakeCamera:!1}}},controls:{keySetList:[{78:"nextPlayer",80:"prevPlayer"},{65:"left",68:"right",87:"boost",82:"respawn"}],pointer:{keySets:[1],doubleTapMs:300,doubleTapPx:40,sendIntervalMs:50}},chat:{params:{messages:{s:["Team {0} is full. Your current team: {1}","Your team: {0}","Your new team: {0}","Your new status: spectator","{0} crashed into {1}","{0} joined the game","{0} left the game"],v:["A vote has been created","Voting has started","Your vote has been accepted","Voting is temporarily unavailable","Vote passed","Vote failed"],m:["Current map: {0}","Next map: {0}"],c:["Command not found","Your rank: {0}"],n:["Invalid name","{0} changed name to {1}"],g:["Bot snakes in the arena: {0}","Invalid bot count"]}}},panel:{keys:{e:"eaten",k:"kills",s:"score",c:"crystals",d:"dead",wa:"mode",t:"time"},fields:[{name:"eaten",elem:"panel-eaten",type:"value"},{name:"kills",elem:"panel-kills",type:"value"},{name:"score",elem:"panel-score",type:"value"},{name:"crystals",elem:"panel-crystals",type:"value"},{name:"dead",elem:"panel-dead",type:"value"},{name:"mode",elem:"panel-mode",type:"weapon"},{name:"time",elem:"panel-time",type:"time"}]},stat:{params:{columns:["snake","status","eaten","kills","score","ping"],heads:{1:"players"},bodies:{1:"players",2:"spectators"},sortList:{players:[[4,!0],[2,!0]]}}},vote:{params:{templates:{teamChange:["Play or watch?","teams",!0],mapChangeBySystem:["Choose the next map"],mapChangeByUser:["{0} suggested the map: {1}",["Yes","No"]]},menu:[["teamChange",["Play / watch","teams"]]]}}},gameInform:{list:["{0} WINS!","SLITHER!","GAME OVER!"]}};class oe{constructor({participants:e,coreAdapter:t,socketManager:r},a){this._participants=e,this._coreAdapter=t,this._socketManager=r,this._scriptedManager=a,this._population=null,this._size=null,this._mapData=null,this._delivered=new Map}onCoreEvent(e){!e||e.type!=="population"||this._apply(Number(e.count)||0)}_apply(e){const t=this._sizeFor(e);if(t!==this._size){this._size=t,this._population=e;const r=V(e);this._coreAdapter.createMap(r),this._scriptedManager?.createMap(r),this._mapData=r,this._delivered.clear()}this._broadcast()}_sizeFor(e){if(this._size===null)return A(e);const t=A(e);return t>this._size||e<=this._population-C?t:this._size}_broadcast(){if(!this._mapData)return;const e=this._participants.getHumans();for(const t of e)!t.isReady||this._delivered.get(t.gameId)===this._size||(this._delivered.set(t.gameId,this._size),this._socketManager.sendMap(t.socketId,this._mapData));if(this._delivered.size>e.length){const t=new Set(e.map(r=>r.gameId));for(const r of this._delivered.keys())t.has(r)||this._delivered.delete(r)}}get mapData(){return this._mapData??null}}class _e{constructor({participants:e,coreAdapter:t,panel:r,stat:a,scripted:o}){this._participants=e,this._coreAdapter=t,this._panel=r,this._stat=a,this._model=o.defaultModel,this._respawns=null}createMap(e){this._respawns=e.respawns}getCountsPerTeam(){const e={};for(const t of this._participants.getScripted())e[t.team]=(e[t.team]??0)+1;return e}createScripted(e,t=null){if(!this._respawns)return 0;const r=this._participants.getPlayableTeams();let a=0;for(let o=0;o<e&&!this._participants.isFull;o+=1){const i=t??this._pickTeam(r);if(!i||!this._hasRoom(i))break;const _=this._participants.createScripted({team:i,model:this._model}),c=this._participants.get(_);this._stat.addUser(_,c.teamId,{name:c.name,status:"",latency:"BOT"}),this._panel.addUser(_),a+=1}return a}_hasRoom(e){const t=this._respawns[e];return!!(t&&this._participants.getTeamSize(e)<t.length)}_pickTeam(e){return[...e].sort((t,r)=>this._participants.getTeamSize(t)-this._participants.getTeamSize(r)).find(t=>this._hasRoom(t))??null}removeScripted(e=null){const t=this._participants.getScripted();(e?t.filter(a=>a.team===e):[...t]).forEach(a=>this._remove(a.gameId))}removeOneForHuman(e){for(const t of this._participants.getScripted())if(t.team===e)return this._remove(t.gameId),!0;return!1}_remove(e){const t=this._participants.get(e);!t||!t.isScripted||(this._stat.removeUser(e,t.teamId),this._panel.removeUser(e),this._coreAdapter.removePlayer(e),this._participants.remove(e))}}class ce{constructor({participants:e,stat:t}){this._participants=e,this._stat=t,this._totals=new Map}onCoreEvent(e,t={}){if(!e||typeof e!="object")return;const{vimp:r,panel:a}=t,o=String(e.id);switch(e.type){case"crystals":this._onCrystals(o,Number(e.gained)||0,a);break;case"death":this._onDeath(o,e,r,a);break}}reset(e){this._totals.delete(e)}_onCrystals(e,t,r){const a=this._record(e);!a||t<=0||(a.eaten+=t,a.score+=t,this._publish(e,a,r))}_onDeath(e,t,r,a){const o=this._record(e);if(!o)return;const i=t.killer===null||t.killer===void 0?null:String(t.killer);if(i!==null&&i!==e){const _=this._record(i);_&&(_.kills+=1,_.score+=o.score,this._publish(i,_,a))}this._publish(e,o,a),this._recordBest(e,o,r)}_record(e){const t=this._participants.get(e);if(!t)return null;const r=this._totals.get(e);if(r&&r.participant===t)return r;const a={participant:t,eaten:0,kills:0,score:0,flushedEaten:0};return this._totals.set(e,a),a}_publish(e,t,r){const{eaten:a,kills:o,score:i}=t;this._stat.updateUser(e,t.participant.teamId,{eaten:a,kills:o,score:i}),r&&(r.updateUser(e,"eaten",a,"set"),r.updateUser(e,"kills",o,"set"),r.updateUser(e,"score",i,"set"))}_recordBest(e,t,r){if(!r?.getPlayerState)return;const a=r.getPlayerState(e);if(!a)return;const o=t.eaten-t.flushedEaten;t.flushedEaten=t.eaten;const i=Math.max(Number(a.best)||0,t.score),_=(Number(a.eaten)||0)+o;r.setPlayerState(e,{...a,best:i,eaten:_})}}let L=null,U=null;function le(n){const e=new _e(n);return L=new ce(n),U=new oe(n,e),{scripted:e}}function pe(){return L}function de(){return U}const ue={name:"/bot",handler(n,e,t){const r=Number(t[0]);if(t[0]===void 0||!Number.isFinite(r)||r<0){n.chat.pushSystemByUser(e,"BOT_COUNT_INVALID");return}const{maxPlayers:a}=n.participants,o=Math.trunc(r),i=a>0?Math.min(o,a):o;n.scripted.removeScripted();const _=i>0?n.scripted.createScripted(i):0;n.chat.pushSystem("BOTS_SET",[_]),_>0&&n.roundManager.initiateNewRound()}},me={name:"/name",handler(n,e,t){n.roundManager.changeName(e,t.join(" "))}},he={name:"/nr",handler(n,e){n.isDevMode?n.roundManager.initiateNewRound():n.chat.pushSystemByUser(e,"COMMANDS_NOT_FOUND")}},fe={name:"/rank",handler(n,e){n.chat.pushSystemByUser(e,"RANK",[n.playerDataSync.getRank(e)])}},ge={BOTS_SET:"g:0",BOT_COUNT_INVALID:"g:1"},ye="modulepreload",be=function(n){return"/"+n},O={},we=function(e,t,r){let a=Promise.resolve();if(t&&t.length>0){let c=function(p){return Promise.all(p.map(h=>Promise.resolve(h).then(g=>({status:"fulfilled",value:g}),g=>({status:"rejected",reason:g}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),_=i?.nonce||i?.getAttribute("nonce");a=c(t.map(p=>{if(p=be(p),p in O)return;O[p]=!0;const h=p.endsWith(".css"),g=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${p}"]${g}`))return;const f=document.createElement("link");if(f.rel=h?"stylesheet":ye,h||(f.as="script"),f.crossOrigin="",f.href=p,_&&f.setAttribute("nonce",_),document.head.appendChild(f),h)return new Promise((G,Y)=>{f.addEventListener("load",G),f.addEventListener("error",()=>Y(new Error(`Unable to preload CSS for ${p}`)))})}))}function o(i){const _=new Event("vite:preloadError",{cancelable:!0});if(_.payload=i,window.dispatchEvent(_),!_.defaultPrevented)throw i}return a.then(i=>{for(const _ of i||[])_.status==="rejected"&&o(_.reason);return e().catch(o)})},ve=n=>(n??"").endsWith(".js"),Se=n=>import(n),ke=()=>we(()=>Promise.resolve().then(()=>Ie),[]),Ne={id:"snakes",engineApi:3,async createCore(n,{wasmUrl:e}={}){if(ve(e)){const a=await Se(e);return new a.GameCore(n)}const{default:t,GameCore:r}=await ke();return await t({module_or_path:e}),new r(n)},gameConfig:re,authSchema:ne,chatCommands:[ue,me,he,fe],systemMessages:ge,createModules:le,buildClientGameConfig:()=>ie,onCoreEvent(n,e={}){pe()?.onCoreEvent(n,e),de()?.onCoreEvent(n)}};class E{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,z.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_clientcore_free(e,0)}apply_aim(e,t,r,a){s.clientcore_apply_aim(this.__wbg_ptr,e,t,r,a)}apply_input(e,t,r){const a=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),o=l,i=d(t,s.__wbindgen_malloc,s.__wbindgen_realloc),_=l;s.clientcore_apply_input(this.__wbg_ptr,a,o,i,_,r)}debug_json(){let e,t;try{const r=s.clientcore_debug_json(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}decode_frame(e){let t,r;try{const a=R(e,s.__wbindgen_malloc),o=l,i=s.clientcore_decode_frame(this.__wbg_ptr,a,o);return t=i[0],r=i[1],u(i[0],i[1])}finally{s.__wbindgen_free(t,r,1)}}hot_ptr(){return s.clientcore_hot_ptr(this.__wbg_ptr)>>>0}hot_values(){const e=s.clientcore_hot_values(this.__wbg_ptr);var t=P(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}my_game_id(){return s.clientcore_my_game_id(this.__wbg_ptr)}constructor(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=l,a=s.clientcore_new(t,r);if(a[2])throw m(a[1]);return this.__wbg_ptr=a[0],z.register(this,this.__wbg_ptr,this),this}offset(){return s.clientcore_offset(this.__wbg_ptr)}push_frame(e,t){const r=R(e,s.__wbindgen_malloc),a=l;return s.clientcore_push_frame(this.__wbg_ptr,r,a,t)!==0}reset(){s.clientcore_reset(this.__wbg_ptr)}resync(){s.clientcore_resync(this.__wbg_ptr)}sample(e){return s.clientcore_sample(this.__wbg_ptr,e)>>>0}set_active(e){s.clientcore_set_active(this.__wbg_ptr,e)}set_map(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=l,a=s.clientcore_set_map(this.__wbg_ptr,t,r);if(a[1])throw m(a[0])}set_model(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=l;s.clientcore_set_model(this.__wbg_ptr,t,r)}sync_panel(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=l;s.clientcore_sync_panel(this.__wbg_ptr,t,r)}take_divergence(){let e,t;try{const r=s.clientcore_take_divergence(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}take_frames(){let e,t;try{const r=s.clientcore_take_frames(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(E.prototype[Symbol.dispose]=E.prototype.free);class T{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,D.unregister(this),e}free(){const e=this.__destroy_into_raw();s.__wbg_gamecore_free(e,0)}alive_players(){const e=s.gamecore_alive_players(this.__wbg_ptr);var t=P(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*4,4),t}apply_aim(e,t,r,a,o){s.gamecore_apply_aim(this.__wbg_ptr,e,t,r,a,o)}apply_input(e,t,r,a){const o=d(r,s.__wbindgen_malloc,s.__wbindgen_realloc),i=l,_=d(a,s.__wbindgen_malloc,s.__wbindgen_realloc),c=l;s.gamecore_apply_input(this.__wbg_ptr,e,t,o,i,_,c)}body_has_events(){return s.gamecore_body_has_events(this.__wbg_ptr)!==0}clear(){s.gamecore_clear(this.__wbg_ptr)}debug_json(){let e,t;try{const r=s.gamecore_debug_json(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}deserialize_state(e){const t=R(e,s.__wbindgen_malloc),r=l,a=s.gamecore_deserialize_state(this.__wbg_ptr,t,r);if(a[1])throw m(a[0])}frame_bytes(){const e=s.gamecore_frame_bytes(this.__wbg_ptr);var t=F(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}frame_ptr(){return s.gamecore_frame_ptr(this.__wbg_ptr)>>>0}is_alive(e){return s.gamecore_is_alive(this.__wbg_ptr,e)!==0}last_input_seq(e){return s.gamecore_last_input_seq(this.__wbg_ptr,e)>>>0}load_map(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=l,a=s.gamecore_load_map(this.__wbg_ptr,t,r);if(a[1])throw m(a[0])}map_info(){let e,t;try{const r=s.gamecore_map_info(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}constructor(e){const t=d(e,s.__wbindgen_malloc,s.__wbindgen_realloc),r=l,a=s.gamecore_new(t,r);if(a[2])throw m(a[1]);return this.__wbg_ptr=a[0],D.register(this,this.__wbg_ptr,this),this}pack_body(){const e=s.gamecore_pack_body(this.__wbg_ptr);if(e[1])throw m(e[0])}pack_frame(e,t,r,a,o,i,_,c){var p=Ce(_)?0:d(_,s.__wbindgen_malloc,s.__wbindgen_realloc),h=l;return s.gamecore_pack_frame(this.__wbg_ptr,e,t,r,a,o,i,p,h,c)>>>0}players_data(){let e,t;try{const r=s.gamecore_players_data(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}position_of(e){const t=s.gamecore_position_of(this.__wbg_ptr,e);var r=P(t[0],t[1]).slice();return s.__wbindgen_free(t[0],t[1]*4,4),r}remove_actor(e){s.gamecore_remove_actor(this.__wbg_ptr,e)}remove_players_and_shots(){let e,t;try{const r=s.gamecore_remove_players_and_shots(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}remove_scripted_actor(e){s.gamecore_remove_scripted_actor(this.__wbg_ptr,e)}reset_actor(e,t,r,a,o){s.gamecore_reset_actor(this.__wbg_ptr,e,t,r,a,o)}reset_all_vitals(){s.gamecore_reset_all_vitals(this.__wbg_ptr)}serialize_state(){const e=s.gamecore_serialize_state(this.__wbg_ptr);if(e[3])throw m(e[2]);var t=F(e[0],e[1]).slice();return s.__wbindgen_free(e[0],e[1]*1,1),t}spawn_actor(e,t,r,a,o,i){const _=d(t,s.__wbindgen_malloc,s.__wbindgen_realloc),c=l,p=s.gamecore_spawn_actor(this.__wbg_ptr,e,_,c,r,a,o,i);if(p[1])throw m(p[0])}spawn_scripted_actor(e,t,r,a,o,i){const _=d(t,s.__wbindgen_malloc,s.__wbindgen_realloc),c=l,p=s.gamecore_spawn_scripted_actor(this.__wbg_ptr,e,_,c,r,a,o,i);if(p[1])throw m(p[0])}step(e){s.gamecore_step(this.__wbg_ptr,e)}take_events(){let e,t;try{const r=s.gamecore_take_events(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(T.prototype[Symbol.dispose]=T.prototype.free);function W(){return{__proto__:null,"./vimp_snakes_core_bg.js":{__proto__:null,__wbg_Error_408e67f47ca7b58b:function(e,t){return Error(u(e,t))},__wbg___wbindgen_throw_bb96b2010945f0bc:function(e,t){throw new Error(u(e,t))},__wbindgen_init_externref_table:function(){const e=s.__wbindgen_externrefs,t=e.grow(4);e.set(0,void 0),e.set(t+0,void 0),e.set(t+1,null),e.set(t+2,!0),e.set(t+3,!1)}}}}const z=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(n=>s.__wbg_clientcore_free(n,1)),D=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(n=>s.__wbg_gamecore_free(n,1));function P(n,e){return n=n>>>0,Me().subarray(n/4,n/4+e)}function F(n,e){return n=n>>>0,y().subarray(n/1,n/1+e)}let b=null;function Me(){return(b===null||b.byteLength===0)&&(b=new Float32Array(s.memory.buffer)),b}function u(n,e){return Ee(n>>>0,e)}let w=null;function y(){return(w===null||w.byteLength===0)&&(w=new Uint8Array(s.memory.buffer)),w}function Ce(n){return n==null}function R(n,e){const t=e(n.length*1,1)>>>0;return y().set(n,t/1),l=n.length,t}function d(n,e,t){if(t===void 0){const _=v.encode(n),c=e(_.length,1)>>>0;return y().subarray(c,c+_.length).set(_),l=_.length,c}let r=n.length,a=e(r,1)>>>0;const o=y();let i=0;for(;i<r;i++){const _=n.charCodeAt(i);if(_>127)break;o[a+i]=_}if(i!==r){i!==0&&(n=n.slice(i)),a=t(a,r,r=i+n.length*3,1)>>>0;const _=y().subarray(a+i,a+r),c=v.encodeInto(n,_);i+=c.written,a=t(a,r,i,1)>>>0}return l=i,a}function m(n){const e=s.__wbindgen_externrefs.get(n);return s.__externref_table_dealloc(n),e}let S=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});S.decode();const Ae=2146435072;let k=0;function Ee(n,e){return k+=e,k>=Ae&&(S=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),S.decode(),k=e),S.decode(y().subarray(n,n+e))}const v=new TextEncoder;"encodeInto"in v||(v.encodeInto=function(n,e){const t=v.encode(n);return e.set(t),{read:n.length,written:t.length}});let l=0,s;function j(n,e){return s=n.exports,b=null,w=null,s.__wbindgen_start(),s}async function Te(n,e){if(typeof Response=="function"&&n instanceof Response){if(!n.ok)throw new Error(`failed to fetch Wasm: ${n.status} ${n.statusText} fetching '${n.url}'`);if(typeof WebAssembly.instantiateStreaming=="function")try{return await WebAssembly.instantiateStreaming(n,e)}catch(a){if(t(n.type)&&n.headers.get("Content-Type")!=="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",a);else throw a}const r=await n.arrayBuffer();return await WebAssembly.instantiate(r,e)}else{const r=await WebAssembly.instantiate(n,e);return r instanceof WebAssembly.Instance?{instance:r,module:n}:r}function t(r){switch(r){case"basic":case"cors":case"default":return!0}return!1}}function Pe(n){if(s!==void 0)return s;n!==void 0&&(Object.getPrototypeOf(n)===Object.prototype?{module:n}=n:console.warn("using deprecated parameters for `initSync()`; pass a single object instead"));const e=W();n instanceof WebAssembly.Module||(n=new WebAssembly.Module(n));const t=new WebAssembly.Instance(n,e);return j(t)}async function Re(n){if(s!==void 0)return s;n!==void 0&&(Object.getPrototypeOf(n)===Object.prototype?{module_or_path:n}=n:console.warn("using deprecated parameters for the initialization function; pass a single object instead")),n===void 0&&(n=new URL("/assets/vimp_snakes_core_bg-3ggUM5Py.wasm",import.meta.url));const e=W();(typeof n=="string"||typeof Request=="function"&&n instanceof Request||typeof URL=="function"&&n instanceof URL)&&(n=fetch(n));const{instance:t,module:r}=await Te(await n,e);return j(t)}const Ie=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:E,GameCore:T,default:Re,initSync:Pe},Symbol.toStringTag,{value:"Module"}));export{Ne as default};