@vimp-games/snakes 0.7.4 → 0.7.6

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
@@ -25,8 +25,11 @@ typing a message never steers the snake.
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
35
  One number follows you and a crash does not reset it: **score** — the crystals
@@ -37,17 +40,20 @@ the score alone; what you are carrying right now is told by the size of your
37
40
  snake. A kill is also worth a point of **rank**, the number `/rank` reports and
38
41
  the one that survives the session.
39
42
 
40
- The first two seconds of a life are yours: a fresh snake stands still and
41
- blinks, kills nobody and cannot be killed. Long enough to read the arena, and
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
42
46
  long enough for whoever was flying at that spot to steer around you.
43
47
 
44
48
  The heavier you get the wider you steer: 3.4 rad/s empty, falling with the
45
49
  square root of the crystals down to a floor of 1.4. A leader stays steerable
46
50
  and stops being nimble — the fastest snake in the arena is a small one.
47
51
 
48
- The stat table (`Tab`) is a single leaderboard ranked by score, ties broken by
49
- rank. Everyone is a player: there are no teams, no spectators and nothing to
50
- vote on.
52
+ One life is one game: the score of a crashed life is its result, and `Tab`
53
+ shows the game's global daily top ten the best single game of the day
54
+ across every server — rather than this room. The top ten of the day wears a
55
+ diamond pattern down the body, the top ten of the month a crown. Everyone is a
56
+ player: there are no teams, no spectators and nothing to vote on.
51
57
 
52
58
  ## Run it
53
59
 
@@ -187,6 +193,23 @@ ready-made placeholders in `assets/sounds/`: when `build/sounds/` is absent,
187
193
  on a bare machine. The two cues are `pickup` and `death`, both played
188
194
  positionally by `src/client/parts/Snake.js`.
189
195
 
196
+ ## Documentation
197
+
198
+ Full documentation lives in [docs/en/](docs/en/README.md):
199
+
200
+ - [Local setup](docs/en/getting-started.md)
201
+ - [Architecture](docs/en/architecture.md)
202
+ - [Gameplay](docs/en/gameplay.md)
203
+ - [Rust core](docs/en/core.md)
204
+ - [Configuration](docs/en/configuration.md)
205
+ - [Extending the game (models, tiers, sounds, parts)](docs/en/extending.md)
206
+
207
+ [Русская версия](docs/ru/README.md)
208
+
209
+ For engine-side concepts (transport, master server, plugin contract), see the
210
+ engine's own docs:
211
+ [vimp-engine/docs/en/](https://github.com/lgick/vimp-engine/blob/main/docs/en/README.md).
212
+
190
213
  ## Engine
191
214
 
192
215
  The engine versions this game builds against are the pins themselves —
@@ -0,0 +1,8 @@
1
+ import{Container as q,Graphics as M,Sprite as ie,Rectangle as ce}from"pixi.js";const de=4,fe='#panel-score:before{content:"★ ";color:#ffd76b}#panel-crystals,#panel-dead,#panel-mode,#panel-time{display:none!important}#stat .stat-leaderboard{padding:12px 0;font:400 16px/1.6 system-ui,sans-serif;color:#e6ecf5}#stat .stat-leaderboard .stat-row{grid-template-columns:3.5em 1fr 5.5em;gap:0 12px;padding:4px 16px;border-radius:6px}#stat .stat-leaderboard .stat-row span:first-child,#stat .stat-leaderboard .stat-row span:last-child{font-variant-numeric:tabular-nums;text-align:right}#stat .stat-leaderboard .stat-row span:first-child{opacity:.6}#stat .stat-leaderboard .stat-row span:last-child{font-weight:700;color:#ffd76b}#stat .stat-leaderboard .stat-row span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#stat .stat-leaderboard .is-self{background:#3ab7ff2e;color:#7ef9ff}#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}',pe={background:856608,floor:1317936,edge:3756159,edgeWidth:10,rings:4,ringColor:1911111},m={innerScale:.62,innerDarken:.55,smoothing:4,eye:16251903,pupil:1054760,boostGlow:16771466,accolade:{diamondEvery:1.6,diamondLong:.9,diamondWide:.55,diamondLighten:.55,crownScale:1.9,crownLift:.44,crownTint:16766827}},he=.5;class ue extends q{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:u,rings:y,ringColor:T}=pe,b=new M;b.rect(-a,-i,a*3,i*3),b.fill(d),b.circle(_,l,c),b.fill(f);for(let E=1;E<y;E+=1)b.circle(_,l,c*E/y),b.stroke({color:T,width:2,alpha:he});b.circle(_,l,c),b.stroke({color:p,width:u,alignment:1}),this.addChild(b)}update(){}destroy(){super.destroy({children:!0})}}const V=[16731469,16752412,16765503,10214972,3065014,3848191,5531903,11623679,16735432,16250871,8250065,16753828],X=[8321535,10146047,13154047,12386267,16771466,16757702],Z=[{value:1,radius:8},{value:3,radius:13},{value:8,radius:20}],ae=16,k=ae*2,C={ANGLE:k,RADIUS:k+1,CRYSTALS:k+2,COLOR:k+3,FLAGS:k+4},ge=1,be=2,we=4,J=.25,ye=.85;function me(r){const e=(Math.sin(r/1e3*we*Math.PI*2)+1)/2;return J+(ye-J)*e}function Q(r){return r!=null}function xe(r,e){const t=i=>Math.round(i+(255-i)*e),n=t(r>>16&255),o=t(r>>8&255),a=t(r&255);return n<<16|o<<8|a}function ve(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 Ae(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 Se extends q{constructor(e,t={},n={},o={}){super(),this.zIndex=3,this._sound=n.soundManager,this._localPlayer=n.localPlayer,this._id=o.id??null,this._accolades=n.accolades,this._body=new M,this._head=new M,this.addChild(this._body,this._head),this._crown=t?.crown?this._buildCrown(t.crown):null,this._headAt=[0,0],this._crystals=null,this.update(e)}update(e){const t=e[C.RADIUS]||1,n=e[C.ANGLE]||0,o=e[C.CRYSTALS]||0,a=e[C.FLAGS]||0,i=(a&ge)!==0,c=(a&be)!==0,_=V[(e[C.COLOR]||0)%V.length],l=[];for(let p=0;p<ae;p+=1)l.push([e[p*2]||0,e[p*2+1]||0]);this.alpha=c?me(performance.now()):1;const{daily:d,monthly:f}=this._accolades?.placeOf(this._id)??{};this._drawBody(l,t,_,i,Q(d)),this._drawHead(l[0],n,t,_),this._drawCrown(l[0],n,t,Q(f)),this._crystals!==null&&o>this._crystals&&this._play("pickup",l[0]),this._crystals=o,this._headAt=l[0]}_drawBody(e,t,n,o,a){const i=Ae(e,m.smoothing),c=this._body;c.clear(),c.moveTo(i[0][0],i[0][1]);for(let _=1;_<i.length;_+=1)c.lineTo(i[_][0],i[_][1]);o&&c.stroke({color:m.boostGlow,width:t*2.6,alpha:.22,cap:"round",join:"round"}),c.stroke({color:n,width:t*2,cap:"round",join:"round"}),c.stroke({color:ve(n,m.innerDarken),width:t*2*m.innerScale,alpha:.45,cap:"round",join:"round"}),a&&this._drawDiamonds(i,t,n)}_drawDiamonds(e,t,n){const{diamondEvery:o,diamondLong:a,diamondWide:i,diamondLighten:c}=m.accolade,_=this._body,l=t*o,d=t*a,f=t*i;let p=l*.5;for(let u=1;u<e.length;u+=1){const[y,T]=e[u-1],[b,E]=e[u],j=b-y,G=E-T,v=Math.hypot(j,G);if(v!==0){for(;p<=v;){const H=p/v,P=y+j*H,I=T+G*H,W=j/v,N=G/v;_.moveTo(P+W*d,I+N*d),_.lineTo(P-N*f,I+W*f),_.lineTo(P-W*d,I-N*d),_.lineTo(P+N*f,I-W*f),_.fill(xe(n,c)),p+=l}p-=v}}}_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 u=e+c*d-_*l*p,y=t+_*d+c*l*p;i.circle(u,y,f),i.fill(m.eye),i.circle(u+c*f*.35,y+_*f*.35,f*.5),i.fill(m.pupil)}}_buildCrown(e){const t=new ie(e);return t.anchor.set(.5,1),t.tint=m.accolade.crownTint,t.visible=!1,this.addChild(t),t}_drawCrown([e,t],n,o,a){if(!this._crown||(this._crown.visible=a,!a))return;const{crownScale:i,crownLift:c}=m.accolade,_=o*i;this._crown.scale.set(_/this._crown.texture.width),this._crown.rotation=n+Math.PI/2,this._crown.x=e+Math.cos(n)*o*c,this._crown.y=t+Math.sin(n)*o*c}_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 z={X:0,Y:1,TIER:2,COLOR:3},Ee=32;class ke extends q{constructor(e,t){super(),this.zIndex=2,this._sprite=new ie(t.crystalGem),this._sprite.anchor.set(.5),this.addChild(this._sprite),this.update(e)}update(e){this.x=e[z.X]||0,this.y=e[z.Y]||0;const t=Z[e[z.TIER]||0]??Z[0];this._sprite.scale.set(t.radius/Ee),this._sprite.tint=X[(e[z.COLOR]||0)%X.length],this._sprite.rotation=(this.x+this.y)%360*(Math.PI/180)}destroy(){super.destroy({children:!0})}}const Ce={Arena:ue,Snake:Se,Crystal:ke};function Le(r,e){const{radius:t,facets:n}=r,o=t*2,a=new M,i=(d,f,p=0)=>{const u=(f+p)/n*Math.PI*2-Math.PI/2;return[t+Math.cos(u)*d,t+Math.sin(u)*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 ce(0,0,o,o)});return a.destroy(!0),l}function Re(r,e){const{size:t,points:n}=r,o=new M,a=t*.26,i=t*.08,c=t-a,_=t/n,l=[0,c];for(let f=0;f<n;f+=1){const p=(n-1)/2,u=Math.abs(f-p)/(p||1)*t*.18;l.push(f*_,i+u),l.push((f+.5)*_,c*.55)}l.push(t,i+t*.18,t,c),o.poly(l),o.fill({color:16777215,alpha:.92}),o.rect(0,c,t,a),o.fill({color:16777215,alpha:1});const d=e.generateTexture({target:o,frame:new ce(0,0,t,t)});return o.destroy(!0),d}const Oe={crystalGem:Le,crown:Re},A="snakes-gameover",Me=82,ee="d",te="s";function Te(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 Pe(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 Ie{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=A,e.hidden=!0,e.innerHTML=`
2
+ <div class="${A}-card">
3
+ <h2>You crashed</h2>
4
+ <p class="${A}-score"><span>0</span> crystals</p>
5
+ <p class="${A}-total">Total score: <span>0</span></p>
6
+ <button type="button">OK</button>
7
+ </div>
8
+ `,this._crystals=e.querySelector(`.${A}-score span`),this._total=e.querySelector(`.${A}-total span`),e.querySelector("button").addEventListener("click",()=>this._respawn()),document.body.appendChild(e),this._root=e}onPanel(e){if(!this._root)return;const t=Pe(e);if(te in t&&(this._lastScore=t[te]),!(ee in t))return;const n=t[ee];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"])Te(e,Me)}}const We="modulepreload",Ne=function(r){return"/"+r},ne={},ze=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=Ne(l),l in ne)return;ne[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((u,y)=>{p.addEventListener("load",u),p.addEventListener("error",()=>y(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)})},Fe=r=>(r??"").endsWith(".js"),je=r=>import(r),Ge=()=>ze(()=>Promise.resolve().then(()=>He),[]),D=new Ie,Xe={id:"snakes",engineApi:de,async createClientCore(r,{wasmUrl:e}={}){if(Fe(e)){const a=await je(e);return{core:new a.ClientCore(r),memory:null}}const{default:t,ClientCore:n}=await Ge(),o=await t({module_or_path:e});return{core:new n(r),memory:o.memory}},parts:Ce,bakers:Oe,styles:fe,hooks:{onAuth(r,e){r.set_model(e.model),D.mount(),D.reset()},onPanel(r,e){r.sync_panel(JSON.stringify(e)),D.onPanel(e)},onLocalAction(){return null}}};class ${__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,re.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=g(e,s.__wbindgen_malloc,s.__wbindgen_realloc),a=h,i=g(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],w(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}decode_frame(e){let t,n;try{const o=K(e,s.__wbindgen_malloc),a=h,i=s.clientcore_decode_frame(this.__wbg_ptr,o,a);return t=i[0],n=i[1],w(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=U(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=g(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.clientcore_new(t,n);if(o[2])throw x(o[1]);return this.__wbg_ptr=o[0],re.register(this,this.__wbg_ptr,this),this}offset(){return s.clientcore_offset(this.__wbg_ptr)}push_frame(e,t){const n=K(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=g(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.clientcore_set_map(this.__wbg_ptr,t,n);if(o[1])throw x(o[0])}set_model(e){const t=g(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h;s.clientcore_set_model(this.__wbg_ptr,t,n)}sync_panel(e){const t=g(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],w(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],w(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&($.prototype[Symbol.dispose]=$.prototype.free);class B{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,se.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=U(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=g(n,s.__wbindgen_malloc,s.__wbindgen_realloc),i=h,c=g(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],w(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}deserialize_state(e){const t=K(e,s.__wbindgen_malloc),n=h,o=s.gamecore_deserialize_state(this.__wbg_ptr,t,n);if(o[1])throw x(o[0])}frame_bytes(){const e=s.gamecore_frame_bytes(this.__wbg_ptr);var t=oe(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=g(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.gamecore_load_map(this.__wbg_ptr,t,n);if(o[1])throw x(o[0])}map_info(){let e,t;try{const n=s.gamecore_map_info(this.__wbg_ptr);return e=n[0],t=n[1],w(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}constructor(e){const t=g(e,s.__wbindgen_malloc,s.__wbindgen_realloc),n=h,o=s.gamecore_new(t,n);if(o[2])throw x(o[1]);return this.__wbg_ptr=o[0],se.register(this,this.__wbg_ptr,this),this}pack_body(){const e=s.gamecore_pack_body(this.__wbg_ptr);if(e[1])throw x(e[0])}pack_frame(e,t,n,o,a,i,c,_){var l=Ye(c)?0:g(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],w(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=U(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],w(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 x(e[2]);var t=oe(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=g(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 x(l[0])}spawn_scripted_actor(e,t,n,o,a,i){const c=g(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 x(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],w(n[0],n[1])}finally{s.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(B.prototype[Symbol.dispose]=B.prototype.free);function _e(){return{__proto__:null,"./vimp_snakes_core_bg.js":{__proto__:null,__wbg_Error_408e67f47ca7b58b:function(e,t){return Error(w(e,t))},__wbg___wbindgen_throw_bb96b2010945f0bc:function(e,t){throw new Error(w(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 re=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(r=>s.__wbg_clientcore_free(r,1)),se=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(r=>s.__wbg_gamecore_free(r,1));function U(r,e){return r=r>>>0,De().subarray(r/4,r/4+e)}function oe(r,e){return r=r>>>0,S().subarray(r/1,r/1+e)}let L=null;function De(){return(L===null||L.byteLength===0)&&(L=new Float32Array(s.memory.buffer)),L}function w(r,e){return Be(r>>>0,e)}let R=null;function S(){return(R===null||R.byteLength===0)&&(R=new Uint8Array(s.memory.buffer)),R}function Ye(r){return r==null}function K(r,e){const t=e(r.length*1,1)>>>0;return S().set(r,t/1),h=r.length,t}function g(r,e,t){if(t===void 0){const c=O.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),_=O.encodeInto(r,c);i+=_.written,o=t(o,n,i,1)>>>0}return h=i,o}function x(r){const e=s.__wbindgen_externrefs.get(r);return s.__externref_table_dealloc(r),e}let F=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});F.decode();const $e=2146435072;let Y=0;function Be(r,e){return Y+=e,Y>=$e&&(F=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),F.decode(),Y=e),F.decode(S().subarray(r,r+e))}const O=new TextEncoder;"encodeInto"in O||(O.encodeInto=function(r,e){const t=O.encode(r);return e.set(t),{read:r.length,written:t.length}});let h=0,s;function le(r,e){return s=r.exports,L=null,R=null,s.__wbindgen_start(),s}async function Ue(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 Ke(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=_e();r instanceof WebAssembly.Module||(r=new WebAssembly.Module(r));const t=new WebAssembly.Instance(r,e);return le(t)}async function qe(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-C5At6odT.wasm",import.meta.url));const e=_e();(typeof r=="string"||typeof Request=="function"&&r instanceof Request||typeof URL=="function"&&r instanceof URL)&&(r=fetch(r));const{instance:t,module:n}=await Ue(await r,e);return le(t)}const He=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:$,GameCore:B,default:qe,initSync:Ke},Symbol.toStringTag,{value:"Module"}));export{Xe 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(),H={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}}},Z={},F=128,I=1,Q=20,D=8,E=4,k=64,J=Math.PI*(3-Math.sqrt(5)),ee=.72,te=25;function C(n){const e=Math.ceil(Math.max(n,0)/E)*E,t=Math.max(e,D);return Math.round(Q*Math.sqrt(t/D))}const W=Math.log2(k);if(!Number.isInteger(W))throw new Error(`RESPAWN_COUNT must be a power of two (the order is bit-reversed), got ${k}`);function re(n){let e=0;for(let t=0;t<W;t+=1)e=e<<1|n>>t&1;return e}function ne(n){const e=n*F/2,t=e;return Array.from({length:k},(r,s)=>{const i=re(s),o=e*ee*Math.sqrt((i+.5)/k),c=i*J,l=t+Math.cos(c)*o,_=t+Math.sin(c)*o,h=(s*.6180339887%1*2-1)*te,m=c*180/Math.PI+180+h;return[Math.round(l),Math.round(_),Math.round((m%360+360)%360)]})}function L(n=0){const e=C(n);return{setId:"c1",scale:1,step:F,physicsStatic:[],physicsDynamic:[],layers:{1:[I]},map:Array.from({length:e},()=>Array.from({length:e},()=>I)),respawns:{players:ne(e)}}}const se=L(0),ae={arena:se},ie={title:"Vimp Snakes",parts:{models:A,weapons:Z,friendlyFire:!1},snapshot:H,soundCues:{roundStart:null,victory:null,defeat:null,frag:null,death:null},maps:ae,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,statMode:"leaderboard",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:""},score:{key:2,bodyMethod:"=",bodyValue:0,headMethod:"+",headValue:0},latency:{key:3,bodyMethod:"="}},roomDefaults:{maxPlayers:32},roomForm:[{name:"maxPlayers",control:"text",label:"Max players",numeric:!0},{name:"map",control:"select",label:"Map",source:"maps"}]},oe={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}},_e={codecList:["webm","mp3"],sounds:ce},le={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}},{name:"crown",component:"Snake",params:{size:64,points:3}}]},componentDependencies:{soundManager:["Snake"],localPlayer:["Snake"],accolades:["Snake"]},sounds:_e},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 place today: {0} of {1} ({2} points)"],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:{mode:"leaderboard",period:"day",limit:10,columns:["#","snake","score"]}}},gameInform:{list:["{0} WINS!","SLITHER!","GAME OVER!"]}};class pe{constructor({participants:e,coreAdapter:t,socketManager:r},s){this._participants=e,this._coreAdapter=t,this._socketManager=r,this._scriptedManager=s,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=L(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 C(e);const t=C(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 de{constructor({participants:e,coreAdapter:t,panel:r,stat:s,scripted:i}){this._participants=e,this._coreAdapter=t,this._panel=r,this._stat=s,this._model=i.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 s=0;for(let i=0;i<e&&!this._participants.isFull;i+=1){const o=t??this._pickTeam(r);if(!o||!this._hasRoom(o))break;const c=this._participants.createScripted({team:o,model:this._model}),l=this._participants.get(c);this._stat.addUser(c,l.teamId,{name:l.name,status:"",latency:"BOT"}),this._panel.addUser(c),s+=1}return s}_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(s=>s.team===e):t).forEach(s=>this._remove(s.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 ue=15;class he{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:s}=t,i=String(e.id);switch(e.type){case"crystals":this._onCrystals(i,Number(e.gained)||0,r,s);break;case"burn":this._onBurn(i,Number(e.burned)||0,r,s);break;case"death":this._onDeath(i,e,r,s);break;case"respawn":this._onRespawn(i,r,s);break;case"population":this._publishNewcomers(r,s),r?.flushPlayerData?.();break}}reset(e){this._totals.delete(e)}_onCrystals(e,t,r,s){const i=this._record(e);!i||t<=0||(i.eaten+=t,i.score+=t,this._publish(e,i,r,s))}_onBurn(e,t,r,s){const i=this._record(e);!i||t<=0||(i.score=Math.max(0,i.score-t),this._publish(e,i,r,s))}_onDeath(e,t,r,s){const i=this._record(e);if(!i)return;const o=t.killer===null||t.killer===void 0?null:String(t.killer);if(o!==null&&o!==e){const _=this._record(o);_&&(_.kills+=1,_.score+=ue,this._publish(o,_,r,s))}this._publish(e,i,r,s);const l=r?.isPlayerRatingLoaded?.(e,"day")===!0?r.getPlayerRating?.(e,"day")?.value??0:1/0;r?.addPlayerPoints?.(e,i.score),r?.finishPlayerGame?.(e),this._recordBest(e,i,r),r?.flushPlayerData?.({urgent:i.score>l})}_onRespawn(e,t,r){const s=this._record(e);s&&(s.eaten=0,s.kills=0,s.score=0,s.flushedEaten=0,this._publish(e,s,t,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 s={participant:t,eaten:0,kills:0,score:0,flushedEaten:0,published:!1};return this._totals.set(e,s),s}_publishNewcomers(e,t){for(const r of this._participants.getAll()){const s=r.gameId,i=this._totals.get(s),o=i?.participant===r?i:this._record(s);o&&!o.published&&this._publish(s,o,e,t)}}_publish(e,t,r,s){const{score:i}=t;t.published=!0,this._stat.updateUser(e,t.participant.teamId,{score:i}),s&&s.updateUser(e,"score",i,"set")}_recordBest(e,t,r){if(!r?.getPlayerState)return;const s=r.getPlayerState(e);if(!s)return;const i=t.eaten-t.flushedEaten;t.flushedEaten=t.eaten;const o=Math.max(Number(s.best)||0,t.score),c=(Number(s.eaten)||0)+i;r.setPlayerState(e,{...s,best:o,eaten:c})}}let U=null,j=null;function fe(n){const e=new de(n);return U=new he(n),j=new pe(n,e),{scripted:e}}function me(){return U}function V(){return j}const ge={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:s}=n.participants,i=Math.trunc(r),o=s>0?Math.min(i,s):i;n.scripted.removeScripted();const c=o>0?n.scripted.createScripted(o):0;n.chat.pushSystem("BOTS_SET",[c]),c>0&&(n.roundManager.initiateNewRound(),V()?.reapply())}},ye={name:"/name",handler(n,e,t){n.roundManager.changeName(e,t.join(" "))}},be={name:"/nr",handler(n,e){n.isDevMode?n.roundManager.initiateNewRound():n.chat.pushSystemByUser(e,"COMMANDS_NOT_FOUND")}},we={name:"/rank",async handler(n,e){let t=null;try{t=await n.playerDataSync?.refreshPlacement?.(e,"day")}catch{t=n.playerDataSync?.getRating?.(e,"day")??null}const{value:r=0,placement:s=null,total:i=0}=t??{};n.chat.pushSystemByUser(e,"RANK",[s??"—",i,r])}},ve={BOTS_SET:"g:0",BOT_COUNT_INVALID:"g:1"},Se="modulepreload",ke=function(n){return"/"+n},O={},Me=function(e,t,r){let s=Promise.resolve();if(t&&t.length>0){let l=function(_){return Promise.all(_.map(h=>Promise.resolve(h).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),c=o?.nonce||o?.getAttribute("nonce");s=l(t.map(_=>{if(_=ke(_),_ in O)return;O[_]=!0;const h=_.endsWith(".css"),m=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${_}"]${m}`))return;const g=document.createElement("link");if(g.rel=h?"stylesheet":Se,h||(g.as="script"),g.crossOrigin="",g.href=_,c&&g.setAttribute("nonce",c),document.head.appendChild(g),h)return new Promise((Y,$)=>{g.addEventListener("load",Y),g.addEventListener("error",()=>$(new Error(`Unable to preload CSS for ${_}`)))})}))}function i(o){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=o,window.dispatchEvent(c),!c.defaultPrevented)throw o}return s.then(o=>{for(const c of o||[])c.status==="rejected"&&i(c.reason);return e().catch(i)})},Ae=n=>(n??"").endsWith(".js"),Ee=n=>import(n),Ce=()=>Me(()=>Promise.resolve().then(()=>xe),[]),ze={id:"snakes",engineApi:4,async createCore(n,{wasmUrl:e}={}){if(Ae(e)){const s=await Ee(e);return new s.GameCore(n)}const{default:t,GameCore:r}=await Ce();return await t({module_or_path:e}),new r(n)},gameConfig:ie,authSchema:oe,chatCommands:[ge,ye,be,we],systemMessages:ve,createModules:fe,buildClientGameConfig:()=>le,onCoreEvent(n,e={}){me()?.onCoreEvent(n,e),V()?.onCoreEvent(n,e)}};class T{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,x.unregister(this),e}free(){const e=this.__destroy_into_raw();a.__wbg_clientcore_free(e,0)}apply_aim(e,t,r,s){a.clientcore_apply_aim(this.__wbg_ptr,e,t,r,s)}apply_input(e,t,r){const s=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),i=p,o=d(t,a.__wbindgen_malloc,a.__wbindgen_realloc),c=p;a.clientcore_apply_input(this.__wbg_ptr,s,i,o,c,r)}debug_json(){let e,t;try{const r=a.clientcore_debug_json(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}decode_frame(e){let t,r;try{const s=N(e,a.__wbindgen_malloc),i=p,o=a.clientcore_decode_frame(this.__wbg_ptr,s,i);return t=o[0],r=o[1],u(o[0],o[1])}finally{a.__wbindgen_free(t,r,1)}}hot_ptr(){return a.clientcore_hot_ptr(this.__wbg_ptr)>>>0}hot_values(){const e=a.clientcore_hot_values(this.__wbg_ptr);var t=R(e[0],e[1]).slice();return a.__wbindgen_free(e[0],e[1]*4,4),t}my_game_id(){return a.clientcore_my_game_id(this.__wbg_ptr)}constructor(e){const t=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),r=p,s=a.clientcore_new(t,r);if(s[2])throw f(s[1]);return this.__wbg_ptr=s[0],x.register(this,this.__wbg_ptr,this),this}offset(){return a.clientcore_offset(this.__wbg_ptr)}push_frame(e,t){const r=N(e,a.__wbindgen_malloc),s=p;return a.clientcore_push_frame(this.__wbg_ptr,r,s,t)!==0}reset(){a.clientcore_reset(this.__wbg_ptr)}resync(){a.clientcore_resync(this.__wbg_ptr)}sample(e){return a.clientcore_sample(this.__wbg_ptr,e)>>>0}set_active(e){a.clientcore_set_active(this.__wbg_ptr,e)}set_map(e){const t=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),r=p,s=a.clientcore_set_map(this.__wbg_ptr,t,r);if(s[1])throw f(s[0])}set_model(e){const t=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),r=p;a.clientcore_set_model(this.__wbg_ptr,t,r)}sync_panel(e){const t=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),r=p;a.clientcore_sync_panel(this.__wbg_ptr,t,r)}take_divergence(){let e,t;try{const r=a.clientcore_take_divergence(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}take_frames(){let e,t;try{const r=a.clientcore_take_frames(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(T.prototype[Symbol.dispose]=T.prototype.free);class P{__destroy_into_raw(){const e=this.__wbg_ptr;return this.__wbg_ptr=0,z.unregister(this),e}free(){const e=this.__destroy_into_raw();a.__wbg_gamecore_free(e,0)}alive_players(){const e=a.gamecore_alive_players(this.__wbg_ptr);var t=R(e[0],e[1]).slice();return a.__wbindgen_free(e[0],e[1]*4,4),t}apply_aim(e,t,r,s,i){a.gamecore_apply_aim(this.__wbg_ptr,e,t,r,s,i)}apply_input(e,t,r,s){const i=d(r,a.__wbindgen_malloc,a.__wbindgen_realloc),o=p,c=d(s,a.__wbindgen_malloc,a.__wbindgen_realloc),l=p;a.gamecore_apply_input(this.__wbg_ptr,e,t,i,o,c,l)}body_has_events(){return a.gamecore_body_has_events(this.__wbg_ptr)!==0}clear(){a.gamecore_clear(this.__wbg_ptr)}debug_json(){let e,t;try{const r=a.gamecore_debug_json(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}deserialize_state(e){const t=N(e,a.__wbindgen_malloc),r=p,s=a.gamecore_deserialize_state(this.__wbg_ptr,t,r);if(s[1])throw f(s[0])}frame_bytes(){const e=a.gamecore_frame_bytes(this.__wbg_ptr);var t=B(e[0],e[1]).slice();return a.__wbindgen_free(e[0],e[1]*1,1),t}frame_ptr(){return a.gamecore_frame_ptr(this.__wbg_ptr)>>>0}is_alive(e){return a.gamecore_is_alive(this.__wbg_ptr,e)!==0}last_input_seq(e){return a.gamecore_last_input_seq(this.__wbg_ptr,e)>>>0}load_map(e){const t=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),r=p,s=a.gamecore_load_map(this.__wbg_ptr,t,r);if(s[1])throw f(s[0])}map_info(){let e,t;try{const r=a.gamecore_map_info(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}constructor(e){const t=d(e,a.__wbindgen_malloc,a.__wbindgen_realloc),r=p,s=a.gamecore_new(t,r);if(s[2])throw f(s[1]);return this.__wbg_ptr=s[0],z.register(this,this.__wbg_ptr,this),this}pack_body(){const e=a.gamecore_pack_body(this.__wbg_ptr);if(e[1])throw f(e[0])}pack_frame(e,t,r,s,i,o,c,l){var _=Pe(c)?0:d(c,a.__wbindgen_malloc,a.__wbindgen_realloc),h=p;return a.gamecore_pack_frame(this.__wbg_ptr,e,t,r,s,i,o,_,h,l)>>>0}players_data(){let e,t;try{const r=a.gamecore_players_data(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}position_of(e){const t=a.gamecore_position_of(this.__wbg_ptr,e);var r=R(t[0],t[1]).slice();return a.__wbindgen_free(t[0],t[1]*4,4),r}remove_actor(e){a.gamecore_remove_actor(this.__wbg_ptr,e)}remove_players_and_shots(){let e,t;try{const r=a.gamecore_remove_players_and_shots(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}remove_scripted_actor(e){a.gamecore_remove_scripted_actor(this.__wbg_ptr,e)}reset_actor(e,t,r,s,i){a.gamecore_reset_actor(this.__wbg_ptr,e,t,r,s,i)}reset_all_vitals(){a.gamecore_reset_all_vitals(this.__wbg_ptr)}serialize_state(){const e=a.gamecore_serialize_state(this.__wbg_ptr);if(e[3])throw f(e[2]);var t=B(e[0],e[1]).slice();return a.__wbindgen_free(e[0],e[1]*1,1),t}spawn_actor(e,t,r,s,i,o){const c=d(t,a.__wbindgen_malloc,a.__wbindgen_realloc),l=p,_=a.gamecore_spawn_actor(this.__wbg_ptr,e,c,l,r,s,i,o);if(_[1])throw f(_[0])}spawn_scripted_actor(e,t,r,s,i,o){const c=d(t,a.__wbindgen_malloc,a.__wbindgen_realloc),l=p,_=a.gamecore_spawn_scripted_actor(this.__wbg_ptr,e,c,l,r,s,i,o);if(_[1])throw f(_[0])}step(e){a.gamecore_step(this.__wbg_ptr,e)}take_events(){let e,t;try{const r=a.gamecore_take_events(this.__wbg_ptr);return e=r[0],t=r[1],u(r[0],r[1])}finally{a.__wbindgen_free(e,t,1)}}}Symbol.dispose&&(P.prototype[Symbol.dispose]=P.prototype.free);function G(){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=a.__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=>a.__wbg_clientcore_free(n,1)),z=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(n=>a.__wbg_gamecore_free(n,1));function R(n,e){return n=n>>>0,Te().subarray(n/4,n/4+e)}function B(n,e){return n=n>>>0,y().subarray(n/1,n/1+e)}let b=null;function Te(){return(b===null||b.byteLength===0)&&(b=new Float32Array(a.memory.buffer)),b}function u(n,e){return Ne(n>>>0,e)}let w=null;function y(){return(w===null||w.byteLength===0)&&(w=new Uint8Array(a.memory.buffer)),w}function Pe(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 c=v.encode(n),l=e(c.length,1)>>>0;return y().subarray(l,l+c.length).set(c),p=c.length,l}let r=n.length,s=e(r,1)>>>0;const i=y();let o=0;for(;o<r;o++){const c=n.charCodeAt(o);if(c>127)break;i[s+o]=c}if(o!==r){o!==0&&(n=n.slice(o)),s=t(s,r,r=o+n.length*3,1)>>>0;const c=y().subarray(s+o,s+r),l=v.encodeInto(n,c);o+=l.written,s=t(s,r,o,1)>>>0}return p=o,s}function f(n){const e=a.__wbindgen_externrefs.get(n);return a.__externref_table_dealloc(n),e}let S=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});S.decode();const Re=2146435072;let M=0;function Ne(n,e){return M+=e,M>=Re&&(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,a;function q(n,e){return a=n.exports,b=null,w=null,a.__wbindgen_start(),a}async function Ie(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(s){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",s);else throw s}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 De(n){if(a!==void 0)return a;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=G();n instanceof WebAssembly.Module||(n=new WebAssembly.Module(n));const t=new WebAssembly.Instance(n,e);return q(t)}async function Oe(n){if(a!==void 0)return a;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-C5At6odT.wasm",import.meta.url));const e=G();(typeof n=="string"||typeof Request=="function"&&n instanceof Request||typeof URL=="function"&&n instanceof URL)&&(n=fetch(n));const{instance:t,module:r}=await Ie(await n,e);return q(t)}const xe=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:T,GameCore:P,default:Oe,initSync:De},Symbol.toStringTag,{value:"Module"}));export{ze as default};
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "id": "snakes",
3
- "engineApi": 3,
4
- "version": "490801a38480c59f",
3
+ "engineApi": 4,
4
+ "version": "846dc00984d276a8",
5
5
  "title": "Snakes",
6
6
  "entries": {
7
- "client": "/games/snakes/client-CS6xkddp.js",
8
- "host": "/games/snakes/host-DUSYeUSU.js",
9
- "wasm": "/games/snakes/assets/vimp_snakes_core_bg-D9Smhejf.wasm",
7
+ "client": "/games/snakes/client-Cgf_r1An.js",
8
+ "host": "/games/snakes/host-CXhs31HD.js",
9
+ "wasm": "/games/snakes/assets/vimp_snakes_core_bg-C5At6odT.wasm",
10
10
  "wasmNode": "./core-node/vimp_snakes_core.js"
11
11
  },
12
12
  "assetsBase": "/games/snakes/",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vimp-games/snakes",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
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.19.0",
49
+ "vimp-engine": "^0.21.0",
50
50
  "vite": "^7.1.11",
51
51
  "vitest": "^4.1.9"
52
52
  }
@@ -1,8 +0,0 @@
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(()=>je),[]),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=F(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=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=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=F(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=j(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=F(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=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,_){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 j(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 F(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-D9Smhejf.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 je=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:N,GameCore:W,default:We,initSync:Ne},Symbol.toStringTag,{value:"Module"}));export{ze as default};
@@ -1 +0,0 @@
1
- const H=Array.from({length:16},(n,e)=>[{name:`p${e}x`,ty:"f32",interp:"lerp"},{name:`p${e}y`,ty:"f32",interp:"lerp"}]).flat(),K={s1:{id:1,kind:"indexed8",class:"hot",fields:[...H,{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}}},Z={},L=128,I=1,Q=20,D=8,E=4,k=64,J=Math.PI*(3-Math.sqrt(5)),ee=.72,te=25;function C(n){const e=Math.ceil(Math.max(n,0)/E)*E,t=Math.max(e,D);return Math.round(Q*Math.sqrt(t/D))}const W=Math.log2(k);if(!Number.isInteger(W))throw new Error(`RESPAWN_COUNT must be a power of two (the order is bit-reversed), got ${k}`);function re(n){let e=0;for(let t=0;t<W;t+=1)e=e<<1|n>>t&1;return e}function ne(n){const e=n*L/2,t=e;return Array.from({length:k},(r,a)=>{const o=re(a),i=e*ee*Math.sqrt((o+.5)/k),_=o*J,c=t+Math.cos(_)*i,l=t+Math.sin(_)*i,h=(a*.6180339887%1*2-1)*te,f=_*180/Math.PI+180+h;return[Math.round(c),Math.round(l),Math.round((f%360+360)%360)]})}function B(n=0){const e=C(n);return{setId:"c1",scale:1,step:L,physicsStatic:[],physicsDynamic:[],layers:{1:[I]},map:Array.from({length:e},()=>Array.from({length:e},()=>I)),respawns:{players:ne(e)}}}const se=B(0),ae={arena:se},ie={title:"Vimp Snakes",parts:{models:A,weapons:Z,friendlyFire:!1},snapshot:K,soundCues:{roundStart:null,victory:null,defeat:null,frag:null,death:null},maps:ae,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"}]},oe={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}},_e={pickup:{file:"shot",priority:80,volume:.35},death:{file:"death",priority:150,volume:.5}},ce={codecList:["webm","mp3"],sounds:_e},le={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:ce},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:["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 pe{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=B(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 C(e);const t=C(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 de{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 ue=15;class he{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,r,a);break;case"death":this._onDeath(o,e,r,a);break;case"population":this._publishNewcomers(r,a);break}}reset(e){this._totals.delete(e)}_onCrystals(e,t,r,a){const o=this._record(e);!o||t<=0||(o.eaten+=t,o.score+=t,this._publish(e,o,r,a))}_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+=ue,r?.addPlayerRank?.(i,1),this._publish(i,_,r,a))}this._publish(e,o,r,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,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 U=null,j=null;function me(n){const e=new de(n);return U=new he(n),j=new pe(n,e),{scripted:e}}function fe(){return U}function V(){return j}const ge={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(),V()?.reapply())}},ye={name:"/name",handler(n,e,t){n.roundManager.changeName(e,t.join(" "))}},be={name:"/nr",handler(n,e){n.isDevMode?n.roundManager.initiateNewRound():n.chat.pushSystemByUser(e,"COMMANDS_NOT_FOUND")}},we={name:"/rank",handler(n,e){n.chat.pushSystemByUser(e,"RANK",[n.playerDataSync.getRank(e)])}},ve={BOTS_SET:"g:0",BOT_COUNT_INVALID:"g:1"},Se="modulepreload",ke=function(n){return"/"+n},O={},Me=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(f=>({status:"fulfilled",value:f}),f=>({status:"rejected",reason:f}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),_=i?.nonce||i?.getAttribute("nonce");a=c(t.map(l=>{if(l=ke(l),l in O)return;O[l]=!0;const h=l.endsWith(".css"),f=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${l}"]${f}`))return;const g=document.createElement("link");if(g.rel=h?"stylesheet":Se,h||(g.as="script"),g.crossOrigin="",g.href=l,_&&g.setAttribute("nonce",_),document.head.appendChild(g),h)return new Promise((Y,$)=>{g.addEventListener("load",Y),g.addEventListener("error",()=>$(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)})},Ae=n=>(n??"").endsWith(".js"),Ee=n=>import(n),Ce=()=>Me(()=>Promise.resolve().then(()=>xe),[]),ze={id:"snakes",engineApi:3,async createCore(n,{wasmUrl:e}={}){if(Ae(e)){const a=await Ee(e);return new a.GameCore(n)}const{default:t,GameCore:r}=await Ce();return await t({module_or_path:e}),new r(n)},gameConfig:ie,authSchema:oe,chatCommands:[ge,ye,be,we],systemMessages:ve,createModules:me,buildClientGameConfig:()=>le,onCoreEvent(n,e={}){fe()?.onCoreEvent(n,e),V()?.onCoreEvent(n,e)}};class T{__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=P(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=N(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 m(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=P(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 m(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&&(T.prototype[Symbol.dispose]=T.prototype.free);class R{__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_gamecore_free(e,0)}alive_players(){const e=s.gamecore_alive_players(this.__wbg_ptr);var t=N(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=P(e,s.__wbindgen_malloc),r=p,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=p,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=p,a=s.gamecore_new(t,r);if(a[2])throw m(a[1]);return this.__wbg_ptr=a[0],z.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 l=Re(_)?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=N(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=p,l=s.gamecore_spawn_actor(this.__wbg_ptr,e,_,c,r,a,o,i);if(l[1])throw m(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 m(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&&(R.prototype[Symbol.dispose]=R.prototype.free);function G(){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)),z=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(n=>s.__wbg_gamecore_free(n,1));function N(n,e){return n=n>>>0,Te().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 Te(){return(b===null||b.byteLength===0)&&(b=new Float32Array(s.memory.buffer)),b}function u(n,e){return Pe(n>>>0,e)}let w=null;function y(){return(w===null||w.byteLength===0)&&(w=new Uint8Array(s.memory.buffer)),w}function Re(n){return n==null}function P(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 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 Ne=2146435072;let M=0;function Pe(n,e){return M+=e,M>=Ne&&(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 Ie(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 De(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=G();n instanceof WebAssembly.Module||(n=new WebAssembly.Module(n));const t=new WebAssembly.Instance(n,e);return q(t)}async function Oe(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-D9Smhejf.wasm",import.meta.url));const e=G();(typeof n=="string"||typeof Request=="function"&&n instanceof Request||typeof URL=="function"&&n instanceof URL)&&(n=fetch(n));const{instance:t,module:r}=await Ie(await n,e);return q(t)}const xe=Object.freeze(Object.defineProperty({__proto__:null,ClientCore:T,GameCore:R,default:Oe,initSync:De},Symbol.toStringTag,{value:"Module"}));export{ze as default};