use instancing to improve performance

This commit is contained in:
Brian Beck 2026-03-14 23:04:25 -07:00
parent 78e791f763
commit cd2819d28a
33 changed files with 482 additions and 319 deletions

View file

@ -1 +1 @@
import{r as e}from"./chunk-DECur_0Z.js";import{r as t,t as n}from"./jsx-runtime-BpGWiA-R.js";import{i as r,o as i}from"./react-three-fiber.esm-CFJ5mGMW.js";import"./Html-CIkmciH6.js";import{a,i as o}from"./SettingsProvider-CZgYJ4FU.js";import{t as s}from"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Ht as c,c as l,yt as u}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{r as d}from"./engineStore-CLELjjpY.js";import{B as f,M as p,T as m}from"./index-DRuEJepN.js";var h=e(t(),1),g=n(),_=s(`AudioEmitter`),v=new Map,y=new Map;function b(e,t=1){y.set(e,t)}function x(e){y.delete(e)}var S=0;function C(){return S}function w(){S++;for(let[e]of y){try{e.stop()}catch{}try{e.disconnect()}catch{}}y.clear()}d.subscribe(e=>e.playback.rate,e=>{for(let[t,n]of y)try{t.setPlaybackRate(n*e)}catch{}});function T(e,t){let n=t(e),r=n?.filename;if(!r)return null;let i=r.endsWith(`.wav`)?r:`${r}.wav`,a=n.description,o=a==null?void 0:t(a);return{filename:i,is3D:o?.is3D??!0,isLooping:o?.isLooping??!1,refDist:o?.referenceDistance??20,maxDist:o?.maxDistance??100,volume:o?.volume??1}}function E(e,t,n,r,i){let a;try{a=p(e.filename)}catch{return}let o=d.getState().playback.rate,s=S;D(a,n,n=>{if(s===S)try{if(e.is3D&&i){let a=new u(t);a.setBuffer(n),a.setDistanceModel(`inverse`),a.setRefDistance(e.refDist),a.setMaxDistance(e.maxDist),a.setRolloffFactor(1),a.setVolume(e.volume),a.setPlaybackRate(o),r&&a.position.copy(r),i.add(a),y.set(a,1),a.play(),a.source.onended=()=>{y.delete(a);try{a.disconnect()}catch{}i.remove(a)}}else{let r=new l(t);r.setBuffer(n),r.setVolume(e.volume),r.setPlaybackRate(o),y.set(r,1),r.play(),r.source.onended=()=>{y.delete(r);try{r.disconnect()}catch{}}}}catch{}})}function D(e,t,n){v.has(e)?n(v.get(e)):t.load(e,t=>{v.set(e,t),n(t)},void 0,t=>{_.error(`Audio load error %s: %o`,e,t)})}var O=(0,h.memo)(function({entity:e}){let{debugMode:t}=o(),n=e.audioFileName??``,s=e.audioVolume??1,d=e.audioMinDistance??1,_=e.audioMaxDistance??1,v=e.audioMinLoopGap??0,y=e.audioMaxLoopGap??0,b=e.audioIs3D??!0?1:0,x=e.audioIsLooping??!0,[S,C,w]=e.position??[0,0,0],T=i(e=>e.scene),E=i(e=>e.camera),{audioLoader:O,audioListener:k}=f(),{audioEnabled:A}=a(),j=(0,h.useRef)(null),M=(0,h.useRef)(null),N=(0,h.useRef)(null),P=(0,h.useRef)(!1),F=(0,h.useRef)(!1),I=(0,h.useRef)(new c(S,C,w)),L=(0,h.useRef)(0),R=()=>{M.current!=null&&(clearTimeout(M.current),M.current=null),N.current!=null&&(clearTimeout(N.current),N.current=null)},[z]=(0,h.useState)(()=>Math.random());(0,h.useEffect)(()=>{if(!O||!k)return;L.current++;let e;if(b){let t=new u(k);t.position.copy(I.current),t.setDistanceModel(`inverse`),t.setRefDistance(d),t.setMaxDistance(_),t.setRolloffFactor(1),t.setVolume(s),e=t,T.add(e)}else e=new l(k),e.setVolume(s);return j.current=e,()=>{R();try{e.stop()}catch{}try{e.disconnect()}catch{}b&&T.remove(e),j.current=null,P.current=!1,F.current=!1}},[O,k,b,d,_,s,T]);let B=(e,t)=>{if(x)if(v>0||y>0){let n=Math.max(0,v),r=Math.max(n,y),i=n===r?n:z*(r-n)+n;e.loop=!1;let a=()=>{t===L.current&&(e.isPlaying===!1?M.current=setTimeout(()=>{if(t===L.current)try{e.play(),B(e,t)}catch{}},i):N.current=setTimeout(a,100))};N.current=setTimeout(a,100)}else e.setLoop(!0)},V=(0,h.useEffectEvent)(e=>{if(!O)return;let t=L.current;if(P.current)try{e.isPlaying||(e.play(),B(e,t))}catch{}else{let r;try{r=p(n)}catch{return}D(r,O,n=>{if(t===L.current&&!e.buffer){e.setBuffer(n),P.current=!0;try{e.play(),B(e,t)}catch{}}})}});return(0,h.useEffect)(()=>{let e=j.current;!e||b||!A||!n||V(e)},[A,b,n,O,k]),r(()=>{let e=j.current;if(!e||!b||!A||!n)return;let t=E.position.distanceTo(I.current),r=F.current,i=t<=_;if(i&&!r)F.current=!0,V(e);else if(!i&&r){F.current=!1,R();try{e.stop()}catch{}}}),(0,h.useEffect)(()=>{let e=j.current;if(e&&!A){R();try{e.stop()}catch{}F.current=!1}},[A]),t?(0,g.jsxs)(`mesh`,{position:I.current,children:[(0,g.jsx)(`sphereGeometry`,{args:[d,12,12]}),(0,g.jsx)(`meshBasicMaterial`,{color:`#00ff00`,wireframe:!0,opacity:.05,transparent:!0,toneMapped:!1}),(0,g.jsx)(m,{color:`#00ff00`,position:[0,d+1,0],children:n})]}):null});export{O as AudioEmitter,v as audioBufferCache,D as getCachedAudioBuffer,C as getSoundGeneration,E as playOneShotSound,T as resolveAudioProfile,w as stopAllTrackedSounds,b as trackSound,x as untrackSound};
import{r as e}from"./chunk-DECur_0Z.js";import{r as t,t as n}from"./jsx-runtime-BpGWiA-R.js";import{i as r,o as i}from"./react-three-fiber.esm-CFJ5mGMW.js";import"./Html-CIkmciH6.js";import{a,i as o}from"./SettingsProvider-CZgYJ4FU.js";import{t as s}from"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Ht as c,c as l,yt as u}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{r as d}from"./engineStore-CLELjjpY.js";import{B as f,M as p,T as m}from"./index-OhjeY6aE.js";var h=e(t(),1),g=n(),_=s(`AudioEmitter`),v=new Map,y=new Map;function b(e,t=1){y.set(e,t)}function x(e){y.delete(e)}var S=0;function C(){return S}function w(){S++;for(let[e]of y){try{e.stop()}catch{}try{e.disconnect()}catch{}}y.clear()}d.subscribe(e=>e.playback.rate,e=>{for(let[t,n]of y)try{t.setPlaybackRate(n*e)}catch{}});function T(e,t){let n=t(e),r=n?.filename;if(!r)return null;let i=r.endsWith(`.wav`)?r:`${r}.wav`,a=n.description,o=a==null?void 0:t(a);return{filename:i,is3D:o?.is3D??!0,isLooping:o?.isLooping??!1,refDist:o?.referenceDistance??20,maxDist:o?.maxDistance??100,volume:o?.volume??1}}function E(e,t,n,r,i){let a;try{a=p(e.filename)}catch{return}let o=d.getState().playback.rate,s=S;D(a,n,n=>{if(s===S)try{if(e.is3D&&i){let a=new u(t);a.setBuffer(n),a.setDistanceModel(`inverse`),a.setRefDistance(e.refDist),a.setMaxDistance(e.maxDist),a.setRolloffFactor(1),a.setVolume(e.volume),a.setPlaybackRate(o),r&&a.position.copy(r),i.add(a),y.set(a,1),a.play(),a.source.onended=()=>{y.delete(a);try{a.disconnect()}catch{}i.remove(a)}}else{let r=new l(t);r.setBuffer(n),r.setVolume(e.volume),r.setPlaybackRate(o),y.set(r,1),r.play(),r.source.onended=()=>{y.delete(r);try{r.disconnect()}catch{}}}}catch{}})}function D(e,t,n){v.has(e)?n(v.get(e)):t.load(e,t=>{v.set(e,t),n(t)},void 0,t=>{_.error(`Audio load error %s: %o`,e,t)})}var O=(0,h.memo)(function({entity:e}){let{debugMode:t}=o(),n=e.audioFileName??``,s=e.audioVolume??1,d=e.audioMinDistance??1,_=e.audioMaxDistance??1,v=e.audioMinLoopGap??0,y=e.audioMaxLoopGap??0,b=e.audioIs3D??!0?1:0,x=e.audioIsLooping??!0,[S,C,w]=e.position??[0,0,0],T=i(e=>e.scene),E=i(e=>e.camera),{audioLoader:O,audioListener:k}=f(),{audioEnabled:A}=a(),j=(0,h.useRef)(null),M=(0,h.useRef)(null),N=(0,h.useRef)(null),P=(0,h.useRef)(!1),F=(0,h.useRef)(!1),I=(0,h.useRef)(new c(S,C,w)),L=(0,h.useRef)(0),R=()=>{M.current!=null&&(clearTimeout(M.current),M.current=null),N.current!=null&&(clearTimeout(N.current),N.current=null)},[z]=(0,h.useState)(()=>Math.random());(0,h.useEffect)(()=>{if(!O||!k)return;L.current++;let e;if(b){let t=new u(k);t.position.copy(I.current),t.setDistanceModel(`inverse`),t.setRefDistance(d),t.setMaxDistance(_),t.setRolloffFactor(1),t.setVolume(s),e=t,T.add(e)}else e=new l(k),e.setVolume(s);return j.current=e,()=>{R();try{e.stop()}catch{}try{e.disconnect()}catch{}b&&T.remove(e),j.current=null,P.current=!1,F.current=!1}},[O,k,b,d,_,s,T]);let B=(e,t)=>{if(x)if(v>0||y>0){let n=Math.max(0,v),r=Math.max(n,y),i=n===r?n:z*(r-n)+n;e.loop=!1;let a=()=>{t===L.current&&(e.isPlaying===!1?M.current=setTimeout(()=>{if(t===L.current)try{e.play(),B(e,t)}catch{}},i):N.current=setTimeout(a,100))};N.current=setTimeout(a,100)}else e.setLoop(!0)},V=(0,h.useEffectEvent)(e=>{if(!O)return;let t=L.current;if(P.current)try{e.isPlaying||(e.play(),B(e,t))}catch{}else{let r;try{r=p(n)}catch{return}D(r,O,n=>{if(t===L.current&&!e.buffer){e.setBuffer(n),P.current=!0;try{e.play(),B(e,t)}catch{}}})}});return(0,h.useEffect)(()=>{let e=j.current;!e||b||!A||!n||V(e)},[A,b,n,O,k]),r(()=>{let e=j.current;if(!e||!b||!A||!n)return;let t=E.position.distanceTo(I.current),r=F.current,i=t<=_;if(i&&!r)F.current=!0,V(e);else if(!i&&r){F.current=!1,R();try{e.stop()}catch{}}}),(0,h.useEffect)(()=>{let e=j.current;if(e&&!A){R();try{e.stop()}catch{}F.current=!1}},[A]),t?(0,g.jsxs)(`mesh`,{position:I.current,children:[(0,g.jsx)(`sphereGeometry`,{args:[d,12,12]}),(0,g.jsx)(`meshBasicMaterial`,{color:`#00ff00`,wireframe:!0,opacity:.05,transparent:!0,toneMapped:!1}),(0,g.jsx)(m,{color:`#00ff00`,position:[0,d+1,0],children:n})]}):null});export{O as AudioEmitter,v as audioBufferCache,D as getCachedAudioBuffer,C as getSoundGeneration,E as playOneShotSound,T as resolveAudioProfile,w as stopAllTrackedSounds,b as trackSound,x as untrackSound};

View file

@ -1 +1 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import"./mission-BLbEDC74.js";import{X as i}from"./index-DRuEJepN.js";var a=t(),o=e(n(),1),s={InputForm:`_InputForm_18kom_1`,Input:`_Input_18kom_1`},c=r();function l(){let e=(0,a.c)(8),[t,n]=(0,o.useState)(``),r;e[0]===t?r=e[1]:(r=e=>{e.preventDefault();let r=t.trim();r&&(i.getState().sendCommand(`messageSent`,r),n(``))},e[0]=t,e[1]=r);let l=r,f;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(f=e=>n(e.target.value),e[2]=f):f=e[2];let p;e[3]===t?p=e[4]:(p=(0,c.jsx)(`input`,{className:s.Input,type:`text`,placeholder:`Say something…`,value:t,onChange:f,onKeyDown:d,onKeyUp:u,maxLength:255}),e[3]=t,e[4]=p);let m;return e[5]!==l||e[6]!==p?(m=(0,c.jsx)(`form`,{className:s.InputForm,onSubmit:l,children:p}),e[5]=l,e[6]=p,e[7]=m):m=e[7],m}function u(e){return e.stopPropagation()}function d(e){return e.stopPropagation()}export{l as ChatInput};
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import"./mission-BLbEDC74.js";import{X as i}from"./index-OhjeY6aE.js";var a=t(),o=e(n(),1),s={InputForm:`_InputForm_18kom_1`,Input:`_Input_18kom_1`},c=r();function l(){let e=(0,a.c)(8),[t,n]=(0,o.useState)(``),r;e[0]===t?r=e[1]:(r=e=>{e.preventDefault();let r=t.trim();r&&(i.getState().sendCommand(`messageSent`,r),n(``))},e[0]=t,e[1]=r);let l=r,f;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(f=e=>n(e.target.value),e[2]=f):f=e[2];let p;e[3]===t?p=e[4]:(p=(0,c.jsx)(`input`,{className:s.Input,type:`text`,placeholder:`Say something…`,value:t,onChange:f,onKeyDown:d,onKeyUp:u,maxLength:255}),e[3]=t,e[4]=p);let m;return e[5]!==l||e[6]!==p?(m=(0,c.jsx)(`form`,{className:s.InputForm,onSubmit:l,children:p}),e[5]=l,e[6]=p,e[7]=m):m=e[7],m}function u(e){return e.stopPropagation()}function d(e){return e.stopPropagation()}export{l as ChatInput};

View file

@ -1 +1 @@
import{r as e}from"./chunk-DECur_0Z.js";import{r as t}from"./jsx-runtime-BpGWiA-R.js";import"./react-three-fiber.esm-CFJ5mGMW.js";import"./Html-CIkmciH6.js";import{a as n}from"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{c as r}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{i,r as a}from"./engineStore-CLELjjpY.js";import{B as o,M as s}from"./index-DRuEJepN.js";import{getCachedAudioBuffer as c,getSoundGeneration as l,trackSound as u,untrackSound as d}from"./AudioEmitter-Dbm_u1FH.js";var f=e(t(),1);function p(){let{audioLoader:e,audioListener:t}=o(),{audioEnabled:p}=n(),m=i(e=>e.playback.streamSnapshot?.chatMessages),h=i(e=>e.playback.streamSnapshot?.timeSec),g=(0,f.useRef)(new WeakSet),_=(0,f.useRef)(new Map);return(0,f.useEffect)(()=>{if(!p||!e||!t||!m?.length||h==null)return;let n=g.current,i=_.current;for(let o of m)if(!n.has(o)&&(n.add(o),o.soundPath&&!(Math.abs(h-o.timeSec)>2)))try{let n=s(o.soundPath),f=o.soundPitch??1,p=a.getState().playback.rate,m=o.sender,h=l();c(n,e,e=>{if(h!==l())return;if(m){let e=i.get(m);if(e){try{e.stop()}catch{}d(e);try{e.disconnect()}catch{}i.delete(m)}}let n=new r(t);n.setBuffer(e),n.setPlaybackRate(f*p),u(n,f),m&&i.set(m,n),n.play(),n.source.onended=()=>{d(n);try{n.disconnect()}catch{}m&&i.get(m)===n&&i.delete(m)}})}catch{}},[p,e,t,m,h]),null}export{p as ChatSoundPlayer};
import{r as e}from"./chunk-DECur_0Z.js";import{r as t}from"./jsx-runtime-BpGWiA-R.js";import"./react-three-fiber.esm-CFJ5mGMW.js";import"./Html-CIkmciH6.js";import{a as n}from"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{c as r}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{i,r as a}from"./engineStore-CLELjjpY.js";import{B as o,M as s}from"./index-OhjeY6aE.js";import{getCachedAudioBuffer as c,getSoundGeneration as l,trackSound as u,untrackSound as d}from"./AudioEmitter-6YsKaXgh.js";var f=e(t(),1);function p(){let{audioLoader:e,audioListener:t}=o(),{audioEnabled:p}=n(),m=i(e=>e.playback.streamSnapshot?.chatMessages),h=i(e=>e.playback.streamSnapshot?.timeSec),g=(0,f.useRef)(new WeakSet),_=(0,f.useRef)(new Map);return(0,f.useEffect)(()=>{if(!p||!e||!t||!m?.length||h==null)return;let n=g.current,i=_.current;for(let o of m)if(!n.has(o)&&(n.add(o),o.soundPath&&!(Math.abs(h-o.timeSec)>2)))try{let n=s(o.soundPath),f=o.soundPitch??1,p=a.getState().playback.rate,m=o.sender,h=l();c(n,e,e=>{if(h!==l())return;if(m){let e=i.get(m);if(e){try{e.stop()}catch{}d(e);try{e.disconnect()}catch{}i.delete(m)}}let n=new r(t);n.setBuffer(e),n.setPlaybackRate(f*p),u(n,f),m&&i.set(m,n),n.play(),n.source.onended=()=>{d(n);try{n.disconnect()}catch{}m&&i.get(m)===n&&i.delete(m)}})}catch{}},[p,e,t,m,h]),null}export{p as ChatSoundPlayer};

View file

@ -1 +1 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import"./traditional-CVpSAKe0.js";import"./engineStore-CLELjjpY.js";import{G as i,J as a,K as o,W as s,Y as c,q as l}from"./index-DRuEJepN.js";var u=t(),d=e(n(),1),f={Root:`_Root_16j0q_1`,PlayPause:`_PlayPause_16j0q_10`,Time:`_Time_16j0q_32`,Seek:`_Seek_16j0q_38`,Speed:`_Speed_16j0q_44`},p=r(),m=[.25,.5,1,2,4];function h(e){return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,`0`)}`}function g(){let e=(0,u.c)(33),t=a(),n=o(),r=s(),g=i(),x=c(),{play:S,pause:C,seek:w,setSpeed:T}=l(),E,D;e[0]!==n||e[1]!==C||e[2]!==S||e[3]!==t?(E=()=>{if(!t)return;let e=e=>{if(e.code!==`Space`)return;let t=e.target;t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.tagName===`BUTTON`||t.isContentEditable||(e.preventDefault(),n?C():S())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},D=[t,n,S,C],e[0]=n,e[1]=C,e[2]=S,e[3]=t,e[4]=E,e[5]=D):(E=e[4],D=e[5]),(0,d.useEffect)(E,D);let O;e[6]===w?O=e[7]:(O=e=>{w(parseFloat(e.target.value))},e[6]=w,e[7]=O);let k=O,A;e[8]===T?A=e[9]:(A=e=>{T(parseFloat(e.target.value))},e[8]=T,e[9]=A);let j=A;if(!t||!Number.isFinite(t.duration))return null;let M=n?C:S,N=n?`Pause`:`Play`,P=n?`❚❚`:``,F;e[10]!==M||e[11]!==N||e[12]!==P?(F=(0,p.jsx)(`button`,{className:f.PlayPause,onClick:M,"aria-label":N,autoFocus:!0,children:P}),e[10]=M,e[11]=N,e[12]=P,e[13]=F):F=e[13];let I;e[14]===r?I=e[15]:(I=h(r),e[14]=r,e[15]=I);let L;e[16]===g?L=e[17]:(L=h(g),e[16]=g,e[17]=L);let R=`${I} / ${L}`,z;e[18]===R?z=e[19]:(z=(0,p.jsx)(`span`,{className:f.Time,children:R}),e[18]=R,e[19]=z);let B;e[20]!==r||e[21]!==g||e[22]!==k?(B=(0,p.jsx)(`input`,{className:f.Seek,type:`range`,min:0,max:g,step:.01,value:r,onChange:k}),e[20]=r,e[21]=g,e[22]=k,e[23]=B):B=e[23];let V;e[24]===Symbol.for(`react.memo_cache_sentinel`)?(V=m.map(_),e[24]=V):V=e[24];let H;e[25]!==j||e[26]!==x?(H=(0,p.jsx)(`select`,{className:f.Speed,value:x,onChange:j,children:V}),e[25]=j,e[26]=x,e[27]=H):H=e[27];let U;return e[28]!==z||e[29]!==B||e[30]!==H||e[31]!==F?(U=(0,p.jsxs)(`div`,{className:f.Root,onKeyDown:b,onPointerDown:y,onClick:v,children:[F,z,B,H]}),e[28]=z,e[29]=B,e[30]=H,e[31]=F,e[32]=U):U=e[32],U}function _(e){return(0,p.jsxs)(`option`,{value:e,children:[e,`x`]},e)}function v(e){return e.stopPropagation()}function y(e){return e.stopPropagation()}function b(e){return e.stopPropagation()}export{g as DemoPlaybackControls};
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import"./traditional-CVpSAKe0.js";import"./engineStore-CLELjjpY.js";import{G as i,J as a,K as o,W as s,Y as c,q as l}from"./index-OhjeY6aE.js";var u=t(),d=e(n(),1),f={Root:`_Root_16j0q_1`,PlayPause:`_PlayPause_16j0q_10`,Time:`_Time_16j0q_32`,Seek:`_Seek_16j0q_38`,Speed:`_Speed_16j0q_44`},p=r(),m=[.25,.5,1,2,4];function h(e){return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,`0`)}`}function g(){let e=(0,u.c)(33),t=a(),n=o(),r=s(),g=i(),x=c(),{play:S,pause:C,seek:w,setSpeed:T}=l(),E,D;e[0]!==n||e[1]!==C||e[2]!==S||e[3]!==t?(E=()=>{if(!t)return;let e=e=>{if(e.code!==`Space`)return;let t=e.target;t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.tagName===`BUTTON`||t.isContentEditable||(e.preventDefault(),n?C():S())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},D=[t,n,S,C],e[0]=n,e[1]=C,e[2]=S,e[3]=t,e[4]=E,e[5]=D):(E=e[4],D=e[5]),(0,d.useEffect)(E,D);let O;e[6]===w?O=e[7]:(O=e=>{w(parseFloat(e.target.value))},e[6]=w,e[7]=O);let k=O,A;e[8]===T?A=e[9]:(A=e=>{T(parseFloat(e.target.value))},e[8]=T,e[9]=A);let j=A;if(!t||!Number.isFinite(t.duration))return null;let M=n?C:S,N=n?`Pause`:`Play`,P=n?`❚❚`:``,F;e[10]!==M||e[11]!==N||e[12]!==P?(F=(0,p.jsx)(`button`,{className:f.PlayPause,onClick:M,"aria-label":N,autoFocus:!0,children:P}),e[10]=M,e[11]=N,e[12]=P,e[13]=F):F=e[13];let I;e[14]===r?I=e[15]:(I=h(r),e[14]=r,e[15]=I);let L;e[16]===g?L=e[17]:(L=h(g),e[16]=g,e[17]=L);let R=`${I} / ${L}`,z;e[18]===R?z=e[19]:(z=(0,p.jsx)(`span`,{className:f.Time,children:R}),e[18]=R,e[19]=z);let B;e[20]!==r||e[21]!==g||e[22]!==k?(B=(0,p.jsx)(`input`,{className:f.Seek,type:`range`,min:0,max:g,step:.01,value:r,onChange:k}),e[20]=r,e[21]=g,e[22]=k,e[23]=B):B=e[23];let V;e[24]===Symbol.for(`react.memo_cache_sentinel`)?(V=m.map(_),e[24]=V):V=e[24];let H;e[25]!==j||e[26]!==x?(H=(0,p.jsx)(`select`,{className:f.Speed,value:x,onChange:j,children:V}),e[25]=j,e[26]=x,e[27]=H):H=e[27];let U;return e[28]!==z||e[29]!==B||e[30]!==H||e[31]!==F?(U=(0,p.jsxs)(`div`,{className:f.Root,onKeyDown:b,onPointerDown:y,onClick:v,children:[F,z,B,H]}),e[28]=z,e[29]=B,e[30]=H,e[31]=F,e[32]=U):U=e[32],U}function _(e){return(0,p.jsxs)(`option`,{value:e,children:[e,`x`]},e)}function v(e){return e.stopPropagation()}function y(e){return e.stopPropagation()}function b(e){return e.stopPropagation()}export{g as DemoPlaybackControls};

View file

@ -1,4 +1,4 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{i}from"./react-three-fiber.esm-CFJ5mGMW.js";import{a}from"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Et as o,Vt as s,kt as c,p as l,y as u}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{F as d,V as f,r as p}from"./index-DRuEJepN.js";var m=t(),h=e(n(),1),g=`
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{i}from"./react-three-fiber.esm-CFJ5mGMW.js";import{a}from"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Et as o,Vt as s,kt as c,p as l,y as u}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{F as d,V as f,r as p}from"./index-OhjeY6aE.js";var m=t(),h=e(n(),1),g=`
#include <fog_pars_vertex>
varying vec2 vUv;

View file

@ -1 +1 @@
import{n as e,t}from"./jsx-runtime-BpGWiA-R.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import"./mission-BLbEDC74.js";import"./engineStore-CLELjjpY.js";import{H as n,J as r,Z as i}from"./index-DRuEJepN.js";var a=e(),o={Root:`_Root_uktvs_1`,Column:`_Column_uktvs_13`,Row:`_Row_uktvs_20`,Spacer:`_Spacer_uktvs_26`,Key:`_Key_uktvs_30`,Arrow:`_Arrow_uktvs_53`},s=t();function c(){let e=(0,a.c)(51),t=r(),c=i(y),b=n(v),x=n(_),S=n(g),C=n(h),w=n(m),T=n(p),E=n(f),D=n(d),O=n(u),k=n(l);if(t&&t.source!==`live`||t?.source===`live`&&!c)return null;let A;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(A=(0,s.jsx)(`div`,{className:o.Spacer}),e[0]=A):A=e[0];let j;e[1]===b?j=e[2]:(j=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":b,children:`W`}),e[1]=b,e[2]=j);let M;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,s.jsx)(`div`,{className:o.Spacer}),e[3]=M):M=e[3];let N;e[4]===j?N=e[5]:(N=(0,s.jsxs)(`div`,{className:o.Row,children:[A,j,M]}),e[4]=j,e[5]=N);let P;e[6]===S?P=e[7]:(P=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":S,children:`A`}),e[6]=S,e[7]=P);let F;e[8]===x?F=e[9]:(F=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":x,children:`S`}),e[8]=x,e[9]=F);let I;e[10]===C?I=e[11]:(I=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":C,children:`D`}),e[10]=C,e[11]=I);let L;e[12]!==P||e[13]!==F||e[14]!==I?(L=(0,s.jsxs)(`div`,{className:o.Row,children:[P,F,I]}),e[12]=P,e[13]=F,e[14]=I,e[15]=L):L=e[15];let R;e[16]!==N||e[17]!==L?(R=(0,s.jsxs)(`div`,{className:o.Column,children:[N,L]}),e[16]=N,e[17]=L,e[18]=R):R=e[18];let z;e[19]===Symbol.for(`react.memo_cache_sentinel`)?(z=(0,s.jsx)(`span`,{className:o.Arrow,children:``}),e[19]=z):z=e[19];let B;e[20]===w?B=e[21]:(B=(0,s.jsx)(`div`,{className:o.Row,children:(0,s.jsxs)(`div`,{className:o.Key,"data-pressed":w,children:[z,` Space`]})}),e[20]=w,e[21]=B);let V;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(V=(0,s.jsx)(`span`,{className:o.Arrow,children:``}),e[22]=V):V=e[22];let H;e[23]===T?H=e[24]:(H=(0,s.jsx)(`div`,{className:o.Row,children:(0,s.jsxs)(`div`,{className:o.Key,"data-pressed":T,children:[V,` Shift`]})}),e[23]=T,e[24]=H);let U;e[25]!==B||e[26]!==H?(U=(0,s.jsxs)(`div`,{className:o.Column,children:[B,H]}),e[25]=B,e[26]=H,e[27]=U):U=e[27];let W;e[28]===Symbol.for(`react.memo_cache_sentinel`)?(W=(0,s.jsx)(`div`,{className:o.Spacer}),e[28]=W):W=e[28];let G;e[29]===E?G=e[30]:(G=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":E,children:``}),e[29]=E,e[30]=G);let K;e[31]===Symbol.for(`react.memo_cache_sentinel`)?(K=(0,s.jsx)(`div`,{className:o.Spacer}),e[31]=K):K=e[31];let q;e[32]===G?q=e[33]:(q=(0,s.jsxs)(`div`,{className:o.Row,children:[W,G,K]}),e[32]=G,e[33]=q);let J;e[34]===O?J=e[35]:(J=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":O,children:``}),e[34]=O,e[35]=J);let Y;e[36]===D?Y=e[37]:(Y=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":D,children:``}),e[36]=D,e[37]=Y);let X;e[38]===k?X=e[39]:(X=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":k,children:``}),e[38]=k,e[39]=X);let Z;e[40]!==J||e[41]!==Y||e[42]!==X?(Z=(0,s.jsxs)(`div`,{className:o.Row,children:[J,Y,X]}),e[40]=J,e[41]=Y,e[42]=X,e[43]=Z):Z=e[43];let Q;e[44]!==q||e[45]!==Z?(Q=(0,s.jsxs)(`div`,{className:o.Column,children:[q,Z]}),e[44]=q,e[45]=Z,e[46]=Q):Q=e[46];let $;return e[47]!==U||e[48]!==Q||e[49]!==R?($=(0,s.jsxs)(`div`,{className:o.Root,children:[R,U,Q]}),e[47]=U,e[48]=Q,e[49]=R,e[50]=$):$=e[50],$}function l(e){return e.lookRight}function u(e){return e.lookLeft}function d(e){return e.lookDown}function f(e){return e.lookUp}function p(e){return e.down}function m(e){return e.up}function h(e){return e.right}function g(e){return e.left}function _(e){return e.backward}function v(e){return e.forward}function y(e){return e.liveReady}export{c as KeyboardOverlay};
import{n as e,t}from"./jsx-runtime-BpGWiA-R.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import"./mission-BLbEDC74.js";import"./engineStore-CLELjjpY.js";import{H as n,J as r,Z as i}from"./index-OhjeY6aE.js";var a=e(),o={Root:`_Root_uktvs_1`,Column:`_Column_uktvs_13`,Row:`_Row_uktvs_20`,Spacer:`_Spacer_uktvs_26`,Key:`_Key_uktvs_30`,Arrow:`_Arrow_uktvs_53`},s=t();function c(){let e=(0,a.c)(51),t=r(),c=i(y),b=n(v),x=n(_),S=n(g),C=n(h),w=n(m),T=n(p),E=n(f),D=n(d),O=n(u),k=n(l);if(t&&t.source!==`live`||t?.source===`live`&&!c)return null;let A;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(A=(0,s.jsx)(`div`,{className:o.Spacer}),e[0]=A):A=e[0];let j;e[1]===b?j=e[2]:(j=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":b,children:`W`}),e[1]=b,e[2]=j);let M;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,s.jsx)(`div`,{className:o.Spacer}),e[3]=M):M=e[3];let N;e[4]===j?N=e[5]:(N=(0,s.jsxs)(`div`,{className:o.Row,children:[A,j,M]}),e[4]=j,e[5]=N);let P;e[6]===S?P=e[7]:(P=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":S,children:`A`}),e[6]=S,e[7]=P);let F;e[8]===x?F=e[9]:(F=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":x,children:`S`}),e[8]=x,e[9]=F);let I;e[10]===C?I=e[11]:(I=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":C,children:`D`}),e[10]=C,e[11]=I);let L;e[12]!==P||e[13]!==F||e[14]!==I?(L=(0,s.jsxs)(`div`,{className:o.Row,children:[P,F,I]}),e[12]=P,e[13]=F,e[14]=I,e[15]=L):L=e[15];let R;e[16]!==N||e[17]!==L?(R=(0,s.jsxs)(`div`,{className:o.Column,children:[N,L]}),e[16]=N,e[17]=L,e[18]=R):R=e[18];let z;e[19]===Symbol.for(`react.memo_cache_sentinel`)?(z=(0,s.jsx)(`span`,{className:o.Arrow,children:``}),e[19]=z):z=e[19];let B;e[20]===w?B=e[21]:(B=(0,s.jsx)(`div`,{className:o.Row,children:(0,s.jsxs)(`div`,{className:o.Key,"data-pressed":w,children:[z,` Space`]})}),e[20]=w,e[21]=B);let V;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(V=(0,s.jsx)(`span`,{className:o.Arrow,children:``}),e[22]=V):V=e[22];let H;e[23]===T?H=e[24]:(H=(0,s.jsx)(`div`,{className:o.Row,children:(0,s.jsxs)(`div`,{className:o.Key,"data-pressed":T,children:[V,` Shift`]})}),e[23]=T,e[24]=H);let U;e[25]!==B||e[26]!==H?(U=(0,s.jsxs)(`div`,{className:o.Column,children:[B,H]}),e[25]=B,e[26]=H,e[27]=U):U=e[27];let W;e[28]===Symbol.for(`react.memo_cache_sentinel`)?(W=(0,s.jsx)(`div`,{className:o.Spacer}),e[28]=W):W=e[28];let G;e[29]===E?G=e[30]:(G=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":E,children:``}),e[29]=E,e[30]=G);let K;e[31]===Symbol.for(`react.memo_cache_sentinel`)?(K=(0,s.jsx)(`div`,{className:o.Spacer}),e[31]=K):K=e[31];let q;e[32]===G?q=e[33]:(q=(0,s.jsxs)(`div`,{className:o.Row,children:[W,G,K]}),e[32]=G,e[33]=q);let J;e[34]===O?J=e[35]:(J=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":O,children:``}),e[34]=O,e[35]=J);let Y;e[36]===D?Y=e[37]:(Y=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":D,children:``}),e[36]=D,e[37]=Y);let X;e[38]===k?X=e[39]:(X=(0,s.jsx)(`div`,{className:o.Key,"data-pressed":k,children:``}),e[38]=k,e[39]=X);let Z;e[40]!==J||e[41]!==Y||e[42]!==X?(Z=(0,s.jsxs)(`div`,{className:o.Row,children:[J,Y,X]}),e[40]=J,e[41]=Y,e[42]=X,e[43]=Z):Z=e[43];let Q;e[44]!==q||e[45]!==Z?(Q=(0,s.jsxs)(`div`,{className:o.Column,children:[q,Z]}),e[44]=q,e[45]=Z,e[46]=Q):Q=e[46];let $;return e[47]!==U||e[48]!==Q||e[49]!==R?($=(0,s.jsxs)(`div`,{className:o.Root,children:[R,U,Q]}),e[47]=U,e[48]=Q,e[49]=R,e[50]=$):$=e[50],$}function l(e){return e.lookRight}function u(e){return e.lookLeft}function d(e){return e.lookDown}function f(e){return e.lookUp}function p(e){return e.down}function m(e){return e.up}function h(e){return e.right}function g(e){return e.left}function _(e){return e.backward}function v(e){return e.forward}function y(e){return e.liveReady}export{c as KeyboardOverlay};

View file

@ -1,4 +1,4 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{c as i}from"./manifest-CnxBQu_n.js";import"./logger-CiAJCFpz.js";import"./mission-BLbEDC74.js";import{Dt as a,N as o,P as s,Tt as c,j as l,wt as u}from"./index-DRuEJepN.js";var d=t(),f=e(n(),1),p={GuiMarkup:`_GuiMarkup_jg4va_1`,Bullet:`_Bullet_jg4va_12`},m=r(),h=new Set([`spop`,`spush`,`lmargin`,`font`,`color`,`bitmap`,`a`,`/a`]);function g(e){return e.split(/<([^><]+)>/g).map((e,t)=>{if(t%2==0)return e?{type:`text`,value:e}:null;{let[t,...n]=e.split(`:`);return h.has(t.toLowerCase())?{type:`tag`,name:t,args:n}:{type:`text`,value:`<${e}>`}}}).filter(e=>e!=null)}function _(e){let[t,n]=e;return{fontDescription:t,fontSize:n?Math.max(11,Math.min(parseInt(n.trim(),10),16)):void 0}}function v(e){let t=g(e),n={type:`span`,source:`root`,style:{},children:[]},r=n,i=[r],a=e=>e.children!=null&&e.children.some(e=>typeof e==`string`||a(e));for(let e of t)switch(e.type){case`text`:r.children.push(e.value);break;case`tag`:switch(e.name){case`spush`:{let e={type:`span`,source:`spush`,style:{},children:[]};r.children.push(e),r=e,i.push(r);break}case`spop`:if(r.source!==`root`){let e=i.pop();for(;e.source!==`spush`;)e=i.pop();r=i[i.length-1]}break;case`lmargin`:break;case`font`:{let t=_(e.args).fontSize;if(!a(r))r.style.fontSize=t;else{let e={type:`span`,source:`spush`,style:{fontSize:t},children:[]};r.children.push(e),r=e,i.push(r)}break}case`color`:if(!a(r))r.style.color=`#${e.args[0].trim()}`;else{let t={type:`span`,source:`spush`,style:{color:`#${e.args[0].trim()}`},children:[]};r.children.push(t),r=t,i.push(r)}break;case`bitmap`:{let t={type:`bitmap`,value:e.args[0]};r.children.push(t);break}case`a`:{let t=e.args[0].trim().split(` `),n={type:`a`,source:`a`,value:`http://${t.length===2&&t[0]===`wwwlink`?t[1]:t[0]}`,style:{},children:[]};r.children.push(n),r=n,i.push(r);break}case`/a`:{let e=i.pop();for(;e.source!==`a`;)e=i.pop();r=i[i.length-1];break}}}return y(n)}function y(e){switch(e.type){case`span`:return f.createElement(`span`,{style:Object.keys(e.style).length===0?void 0:e.style},...e.children.map(e=>typeof e==`string`?e:y(e)));case`a`:return f.createElement(`a`,{href:e.value,style:Object.keys(e.style).length===0?void 0:e.style,rel:`noopener noreferrer`,target:`_blank`},...e.children.map(e=>typeof e==`string`?e:y(e)));case`bitmap`:return(0,m.jsx)(S,{name:e.value})}}var b=new Map;function x(e){if(b.has(e))return b.get(e);let t;try{t=o(i(`textures/gui/${e}`))}catch{t=null}return b.set(e,t),t}function S(e){let t=(0,d.c)(5),{name:n}=e,r;t[0]===n?r=t[1]:(r=x(n),t[0]=n,t[1]=r);let i=r;if(i){let e;return t[2]===i?e=t[3]:(e=(0,m.jsx)(`img`,{src:i,alt:``,className:p.Bitmap}),t[2]=i,t[3]=e),e}if(/bullet/i.test(n)){let e;return t[4]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,m.jsx)(`span`,{className:p.Bullet,children:``}),t[4]=e):e=t[4],e}return null}var C=/<(?:font|color|bitmap|just|lmargin|a):/i;function w(e){return C.test(e)}function T(e,t){let n=t.toUpperCase();return e.split(`
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{c as i}from"./manifest-CnxBQu_n.js";import"./logger-CiAJCFpz.js";import"./mission-BLbEDC74.js";import{Dt as a,N as o,P as s,Tt as c,j as l,wt as u}from"./index-OhjeY6aE.js";var d=t(),f=e(n(),1),p={GuiMarkup:`_GuiMarkup_jg4va_1`,Bullet:`_Bullet_jg4va_12`},m=r(),h=new Set([`spop`,`spush`,`lmargin`,`font`,`color`,`bitmap`,`a`,`/a`]);function g(e){return e.split(/<([^><]+)>/g).map((e,t)=>{if(t%2==0)return e?{type:`text`,value:e}:null;{let[t,...n]=e.split(`:`);return h.has(t.toLowerCase())?{type:`tag`,name:t,args:n}:{type:`text`,value:`<${e}>`}}}).filter(e=>e!=null)}function _(e){let[t,n]=e;return{fontDescription:t,fontSize:n?Math.max(11,Math.min(parseInt(n.trim(),10),16)):void 0}}function v(e){let t=g(e),n={type:`span`,source:`root`,style:{},children:[]},r=n,i=[r],a=e=>e.children!=null&&e.children.some(e=>typeof e==`string`||a(e));for(let e of t)switch(e.type){case`text`:r.children.push(e.value);break;case`tag`:switch(e.name){case`spush`:{let e={type:`span`,source:`spush`,style:{},children:[]};r.children.push(e),r=e,i.push(r);break}case`spop`:if(r.source!==`root`){let e=i.pop();for(;e.source!==`spush`;)e=i.pop();r=i[i.length-1]}break;case`lmargin`:break;case`font`:{let t=_(e.args).fontSize;if(!a(r))r.style.fontSize=t;else{let e={type:`span`,source:`spush`,style:{fontSize:t},children:[]};r.children.push(e),r=e,i.push(r)}break}case`color`:if(!a(r))r.style.color=`#${e.args[0].trim()}`;else{let t={type:`span`,source:`spush`,style:{color:`#${e.args[0].trim()}`},children:[]};r.children.push(t),r=t,i.push(r)}break;case`bitmap`:{let t={type:`bitmap`,value:e.args[0]};r.children.push(t);break}case`a`:{let t=e.args[0].trim().split(` `),n={type:`a`,source:`a`,value:`http://${t.length===2&&t[0]===`wwwlink`?t[1]:t[0]}`,style:{},children:[]};r.children.push(n),r=n,i.push(r);break}case`/a`:{let e=i.pop();for(;e.source!==`a`;)e=i.pop();r=i[i.length-1];break}}}return y(n)}function y(e){switch(e.type){case`span`:return f.createElement(`span`,{style:Object.keys(e.style).length===0?void 0:e.style},...e.children.map(e=>typeof e==`string`?e:y(e)));case`a`:return f.createElement(`a`,{href:e.value,style:Object.keys(e.style).length===0?void 0:e.style,rel:`noopener noreferrer`,target:`_blank`},...e.children.map(e=>typeof e==`string`?e:y(e)));case`bitmap`:return(0,m.jsx)(S,{name:e.value})}}var b=new Map;function x(e){if(b.has(e))return b.get(e);let t;try{t=o(i(`textures/gui/${e}`))}catch{t=null}return b.set(e,t),t}function S(e){let t=(0,d.c)(5),{name:n}=e,r;t[0]===n?r=t[1]:(r=x(n),t[0]=n,t[1]=r);let i=r;if(i){let e;return t[2]===i?e=t[3]:(e=(0,m.jsx)(`img`,{src:i,alt:``,className:p.Bitmap}),t[2]=i,t[3]=e),e}if(/bullet/i.test(n)){let e;return t[4]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,m.jsx)(`span`,{className:p.Bullet,children:``}),t[4]=e):e=t[4],e}return null}var C=/<(?:font|color|bitmap|just|lmargin|a):/i;function w(e){return C.test(e)}function T(e,t){let n=t.toUpperCase();return e.split(`
`).flatMap(e=>{let t=e.match(/^\[([^\]]+)\]/);return t&&!t[1].toUpperCase().split(/\s+/).includes(n)?[]:[e.replace(/^\[[^\]]+\]/,``)]}).join(`
`)}function E(e){let t=(0,d.c)(4),{markup:n}=e,r;t[0]===n?r=t[1]:(r=v(n),t[0]=n,t[1]=r);let i=r,a;return t[2]===i?a=t[3]:(a=(0,m.jsx)(`div`,{className:p.GuiMarkup,children:i}),t[2]=i,t[3]=a),a}var D={Dialog:`_Dialog_1kbms_1 _Dialog_6c89x_1`,Overlay:`_Overlay_1kbms_10 _Overlay_6c89x_20`,Body:`_Body_1kbms_14`,Left:`_Left_1kbms_22`,PreviewImage:`_PreviewImage_1kbms_27`,PreviewImageFloating:`_PreviewImageFloating_1kbms_33`,Title:`_Title_1kbms_43`,MapMeta:`_MapMeta_1kbms_51`,MapPlanet:`_MapPlanet_1kbms_61`,MapQuote:`_MapQuote_1kbms_65`,MapBlurb:`_MapBlurb_1kbms_84`,Section:`_Section_1kbms_89`,SectionTitle:`_SectionTitle_1kbms_93`,MusicTrack:`_MusicTrack_1kbms_103`,MusicButton:`_MusicButton_1kbms_117`,Footer:`_Footer_1kbms_144`,CloseButton:`_CloseButton_1kbms_154 _DialogButton_6c89x_31`,Hint:`_Hint_1kbms_158`,MusicTrackName:`_MusicTrackName_1kbms_164`};function ee(e){let t=(0,d.c)(2),n;return t[0]===e?n=t[1]:(n={queryKey:[`parsedMission`,e],queryFn:()=>s(e)},t[0]=e,t[1]=n),a(n)}function te(e){for(let t of e.body){if(t.type!==`ObjectDeclaration`)continue;let{instanceName:e,body:n}=t;if(e&&e.type===`Identifier`&&e.name.toLowerCase()===`missiongroup`){let e={};for(let t of n){if(t.type!==`Assignment`)continue;let{target:n,value:r}=t;n.type===`Identifier`&&r.type===`StringLiteral`&&(e[n.name.toLowerCase()]=r.value)}return e}}return{}}function ne(e,t){if(e)try{return o(i(`textures/gui/${e}`))}catch{}try{return o(i(`textures/gui/Load_${t}`))}catch{}return null}function re(e){let t=(0,d.c)(7),{src:n,alt:r,className:i}=e,a=i===void 0?D.PreviewImage:i,[o,s]=(0,f.useState)(null),c,l;if(t[0]===n?(c=t[1],l=t[2]):(c=()=>{let e=!1,t;return fetch(n).then(j).then(A).then(k).then(n=>{e||!n||(t=URL.createObjectURL(n),s(t))}).catch(O),()=>{e=!0,t&&URL.revokeObjectURL(t)}},l=[n],t[0]=n,t[1]=c,t[2]=l),(0,f.useEffect)(c,l),!o)return null;let u;return t[3]!==r||t[4]!==a||t[5]!==o?(u=(0,m.jsx)(`img`,{src:o,alt:r,className:a}),t[3]=r,t[4]=a,t[5]=o,t[6]=u):u=t[6],u}function O(){}function k(e){return new Promise(t=>{let n=document.createElement(`canvas`);n.width=e.width,n.height=e.height,n.getContext(`2d`)?.drawImage(e,0,0),e.close(),n.toBlob(t)})}function A(e){return createImageBitmap(e,{colorSpaceConversion:`none`})}function j(e){return e.blob()}function ie(e){let t=(0,d.c)(22),{track:n}=e,[r,i]=(0,f.useState)(!1),[a,o]=(0,f.useState)(!0),s=(0,f.useRef)(null),p;t[0]===n?p=t[1]:(p=n.toLowerCase(),t[0]=n,t[1]=p);let h=`${l}music/${p}.mp3`,g,_;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(g=()=>{let e=s.current;if(e)return()=>{e.pause()}},_=[],t[2]=g,t[3]=_):(g=t[2],_=t[3]),(0,f.useEffect)(g,_);let v;t[4]===r?v=t[5]:(v=()=>{let e=s.current;e&&(r?e.pause():e.play().catch(()=>o(!1)))},t[4]=r,t[5]=v);let y=v,b,x,S;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(b=()=>i(!0),x=()=>i(!1),S=()=>o(!1),t[6]=b,t[7]=x,t[8]=S):(b=t[6],x=t[7],S=t[8]);let C;t[9]===h?C=t[10]:(C=(0,m.jsx)(`audio`,{ref:s,src:h,loop:!0,onPlay:b,onPause:x,onError:S}),t[9]=h,t[10]=C);let w;t[11]===n?w=t[12]:(w=(0,m.jsx)(`span`,{className:D.MusicTrackName,children:n}),t[11]=n,t[12]=w);let T;t[13]!==a||t[14]!==r||t[15]!==y?(T=a&&(0,m.jsx)(`button`,{className:D.MusicButton,onClick:y,"aria-label":r?`Pause music`:`Play music`,children:r?(0,m.jsx)(c,{}):(0,m.jsx)(u,{})}),t[13]=a,t[14]=r,t[15]=y,t[16]=T):T=t[16];let E;return t[17]!==r||t[18]!==T||t[19]!==C||t[20]!==w?(E=(0,m.jsxs)(`div`,{className:D.MusicTrack,"data-playing":r,children:[C,w,T]}),t[17]=r,t[18]=T,t[19]=C,t[20]=w,t[21]=E):E=t[21],E}function M(e){let t=(0,d.c)(100),{onClose:n,missionName:r,missionType:i}=e,{data:a}=ee(r),o=(0,f.useRef)(null),s,c;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(s=()=>{o.current?.focus();try{document.exitPointerLock()}catch{}},c=[],t[0]=s,t[1]=c):(s=t[0],c=t[1]),(0,f.useEffect)(s,c);let l,u;t[2]===n?(l=t[3],u=t[4]):(l=()=>{let e=e=>{if(e.key===`Escape`)n();else if(e.key===`k`&&(e.metaKey||e.ctrlKey)){n();return}e.stopImmediatePropagation()},t=se;return window.addEventListener(`keydown`,e,{capture:!0}),window.addEventListener(`keyup`,t,{capture:!0}),()=>{window.removeEventListener(`keydown`,e,{capture:!0}),window.removeEventListener(`keyup`,t,{capture:!0})}},u=[n],t[2]=n,t[3]=l,t[4]=u),(0,f.useEffect)(l,u);let p;t[5]===a?p=t[6]:(p=a?te(a.ast):{},t[5]=a,t[6]=p);let h=p,g;t[7]!==r||t[8]!==a?(g=a?ne(a.bitmap,r):null,t[7]=r,t[8]=a,t[9]=g):g=t[9];let _=g,v=a?.displayName??r,y;t[10]===i?y=t[11]:(y=i.toLowerCase(),t[10]=i,t[11]=y);let b=y===`singleplayer`,x=h.musictrack,S,C,O,k,A,j,M,N,P,F,I,L,R,z,B,V,H,U;if(t[12]!==_||t[13]!==v||t[14]!==b||t[15]!==i||t[16]!==n||t[17]!==a){let e=a?.missionString?T(a.missionString,i):null,r,s,c,l;if(t[36]!==a?.missionQuote){if(l=a?.missionQuote?.trim()??``,s=w(l),c=``,r=``,!s)for(let e of l.split(`
`)){let t=e.trim();t.match(/^--[^-]/)?r=t.replace(/^-+\s*/,``).trim():t&&(c+=(c?`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{i}from"./react-three-fiber.esm-CFJ5mGMW.js";import"./Html-CIkmciH6.js";import"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Dt as a,Ht as o,xt as s,y as c}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import"./engineStore-CLELjjpY.js";import{F as l,V as u,_ as d,g as f,y as p}from"./index-DRuEJepN.js";var m=t(),h=e(n(),1),g=r(),_=new o,v=new o,y=new o,b=new o,x=new o,S=new o,C=new o(0,1,0);function w(e){let t=(0,m.c)(14),{entity:n}=e,{visual:r}=n,i;t[0]===r.texture?i=t[1]:(i=l(r.texture),t[0]=r.texture,t[1]=i);let o=u(i,T),s=Array.isArray(o)?o[0]:o,d;t[2]!==r.color.b||t[3]!==r.color.g||t[4]!==r.color.r?(d=new c().setRGB(r.color.r,r.color.g,r.color.b,a),t[2]=r.color.b,t[3]=r.color.g,t[4]=r.color.r,t[5]=d):d=t[5];let f=d,p;t[6]===r.size?p=t[7]:(p=[r.size,r.size,1],t[6]=r.size,t[7]=p);let h;t[8]!==f||t[9]!==s?(h=(0,g.jsx)(`spriteMaterial`,{map:s,color:f,transparent:!0,blending:2,depthWrite:!1,toneMapped:!1}),t[8]=f,t[9]=s,t[10]=h):h=t[10];let _;return t[11]!==p||t[12]!==h?(_=(0,g.jsx)(`sprite`,{scale:p,children:h}),t[11]=p,t[12]=h,t[13]=_):_=t[13],_}function T(e){d(Array.isArray(e)?e[0]:e)}function E(e){let t=(0,m.c)(29),{entity:n}=e,{visual:r}=n,a=(0,h.useRef)(null),o=(0,h.useRef)(null),c=(0,h.useRef)(null),d;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(d=new s,t[0]=d):d=t[0];let w=(0,h.useRef)(d),T;t[1]===r.texture?T=t[2]:(T=l(r.texture),t[1]=r.texture,t[2]=T);let E=r.crossTexture??r.texture,O;t[3]===E?O=t[4]:(O=l(E),t[3]=E,t[4]=O);let k;t[5]!==T||t[6]!==O?(k=[T,O],t[5]=T,t[6]=O,t[7]=k):k=t[7];let A=u(k,D),j;t[8]===A?j=t[9]:(j=Array.isArray(A)?A:[A,A],t[8]=A,t[9]=j);let[M,N]=j,P;t[10]!==n.direction||t[11]!==n.keyframes?.[0]||t[12]!==r.crossSize||t[13]!==r.crossViewAng||t[14]!==r.renderCross||t[15]!==r.tracerLength||t[16]!==r.tracerWidth?(P=e=>{let{camera:t}=e,i=a.current,s=o.current;if(!i||!s)return;let l=n.keyframes?.[0],u=l?.position,d=n.direction??l?.velocity;if(!u||!d){i.visible=!1,c.current&&(c.current.visible=!1);return}if(p(d,_),_.lengthSq()<1e-8){i.visible=!1,c.current&&(c.current.visible=!1);return}_.normalize(),i.visible=!0,p(u,S),v.copy(S).sub(t.position),y.crossVectors(v,_),y.lengthSq()<1e-8&&(y.crossVectors(C,_),y.lengthSq()<1e-8&&y.set(1,0,0)),y.normalize().multiplyScalar(r.tracerWidth);let m=r.tracerLength*.5;b.copy(_).multiplyScalar(-m),x.copy(_).multiplyScalar(m);let h=s.array;h[0]=b.x+y.x,h[1]=b.y+y.y,h[2]=b.z+y.z,h[3]=b.x-y.x,h[4]=b.y-y.y,h[5]=b.z-y.z,h[6]=x.x-y.x,h[7]=x.y-y.y,h[8]=x.z-y.z,h[9]=x.x+y.x,h[10]=x.y+y.y,h[11]=x.z+y.z,s.needsUpdate=!0;let g=c.current;if(!g)return;if(!r.renderCross){g.visible=!1;return}v.normalize();let T=_.dot(v);if(T>-r.crossViewAng&&T<r.crossViewAng){g.visible=!1;return}g.visible=!0,f(_,w.current),g.quaternion.copy(w.current),g.scale.setScalar(r.crossSize)},t[10]=n.direction,t[11]=n.keyframes?.[0],t[12]=r.crossSize,t[13]=r.crossViewAng,t[14]=r.renderCross,t[15]=r.tracerLength,t[16]=r.tracerWidth,t[17]=P):P=t[17],i(P);let F;t[18]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,g.jsx)(`bufferAttribute`,{ref:o,attach:`attributes-position`,args:[new Float32Array(12),3]}),t[18]=F):F=t[18];let I;t[19]===Symbol.for(`react.memo_cache_sentinel`)?(I=(0,g.jsx)(`bufferAttribute`,{attach:`attributes-uv`,args:[new Float32Array([0,0,0,1,1,1,1,0]),2]}),t[19]=I):I=t[19];let L;t[20]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,g.jsxs)(`bufferGeometry`,{children:[F,I,(0,g.jsx)(`bufferAttribute`,{attach:`index`,args:[new Uint16Array([0,1,2,0,2,3]),1]})]}),t[20]=L):L=t[20];let R;t[21]===M?R=t[22]:(R=(0,g.jsxs)(`mesh`,{ref:a,children:[L,(0,g.jsx)(`meshBasicMaterial`,{map:M,transparent:!0,blending:2,side:2,depthWrite:!1,toneMapped:!1})]}),t[21]=M,t[22]=R);let z;t[23]!==N||t[24]!==r.renderCross?(z=r.renderCross?(0,g.jsxs)(`mesh`,{ref:c,children:[(0,g.jsxs)(`bufferGeometry`,{children:[(0,g.jsx)(`bufferAttribute`,{attach:`attributes-position`,args:[new Float32Array([-.5,0,-.5,.5,0,-.5,.5,0,.5,-.5,0,.5]),3]}),(0,g.jsx)(`bufferAttribute`,{attach:`attributes-uv`,args:[new Float32Array([0,0,0,1,1,1,1,0]),2]}),(0,g.jsx)(`bufferAttribute`,{attach:`index`,args:[new Uint16Array([0,1,2,0,2,3]),1]})]}),(0,g.jsx)(`meshBasicMaterial`,{map:N,transparent:!0,blending:2,side:2,depthWrite:!1,toneMapped:!1})]}):null,t[23]=N,t[24]=r.renderCross,t[25]=z):z=t[25];let B;return t[26]!==R||t[27]!==z?(B=(0,g.jsxs)(g.Fragment,{children:[R,z]}),t[26]=R,t[27]=z,t[28]=B):B=t[28],B}function D(e){let t=Array.isArray(e)?e:[e];for(let e of t)d(e)}export{w as SpriteProjectile,E as TracerProjectile};
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{i}from"./react-three-fiber.esm-CFJ5mGMW.js";import"./Html-CIkmciH6.js";import"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Dt as a,Ht as o,xt as s,y as c}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import"./engineStore-CLELjjpY.js";import{F as l,V as u,_ as d,g as f,y as p}from"./index-OhjeY6aE.js";var m=t(),h=e(n(),1),g=r(),_=new o,v=new o,y=new o,b=new o,x=new o,S=new o,C=new o(0,1,0);function w(e){let t=(0,m.c)(14),{entity:n}=e,{visual:r}=n,i;t[0]===r.texture?i=t[1]:(i=l(r.texture),t[0]=r.texture,t[1]=i);let o=u(i,T),s=Array.isArray(o)?o[0]:o,d;t[2]!==r.color.b||t[3]!==r.color.g||t[4]!==r.color.r?(d=new c().setRGB(r.color.r,r.color.g,r.color.b,a),t[2]=r.color.b,t[3]=r.color.g,t[4]=r.color.r,t[5]=d):d=t[5];let f=d,p;t[6]===r.size?p=t[7]:(p=[r.size,r.size,1],t[6]=r.size,t[7]=p);let h;t[8]!==f||t[9]!==s?(h=(0,g.jsx)(`spriteMaterial`,{map:s,color:f,transparent:!0,blending:2,depthWrite:!1,toneMapped:!1}),t[8]=f,t[9]=s,t[10]=h):h=t[10];let _;return t[11]!==p||t[12]!==h?(_=(0,g.jsx)(`sprite`,{scale:p,children:h}),t[11]=p,t[12]=h,t[13]=_):_=t[13],_}function T(e){d(Array.isArray(e)?e[0]:e)}function E(e){let t=(0,m.c)(29),{entity:n}=e,{visual:r}=n,a=(0,h.useRef)(null),o=(0,h.useRef)(null),c=(0,h.useRef)(null),d;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(d=new s,t[0]=d):d=t[0];let w=(0,h.useRef)(d),T;t[1]===r.texture?T=t[2]:(T=l(r.texture),t[1]=r.texture,t[2]=T);let E=r.crossTexture??r.texture,O;t[3]===E?O=t[4]:(O=l(E),t[3]=E,t[4]=O);let k;t[5]!==T||t[6]!==O?(k=[T,O],t[5]=T,t[6]=O,t[7]=k):k=t[7];let A=u(k,D),j;t[8]===A?j=t[9]:(j=Array.isArray(A)?A:[A,A],t[8]=A,t[9]=j);let[M,N]=j,P;t[10]!==n.direction||t[11]!==n.keyframes?.[0]||t[12]!==r.crossSize||t[13]!==r.crossViewAng||t[14]!==r.renderCross||t[15]!==r.tracerLength||t[16]!==r.tracerWidth?(P=e=>{let{camera:t}=e,i=a.current,s=o.current;if(!i||!s)return;let l=n.keyframes?.[0],u=l?.position,d=n.direction??l?.velocity;if(!u||!d){i.visible=!1,c.current&&(c.current.visible=!1);return}if(p(d,_),_.lengthSq()<1e-8){i.visible=!1,c.current&&(c.current.visible=!1);return}_.normalize(),i.visible=!0,p(u,S),v.copy(S).sub(t.position),y.crossVectors(v,_),y.lengthSq()<1e-8&&(y.crossVectors(C,_),y.lengthSq()<1e-8&&y.set(1,0,0)),y.normalize().multiplyScalar(r.tracerWidth);let m=r.tracerLength*.5;b.copy(_).multiplyScalar(-m),x.copy(_).multiplyScalar(m);let h=s.array;h[0]=b.x+y.x,h[1]=b.y+y.y,h[2]=b.z+y.z,h[3]=b.x-y.x,h[4]=b.y-y.y,h[5]=b.z-y.z,h[6]=x.x-y.x,h[7]=x.y-y.y,h[8]=x.z-y.z,h[9]=x.x+y.x,h[10]=x.y+y.y,h[11]=x.z+y.z,s.needsUpdate=!0;let g=c.current;if(!g)return;if(!r.renderCross){g.visible=!1;return}v.normalize();let T=_.dot(v);if(T>-r.crossViewAng&&T<r.crossViewAng){g.visible=!1;return}g.visible=!0,f(_,w.current),g.quaternion.copy(w.current),g.scale.setScalar(r.crossSize)},t[10]=n.direction,t[11]=n.keyframes?.[0],t[12]=r.crossSize,t[13]=r.crossViewAng,t[14]=r.renderCross,t[15]=r.tracerLength,t[16]=r.tracerWidth,t[17]=P):P=t[17],i(P);let F;t[18]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,g.jsx)(`bufferAttribute`,{ref:o,attach:`attributes-position`,args:[new Float32Array(12),3]}),t[18]=F):F=t[18];let I;t[19]===Symbol.for(`react.memo_cache_sentinel`)?(I=(0,g.jsx)(`bufferAttribute`,{attach:`attributes-uv`,args:[new Float32Array([0,0,0,1,1,1,1,0]),2]}),t[19]=I):I=t[19];let L;t[20]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,g.jsxs)(`bufferGeometry`,{children:[F,I,(0,g.jsx)(`bufferAttribute`,{attach:`index`,args:[new Uint16Array([0,1,2,0,2,3]),1]})]}),t[20]=L):L=t[20];let R;t[21]===M?R=t[22]:(R=(0,g.jsxs)(`mesh`,{ref:a,children:[L,(0,g.jsx)(`meshBasicMaterial`,{map:M,transparent:!0,blending:2,side:2,depthWrite:!1,toneMapped:!1})]}),t[21]=M,t[22]=R);let z;t[23]!==N||t[24]!==r.renderCross?(z=r.renderCross?(0,g.jsxs)(`mesh`,{ref:c,children:[(0,g.jsxs)(`bufferGeometry`,{children:[(0,g.jsx)(`bufferAttribute`,{attach:`attributes-position`,args:[new Float32Array([-.5,0,-.5,.5,0,-.5,.5,0,.5,-.5,0,.5]),3]}),(0,g.jsx)(`bufferAttribute`,{attach:`attributes-uv`,args:[new Float32Array([0,0,0,1,1,1,1,0]),2]}),(0,g.jsx)(`bufferAttribute`,{attach:`index`,args:[new Uint16Array([0,1,2,0,2,3]),1]})]}),(0,g.jsx)(`meshBasicMaterial`,{map:N,transparent:!0,blending:2,side:2,depthWrite:!1,toneMapped:!1})]}):null,t[23]=N,t[24]=r.renderCross,t[25]=z):z=t[25];let B;return t[26]!==R||t[27]!==z?(B=(0,g.jsxs)(g.Fragment,{children:[R,z]}),t[26]=R,t[27]=z,t[28]=B):B=t[28],B}function D(e){let t=Array.isArray(e)?e:[e];for(let e of t)d(e)}export{w as SpriteProjectile,E as TracerProjectile};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n}from"./jsx-runtime-BpGWiA-R.js";import{i as r,o as i}from"./react-three-fiber.esm-CFJ5mGMW.js";import{r as a}from"./SettingsProvider-CZgYJ4FU.js";import"./traditional-CVpSAKe0.js";import{L as o,t as s}from"./index-DRuEJepN.js";var c=t(),l=e(n(),1),u=.004,d=2.5,f=.08,p=.15,m=.15;function h(){let e=(0,c.c)(17),{speedMultiplier:t,touchMode:n,invertDrag:h,invertJoystick:_}=a(),v=i(g),{moveState:y,lookState:b}=s(),x=o(),S=(0,l.useRef)(null),C;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(C={x:0,y:0},e[0]=C):C=e[0];let w=(0,l.useRef)(C),T;e[1]===h?T=e[2]:(T=()=>h,e[1]=h,e[2]=T);let E=(0,l.useEffectEvent)(T),D=(0,l.useRef)(0),O=(0,l.useRef)(0),k;e[3]!==E||e[4]!==v.domElement||e[5]!==n?(k=()=>{if(n!==`moveLookStick`)return;let e=v.domElement,t=e=>{if(S.current===null)for(;0<e.changedTouches.length;){let t=e.changedTouches[0];S.current=t.identifier,w.current={x:t.clientX,y:t.clientY};break}},r=e=>{if(S.current!==null)for(let t=0;t<e.changedTouches.length;t++){let n=e.changedTouches[t];if(n.identifier===S.current){let e=n.clientX-w.current.x,t=n.clientY-w.current.y;w.current={x:n.clientX,y:n.clientY};let r=E()?-1:1;D.current+=r*e*u,O.current+=r*t*u;break}}},i=e=>{for(let t=0;t<e.changedTouches.length;t++)if(e.changedTouches[t].identifier===S.current){S.current=null;break}};return e.addEventListener(`touchstart`,t,{passive:!0}),e.addEventListener(`touchmove`,r,{passive:!0}),e.addEventListener(`touchend`,i,{passive:!0}),e.addEventListener(`touchcancel`,i,{passive:!0}),()=>{e.removeEventListener(`touchstart`,t),e.removeEventListener(`touchmove`,r),e.removeEventListener(`touchend`,i),e.removeEventListener(`touchcancel`,i),S.current=null}},e[3]=E,e[4]=v.domElement,e[5]=n,e[6]=k):k=e[6];let A;e[7]!==v.domElement||e[8]!==n?(A=[v.domElement,n],e[7]=v.domElement,e[8]=n,e[9]=A):A=e[9],(0,l.useEffect)(k,A);let j;return e[10]!==_||e[11]!==b.current||e[12]!==y.current||e[13]!==x||e[14]!==t||e[15]!==n?(j=(e,r)=>{let{force:i,angle:a}=y.current,{force:o,angle:s}=b.current,c=D.current,l=O.current;D.current=0,O.current=0;let u=0,h=0;if(n===`dualStick`){if(o>p){let e=(o-p)/(1-p),t=Math.cos(s),n=Math.sin(s),i=_?-1:1;c-=i*t*e*d*r,l+=i*n*e*d*r}if(i>f){let e=(i-f)/(1-f),n=Math.cos(a),r=Math.sin(a);u=Math.max(-1,Math.min(1,-n*e*t)),h=Math.max(-1,Math.min(1,r*e*t))}}else if(n===`moveLookStick`&&i>0&&(h=Math.max(-1,Math.min(1,.5*t)),i>=m)){let e=Math.cos(a),t=Math.sin(a),n=(i-m)/(1-m),o=_?-1:1;c-=o*e*n*d*.5*r,l+=o*t*n*d*.5*r}!(c!==0||l!==0)&&!(u!==0||h!==0)||x({deltaYaw:c,deltaPitch:l,x:u,y:h,z:0,triggers:[],delta:r})},e[10]=_,e[11]=b.current,e[12]=y.current,e[13]=x,e[14]=t,e[15]=n,e[16]=j):j=e[16],r(j),null}function g(e){return e.gl}export{h as TouchHandler};
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n}from"./jsx-runtime-BpGWiA-R.js";import{i as r,o as i}from"./react-three-fiber.esm-CFJ5mGMW.js";import{r as a}from"./SettingsProvider-CZgYJ4FU.js";import"./traditional-CVpSAKe0.js";import{L as o,t as s}from"./index-OhjeY6aE.js";var c=t(),l=e(n(),1),u=.004,d=2.5,f=.08,p=.15,m=.15;function h(){let e=(0,c.c)(17),{speedMultiplier:t,touchMode:n,invertDrag:h,invertJoystick:_}=a(),v=i(g),{moveState:y,lookState:b}=s(),x=o(),S=(0,l.useRef)(null),C;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(C={x:0,y:0},e[0]=C):C=e[0];let w=(0,l.useRef)(C),T;e[1]===h?T=e[2]:(T=()=>h,e[1]=h,e[2]=T);let E=(0,l.useEffectEvent)(T),D=(0,l.useRef)(0),O=(0,l.useRef)(0),k;e[3]!==E||e[4]!==v.domElement||e[5]!==n?(k=()=>{if(n!==`moveLookStick`)return;let e=v.domElement,t=e=>{if(S.current===null)for(;0<e.changedTouches.length;){let t=e.changedTouches[0];S.current=t.identifier,w.current={x:t.clientX,y:t.clientY};break}},r=e=>{if(S.current!==null)for(let t=0;t<e.changedTouches.length;t++){let n=e.changedTouches[t];if(n.identifier===S.current){let e=n.clientX-w.current.x,t=n.clientY-w.current.y;w.current={x:n.clientX,y:n.clientY};let r=E()?-1:1;D.current+=r*e*u,O.current+=r*t*u;break}}},i=e=>{for(let t=0;t<e.changedTouches.length;t++)if(e.changedTouches[t].identifier===S.current){S.current=null;break}};return e.addEventListener(`touchstart`,t,{passive:!0}),e.addEventListener(`touchmove`,r,{passive:!0}),e.addEventListener(`touchend`,i,{passive:!0}),e.addEventListener(`touchcancel`,i,{passive:!0}),()=>{e.removeEventListener(`touchstart`,t),e.removeEventListener(`touchmove`,r),e.removeEventListener(`touchend`,i),e.removeEventListener(`touchcancel`,i),S.current=null}},e[3]=E,e[4]=v.domElement,e[5]=n,e[6]=k):k=e[6];let A;e[7]!==v.domElement||e[8]!==n?(A=[v.domElement,n],e[7]=v.domElement,e[8]=n,e[9]=A):A=e[9],(0,l.useEffect)(k,A);let j;return e[10]!==_||e[11]!==b.current||e[12]!==y.current||e[13]!==x||e[14]!==t||e[15]!==n?(j=(e,r)=>{let{force:i,angle:a}=y.current,{force:o,angle:s}=b.current,c=D.current,l=O.current;D.current=0,O.current=0;let u=0,h=0;if(n===`dualStick`){if(o>p){let e=(o-p)/(1-p),t=Math.cos(s),n=Math.sin(s),i=_?-1:1;c-=i*t*e*d*r,l+=i*n*e*d*r}if(i>f){let e=(i-f)/(1-f),n=Math.cos(a),r=Math.sin(a);u=Math.max(-1,Math.min(1,-n*e*t)),h=Math.max(-1,Math.min(1,r*e*t))}}else if(n===`moveLookStick`&&i>0&&(h=Math.max(-1,Math.min(1,.5*t)),i>=m)){let e=Math.cos(a),t=Math.sin(a),n=(i-m)/(1-m),o=_?-1:1;c-=o*e*n*d*.5*r,l+=o*t*n*d*.5*r}!(c!==0||l!==0)&&!(u!==0||h!==0)||x({deltaYaw:c,deltaPitch:l,x:u,y:h,z:0,triggers:[],delta:r})},e[10]=_,e[11]=b.current,e[12]=y.current,e[13]=x,e[14]=t,e[15]=n,e[16]=j):j=e[16],r(j),null}function g(e){return e.gl}export{h as TouchHandler};

View file

@ -1,2 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/nipplejs-CwanlYdg.js","assets/chunk-DECur_0Z.js"])))=>i.map(i=>d[i]);
import{r as e}from"./chunk-DECur_0Z.js";import{r as t,t as n}from"./jsx-runtime-BpGWiA-R.js";import{r}from"./SettingsProvider-CZgYJ4FU.js";import{U as i,t as a}from"./index-DRuEJepN.js";var o=e(t(),1),s={Joystick:`_Joystick_155b9_1`,Left:`_Left_155b9_11 _Joystick_155b9_1`,Right:`_Right_155b9_17 _Joystick_155b9_1`},c=n();function l(e){let t=e.querySelector(`.back`);t&&(t.style.background=`rgba(3, 79, 76, 0.6)`,t.style.border=`1px solid rgba(0, 219, 223, 0.5)`,t.style.boxShadow=`inset 0 0 10px rgba(0, 0, 0, 0.7)`);let n=e.querySelector(`.front`);n&&(n.style.background=`radial-gradient(circle at 50% 50%, rgba(23, 247, 198, 0.9) 0%, rgba(9, 184, 170, 0.95) 100%)`,n.style.border=`2px solid rgba(255, 255, 255, 0.4)`,n.style.boxShadow=`0 2px 4px rgba(0, 0, 0, 0.5), 0 1px 1px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 2px rgba(0, 0, 0, 0.3)`)}function u(){let{touchMode:t}=r(),[n,u]=(0,o.useState)(null),[d,f]=(0,o.useState)(null),{moveState:p,lookState:m,setMoveState:h,setLookState:g}=a();(0,o.useEffect)(()=>{if(!n)return;let t=null,r=!1;return i(()=>import(`./nipplejs-CwanlYdg.js`).then(t=>e(t.default,1)).then(e=>{r||(t=e.default.create({zone:n,mode:`static`,position:{left:`70px`,bottom:`70px`},size:120,restOpacity:.9}),l(n),t.on(`move`,(e,t)=>{h({angle:t.angle.radian,force:Math.min(1,t.force)})}),t.on(`end`,()=>{h({force:0})}))}),__vite__mapDeps([0,1])),()=>{r=!0,t?.destroy()}},[p,n,h]),(0,o.useEffect)(()=>{if(!d)return;let t=null,n=!1;return i(()=>import(`./nipplejs-CwanlYdg.js`).then(t=>e(t.default,1)).then(e=>{n||(t=e.default.create({zone:d,mode:`static`,position:{right:`70px`,bottom:`70px`},size:120,restOpacity:.9}),l(d),t.on(`move`,(e,t)=>{g({angle:t.angle.radian,force:Math.min(1,t.force)})}),t.on(`end`,()=>{g({force:0})}))}),__vite__mapDeps([0,1])),()=>{n=!0,t?.destroy()}},[m,d,g]);let _=()=>{document.activeElement instanceof HTMLElement&&document.activeElement.blur()};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`div`,{ref:u,className:t===`dualStick`?s.Left:s.Joystick,onContextMenu:e=>e.preventDefault(),onTouchStart:_},t),t===`dualStick`?(0,c.jsx)(`div`,{ref:f,className:s.Right,onContextMenu:e=>e.preventDefault(),onTouchStart:_}):null]})}export{u as TouchJoystick};
import{r as e}from"./chunk-DECur_0Z.js";import{r as t,t as n}from"./jsx-runtime-BpGWiA-R.js";import{r}from"./SettingsProvider-CZgYJ4FU.js";import{U as i,t as a}from"./index-OhjeY6aE.js";var o=e(t(),1),s={Joystick:`_Joystick_155b9_1`,Left:`_Left_155b9_11 _Joystick_155b9_1`,Right:`_Right_155b9_17 _Joystick_155b9_1`},c=n();function l(e){let t=e.querySelector(`.back`);t&&(t.style.background=`rgba(3, 79, 76, 0.6)`,t.style.border=`1px solid rgba(0, 219, 223, 0.5)`,t.style.boxShadow=`inset 0 0 10px rgba(0, 0, 0, 0.7)`);let n=e.querySelector(`.front`);n&&(n.style.background=`radial-gradient(circle at 50% 50%, rgba(23, 247, 198, 0.9) 0%, rgba(9, 184, 170, 0.95) 100%)`,n.style.border=`2px solid rgba(255, 255, 255, 0.4)`,n.style.boxShadow=`0 2px 4px rgba(0, 0, 0, 0.5), 0 1px 1px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 2px rgba(0, 0, 0, 0.3)`)}function u(){let{touchMode:t}=r(),[n,u]=(0,o.useState)(null),[d,f]=(0,o.useState)(null),{moveState:p,lookState:m,setMoveState:h,setLookState:g}=a();(0,o.useEffect)(()=>{if(!n)return;let t=null,r=!1;return i(()=>import(`./nipplejs-CwanlYdg.js`).then(t=>e(t.default,1)).then(e=>{r||(t=e.default.create({zone:n,mode:`static`,position:{left:`70px`,bottom:`70px`},size:120,restOpacity:.9}),l(n),t.on(`move`,(e,t)=>{h({angle:t.angle.radian,force:Math.min(1,t.force)})}),t.on(`end`,()=>{h({force:0})}))}),__vite__mapDeps([0,1])),()=>{r=!0,t?.destroy()}},[p,n,h]),(0,o.useEffect)(()=>{if(!d)return;let t=null,n=!1;return i(()=>import(`./nipplejs-CwanlYdg.js`).then(t=>e(t.default,1)).then(e=>{n||(t=e.default.create({zone:d,mode:`static`,position:{right:`70px`,bottom:`70px`},size:120,restOpacity:.9}),l(d),t.on(`move`,(e,t)=>{g({angle:t.angle.radian,force:Math.min(1,t.force)})}),t.on(`end`,()=>{g({force:0})}))}),__vite__mapDeps([0,1])),()=>{n=!0,t?.destroy()}},[m,d,g]);let _=()=>{document.activeElement instanceof HTMLElement&&document.activeElement.blur()};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`div`,{ref:u,className:t===`dualStick`?s.Left:s.Joystick,onContextMenu:e=>e.preventDefault(),onTouchStart:_},t),t===`dualStick`?(0,c.jsx)(`div`,{ref:f,className:s.Right,onContextMenu:e=>e.preventDefault(),onTouchStart:_}):null]})}export{u as TouchJoystick};

View file

@ -1,166 +0,0 @@
import{r as e}from"./chunk-DECur_0Z.js";import{n as t,r as n,t as r}from"./jsx-runtime-BpGWiA-R.js";import{i,o as a}from"./react-three-fiber.esm-CFJ5mGMW.js";import{a as o,i as s}from"./SettingsProvider-CZgYJ4FU.js";import"./logger-CiAJCFpz.js";import"./traditional-CVpSAKe0.js";import{Et as c,ht as l,kt as u,y as d}from"./three.module-CqFTqVus.js";import"./mission-BLbEDC74.js";import{t as f}from"./extends-CNSZZ44D.js";import{D as p,F as m,V as h,b as g,k as _,nt as v,rt as ee,tt as te,x as y}from"./index-DRuEJepN.js";var b=e(n());function x(e,t){let n=e+`Geometry`;return b.forwardRef(({args:e,children:r,...i},a)=>{let o=b.useRef(null);return b.useImperativeHandle(a,()=>o.current),b.useLayoutEffect(()=>void t?.(o.current)),b.createElement(`mesh`,f({ref:o},i),b.createElement(n,{attach:`geometry`,args:e}),r)})}var ne=x(`box`),S=t(),C=`
#include <fog_pars_vertex>
#ifdef USE_FOG
#define USE_FOG_WORLD_POSITION
varying vec3 vFogWorldPosition;
#endif
uniform float uTime;
uniform float uWaveMagnitude;
varying vec3 vWorldPosition;
varying vec3 vViewVector;
varying float vDistance;
// Wave function matching Tribes 2 engine
// Z = surfaceZ + (sin(X*0.05 + time) + sin(Y*0.05 + time)) * waveFactor
// waveFactor = waveAmplitude * 0.25
// Note: Using xz for Three.js Y-up (Torque uses XY with Z-up)
float getWaveHeight(vec3 worldPos) {
float waveFactor = uWaveMagnitude * 0.25;
return (sin(worldPos.x * 0.05 + uTime) + sin(worldPos.z * 0.05 + uTime)) * waveFactor;
}
void main() {
// Get world position for wave calculation
vec4 worldPos = modelMatrix * vec4(position, 1.0);
vWorldPosition = worldPos.xyz;
// Apply wave displacement to Y (vertical axis in Three.js)
vec3 displaced = position;
displaced.y += getWaveHeight(worldPos.xyz);
// Calculate final world position after displacement for fog
#ifdef USE_FOG
vec4 displacedWorldPos = modelMatrix * vec4(displaced, 1.0);
vFogWorldPosition = displacedWorldPos.xyz;
#endif
// Calculate view vector for environment mapping
vViewVector = cameraPosition - worldPos.xyz;
vDistance = length(vViewVector);
vec4 mvPosition = viewMatrix * modelMatrix * vec4(displaced, 1.0);
gl_Position = projectionMatrix * mvPosition;
// Set fog depth (distance from camera) - normally done by fog_vertex include
// but we can't use that include because it references 'transformed' which we don't have
#ifdef USE_FOG
vFogDepth = length(mvPosition.xyz);
#endif
}
`,re=`
#include <fog_pars_fragment>
// Enable volumetric fog (must be defined before fog uniforms)
#ifdef USE_FOG
#define USE_VOLUMETRIC_FOG
#define USE_FOG_WORLD_POSITION
#endif
uniform float uTime;
uniform float uOpacity;
uniform float uEnvMapIntensity;
uniform sampler2D uBaseTexture;
uniform sampler2D uEnvMapTexture;
// Volumetric fog uniforms
#ifdef USE_FOG
uniform float fogVolumeData[12];
uniform float cameraHeight;
uniform bool fogEnabled;
varying vec3 vFogWorldPosition;
#endif
varying vec3 vWorldPosition;
varying vec3 vViewVector;
varying float vDistance;
#define TWO_PI 6.283185307179586
// Constants from Tribes 2 engine
#define BASE_DRIFT_CYCLE_TIME 8.0
#define BASE_DRIFT_RATE 0.02
#define BASE_DRIFT_SCALAR 0.03
#define TEXTURE_SCALE (1.0 / 48.0)
// Environment map UV wobble constants
#define Q1 150.0
#define Q2 2.0
#define Q3 0.01
// Rotate UV coordinates
vec2 rotateUV(vec2 uv, float angle) {
float c = cos(angle);
float s = sin(angle);
return vec2(
uv.x * c - uv.y * s,
uv.x * s + uv.y * c
);
}
void main() {
// Calculate base texture UVs using world position (1/48 tiling)
vec2 baseUV = vWorldPosition.xz * TEXTURE_SCALE;
// Phase (time in radians for drift cycle)
float phase = mod(uTime * (TWO_PI / BASE_DRIFT_CYCLE_TIME), TWO_PI);
// Base texture drift
float baseDriftX = uTime * BASE_DRIFT_RATE;
float baseDriftY = cos(phase) * BASE_DRIFT_SCALAR;
// === Phase 1a: First base texture pass (rotated 30 degrees) ===
vec2 uv1a = rotateUV(baseUV, radians(30.0));
// === Phase 1b: Second base texture pass (rotated 60 degrees total, with drift) ===
vec2 uv1b = rotateUV(baseUV + vec2(baseDriftX, baseDriftY), radians(60.0));
// Calculate cross-fade swing value
float A1 = cos(((vWorldPosition.x / Q1) + (uTime / Q2)) * 6.0);
float A2 = sin(((vWorldPosition.z / Q1) + (uTime / Q2)) * TWO_PI);
float swing = (A1 + A2) * 0.15 + 0.5;
// Cross-fade alpha calculation from engine
float alpha1a = ((1.0 - swing) * uOpacity) / max(1.0 - (swing * uOpacity), 0.001);
float alpha1b = swing * uOpacity;
// Sample base texture for both passes
vec4 texColor1a = texture2D(uBaseTexture, uv1a);
vec4 texColor1b = texture2D(uBaseTexture, uv1b);
// Combined alpha and color
float combinedAlpha = 1.0 - (1.0 - alpha1a) * (1.0 - alpha1b);
vec3 baseColor = (texColor1a.rgb * alpha1a * (1.0 - alpha1b) + texColor1b.rgb * alpha1b) / max(combinedAlpha, 0.001);
// === Phase 3: Environment map / specular ===
vec3 reflectVec = -vViewVector;
reflectVec.y = abs(reflectVec.y);
if (reflectVec.y < 0.001) reflectVec.y = 0.001;
vec2 envUV;
if (vDistance < 0.001) {
envUV = vec2(0.0);
} else {
float value = (vDistance - reflectVec.y) / (vDistance * vDistance);
envUV.x = reflectVec.x * value;
envUV.y = reflectVec.z * value;
}
envUV = envUV * 0.5 + 0.5;
envUV.x += A1 * Q3;
envUV.y += A2 * Q3;
vec4 envColor = texture2D(uEnvMapTexture, envUV);
vec3 finalColor = baseColor + envColor.rgb * envColor.a * uEnvMapIntensity;
// Note: Tribes 2 water does NOT use lighting - Phase 2 (lightmap) is disabled
// in the original engine. Water colors come directly from textures.
gl_FragColor = vec4(finalColor, combinedAlpha);
// Apply volumetric fog using shared Torque-style fog shader
${y}
}
`;function w(e){return new u({uniforms:{uTime:{value:0},uOpacity:{value:e?.opacity??.75},uWaveMagnitude:{value:e?.waveMagnitude??1},uEnvMapIntensity:{value:e?.envMapIntensity??1},uBaseTexture:{value:e?.baseTexture??null},uEnvMapTexture:{value:e?.envMapTexture??null},fogColor:{value:new d},fogNear:{value:1},fogFar:{value:2e3},fogVolumeData:g.fogVolumeData,cameraHeight:g.cameraHeight,fogEnabled:g.fogEnabled},vertexShader:C,fragmentShader:re,transparent:!0,side:2,depthWrite:!0,fog:!0})}function ie(){let e=(0,S.c)(1),t=(0,b.useRef)(null),n;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(n=e=>{if(!t.current)return t.current=e.clone(),!0;let n=t.current.x===e.x&&t.current.y===e.y&&t.current.z===e.z;return n||t.current.copy(e),n},e[0]=n):n=e[0],n}var T=r(),E=2048,D=1024;function ae(e,t){let n=e<=1024&&t<=1024?8:16;return[Math.max(4,Math.ceil(e/n)),Math.max(4,Math.ceil(t/n))]}function oe(e){let t=(0,S.c)(7),{surfaceTexture:n,attach:r}=e,i;t[0]===n?i=t[1]:(i=m(n),t[0]=n,t[1]=i);let a=i,o=p(),s;t[2]===o?s=t[3]:(s=e=>_(e,{anisotropy:o}),t[2]=o,t[3]=s);let c=h(a,s),l;return t[4]!==r||t[5]!==c?(l=(0,T.jsx)(`meshStandardMaterial`,{attach:r,map:c,transparent:!0,opacity:.8,side:2}),t[4]=r,t[5]=c,t[6]=l):l=t[6],l}var O=(0,b.memo)(function(e){let t=(0,S.c)(59),{entity:n}=e,r=n.waterData,{debugMode:o}=s(),c;t[0]===r.transform?c=t[1]:(c=te(r.transform),t[0]=r.transform,t[1]=c);let u=c,d;t[2]===r.transform.position?d=t[3]:(d=ee(r.transform.position),t[2]=r.transform.position,t[3]=d);let f=d,p;t[4]===r.scale?p=t[5]:(p=v(r.scale),t[4]=r.scale,t[5]=p);let m=p,[h,g,_]=m,y=a(ce),x=ie(),C=r.waveMagnitude,[re,w,oe]=f,O=re+D,k=oe+D,A;t[6]===O?A=t[7]:(A=Math.round(O/8),t[6]=O,t[7]=A);let j=A,M;t[8]===k?M=t[9]:(M=Math.round(k/8),t[8]=k,t[9]=M);let N=M;j=Math.max(0,Math.min(2040,j)),N=Math.max(0,Math.min(2040,N));let P=j*8,F=N*8,I;t[10]!==P||t[11]!==F||t[12]!==w?(I=[P,w,F],t[10]=P,t[11]=F,t[12]=w,t[13]=I):I=t[13];let L=I,ue=le,R;t[14]!==y.position.x||t[15]!==y.position.z?(R=()=>ue(y.position.x,y.position.z),t[14]=y.position.x,t[15]=y.position.z,t[16]=R):R=t[16];let[z,de]=(0,b.useState)(R),B;t[17]!==y.position||t[18]!==x?(B=()=>{if(!x(y.position))return;let e=ue(y.position.x,y.position.z);de(t=>JSON.stringify(t)===JSON.stringify(e)?t:e)},t[17]=y.position,t[18]=x,t[19]=B):B=t[19],i(B);let V=r.surfaceName||`liquidTiles/BlueWater`,H=r.envMapName||void 0,U=r.surfaceOpacity,W=r.envMapIntensity,G;if(t[20]!==h||t[21]!==g||t[22]!==_){let[e,n]=ae(h,_);G=new l(h,_,e,n),G.rotateX(-Math.PI/2),G.translate(h/2,g,_/2),t[20]=h,t[21]=g,t[22]=_,t[23]=G}else G=t[23];let K=G,q,J;t[24]===K?(q=t[25],J=t[26]):(J=()=>()=>{K.dispose()},q=[K],t[24]=K,t[25]=q,t[26]=J),(0,b.useEffect)(J,q);let Y;t[27]!==o||t[28]!==f[0]||t[29]!==f[1]||t[30]!==f[2]||t[31]!==m||t[32]!==h||t[33]!==g||t[34]!==_?(Y=o&&(0,T.jsx)(ne,{args:m,position:[f[0]+h/2,f[1]+g/2,f[2]+_/2],children:(0,T.jsx)(`meshBasicMaterial`,{color:`#00fbff`,wireframe:!0})}),t[27]=o,t[28]=f[0],t[29]=f[1],t[30]=f[2],t[31]=m,t[32]=h,t[33]=g,t[34]=_,t[35]=Y):Y=t[35];let X;if(t[36]!==L||t[37]!==z||t[38]!==K){let e;t[40]!==L||t[41]!==K?(e=e=>{let[t,n]=e,r=L[0]+t*E-D,i=L[2]+n*E-D;return(0,T.jsx)(`mesh`,{geometry:K,position:[r,L[1],i],children:(0,T.jsx)(`meshStandardMaterial`,{color:`#00fbff`,transparent:!0,opacity:.4,wireframe:!0,side:2})},`${t},${n}`)},t[40]=L,t[41]=K,t[42]=e):e=t[42],X=z.map(e),t[36]=L,t[37]=z,t[38]=K,t[39]=X}else X=t[39];let Z;t[43]!==L||t[44]!==W||t[45]!==H||t[46]!==U||t[47]!==z||t[48]!==K||t[49]!==V||t[50]!==C?(Z=(0,T.jsx)(se,{reps:z,basePosition:L,surfaceGeometry:K,surfaceTexture:V,envMapTexture:H,opacity:U,waveMagnitude:C,envMapIntensity:W}),t[43]=L,t[44]=W,t[45]=H,t[46]=U,t[47]=z,t[48]=K,t[49]=V,t[50]=C,t[51]=Z):Z=t[51];let Q;t[52]!==X||t[53]!==Z?(Q=(0,T.jsx)(b.Suspense,{fallback:X,children:Z}),t[52]=X,t[53]=Z,t[54]=Q):Q=t[54];let $;return t[55]!==u||t[56]!==Y||t[57]!==Q?($=(0,T.jsxs)(`group`,{quaternion:u,children:[Y,Q]}),t[55]=u,t[56]=Y,t[57]=Q,t[58]=$):$=t[58],$}),se=(0,b.memo)(function({reps:e,basePosition:t,surfaceGeometry:n,surfaceTexture:r,envMapTexture:a,opacity:s,waveMagnitude:l,envMapIntensity:u}){let d=m(r),f=m(a??`special/lush_env`),g=p(),[v,ee]=h([d,f],e=>{(Array.isArray(e)?e:[e]).forEach(e=>{_(e,{anisotropy:g}),e.colorSpace=``,e.wrapS=c,e.wrapT=c})}),{animationEnabled:te}=o(),y=(0,b.useMemo)(()=>w({opacity:s,waveMagnitude:l,envMapIntensity:u,baseTexture:v,envMapTexture:ee}),[s,l,u,v,ee]),x=(0,b.useRef)(0);return i((e,t)=>{te?(x.current+=t,y.uniforms.uTime.value=x.current):(x.current=0,y.uniforms.uTime.value=0)}),(0,b.useEffect)(()=>()=>{y.dispose()},[y]),(0,T.jsx)(T.Fragment,{children:e.map(([e,r])=>{let i=t[0]+e*E-D,a=t[2]+r*E-D;return(0,T.jsx)(`mesh`,{geometry:n,material:y,position:[i,t[1],a]},`${e},${r}`)})})});function ce(e){return e.camera}function le(e,t){let n=e+D,r=t+D,i=Math.trunc(n/E),a=Math.trunc(r/E);n<0&&i--,r<0&&a--;let o=[];for(let e=a-1;e<=a+1;e++)for(let t=i-1;t<=i+1;t++)o.push([t,e]);return o}export{O as WaterBlock,oe as WaterMaterial};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -9,7 +9,7 @@
/>
<meta name="description" content="Tribes 2 forever." />
<link rel="icon" type="image/png" href="/t2-mapper/icon.png" />
<script type="module" crossorigin src="/t2-mapper/assets/index-DRuEJepN.js"></script>
<script type="module" crossorigin src="/t2-mapper/assets/index-OhjeY6aE.js"></script>
<link rel="modulepreload" crossorigin href="/t2-mapper/assets/chunk-DECur_0Z.js">
<link rel="modulepreload" crossorigin href="/t2-mapper/assets/logger-CiAJCFpz.js">
<link rel="modulepreload" crossorigin href="/t2-mapper/assets/mission-BLbEDC74.js">

View file

@ -17,7 +17,7 @@ import {
BufferGeometry,
Group,
} from "three";
import type { AnimationAction } from "three";
import type { AnimationAction, Material } from "three";
import * as SkeletonUtils from "three/examples/jsm/utils/SkeletonUtils.js";
import { setupTexture } from "../textureUtils";
import { useAnisotropy } from "./useAnisotropy";
@ -84,19 +84,27 @@ type MaterialResult =
| SingleMaterial
| [MeshLambertMaterial, MeshLambertMaterial];
// Stable onBeforeCompile callbacks — using shared function references lets
// Three.js's program cache match by identity rather than toString().
const lambertBeforeCompile: Material["onBeforeCompile"] = (shader) => {
injectCustomFog(shader, globalFogUniforms);
injectShapeLighting(shader);
};
const basicBeforeCompile: Material["onBeforeCompile"] = (shader) => {
injectCustomFog(shader, globalFogUniforms);
};
/**
* Helper to apply volumetric fog and lighting multipliers to a material
* Helper to apply volumetric fog and lighting multipliers to a material.
*/
export function applyShapeShaderModifications(
mat: MeshBasicMaterial | MeshLambertMaterial,
): void {
mat.onBeforeCompile = (shader) => {
injectCustomFog(shader, globalFogUniforms);
// Only inject lighting for Lambert materials (Basic materials are unlit)
if (mat instanceof MeshLambertMaterial) {
injectShapeLighting(shader);
}
};
mat.onBeforeCompile =
mat instanceof MeshLambertMaterial
? lambertBeforeCompile
: basicBeforeCompile;
}
export function createMaterialFromFlags(

View file

@ -57,22 +57,23 @@ export function ScoreScreen({ onClose }: { onClose: () => void }) {
const dialogRef = useRef<HTMLDivElement>(null);
const dataSource = useDataSource();
const isLive = dataSource === "live";
const connectedClientId = useEngineSelector(
(state) => state.playback.streamSnapshot?.connectedClientId,
);
const teamScores = useEngineSelector(
(state) => state.playback.streamSnapshot?.teamScores,
);
const playerRoster = useEngineSelector(
(state) => state.playback.streamSnapshot?.playerRoster,
);
const playerSensorGroup = useEngineSelector(
(state) => state.playback.streamSnapshot?.playerSensorGroup,
);
const matchClockMs = useEngineSelector(
(state) => state.playback.streamSnapshot?.matchClockMs,
);
const { connectedClientId, teamScores, playerRoster, matchClockMs } =
useEngineSelector(
(state) => {
const snap = state.playback.streamSnapshot;
return {
connectedClientId: snap?.connectedClientId,
teamScores: snap?.teamScores,
playerRoster: snap?.playerRoster,
matchClockMs: snap?.matchClockMs,
};
},
(a, b) =>
a.connectedClientId === b.connectedClientId &&
a.teamScores === b.teamScores &&
a.playerRoster === b.playerRoster &&
a.matchClockMs === b.matchClockMs,
);
// Focus and exit pointer lock on open
useEffect(() => {

View file

@ -1,4 +1,4 @@
import { memo, useEffect, useMemo, useRef, useState } from "react";
import { memo, useEffect, useMemo, useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useQuery } from "@tanstack/react-query";
import {
@ -7,7 +7,9 @@ import {
DataTexture,
Float32BufferAttribute,
FloatType,
InstancedMesh as ThreeInstancedMesh,
LinearFilter,
Matrix4,
NearestFilter,
NoColorSpace,
ClampToEdgeWrapping,
@ -25,7 +27,7 @@ import { useSceneSky, useSceneSun } from "../state/gameEntityStore";
import { loadTerrain } from "../loaders";
import { uint16ToFloat32 } from "../arrayUtils";
import { setupMask } from "../textureUtils";
import { TerrainTile } from "./TerrainTile";
import { TerrainTile, TerrainMaterial } from "./TerrainTile";
import {
createTerrainHeightSampler,
setTerrainHeightSampler,
@ -447,10 +449,6 @@ function useVisibleDistance(): number {
? sky.visibleDistance
: DEFAULT_VISIBLE_DISTANCE;
}
interface TileAssignment {
tileX: number;
tileZ: number;
}
/**
* Create a visibility mask texture from emptySquares data.
*/
@ -574,27 +572,33 @@ export const TerrainBlock = memo(function TerrainBlock({
const gridSize = 2 * extent + 1;
return gridSize * gridSize - 1; // -1 because primary tile is separate
}, [visibleDistance, blockSize]);
// Create stable pool indices for React keys
const poolIndices = useMemo(
() => Array.from({ length: poolSize }, (_, i) => i),
[poolSize],
);
// Track which tile coordinate each pool slot is assigned to
const [tileAssignments, setTileAssignments] = useState<
(TileAssignment | null)[]
>(() => Array(poolSize).fill(null));
// Track previous tile bounds to avoid unnecessary state updates
const prevBoundsRef = useRef({ xStart: 0, xEnd: 0, zStart: 0, zEnd: 0 });
// InstancedMesh ref and reusable matrix for pooled terrain tiles.
const pooledMeshRef = useRef<ThreeInstancedMesh>(null);
const _tileMatrix = useMemo(() => new Matrix4(), []);
// Track previous tile bounds to avoid unnecessary instance matrix updates.
const prevBoundsRef = useRef({
xStart: Infinity,
xEnd: -Infinity,
zStart: Infinity,
zEnd: -Infinity,
});
// Track which mesh instance we last updated — when r3f recreates the
// InstancedMesh (e.g. poolSize changes), we must force a full update
// even if the camera bounds haven't changed.
const lastMeshRef = useRef<ThreeInstancedMesh | null>(null);
useFrame(() => {
const mesh = pooledMeshRef.current;
if (!mesh) return;
const relativeCamX = camera.position.x - basePosition.x;
const relativeCamZ = camera.position.z - basePosition.z;
const xStart = Math.floor((relativeCamX - visibleDistance) / blockSize);
const xEnd = Math.ceil((relativeCamX + visibleDistance) / blockSize);
const zStart = Math.floor((relativeCamZ - visibleDistance) / blockSize);
const zEnd = Math.ceil((relativeCamZ + visibleDistance) / blockSize);
// Early exit if bounds haven't changed
// Early exit if bounds haven't changed AND we're still on the same mesh.
const prev = prevBoundsRef.current;
if (
mesh === lastMeshRef.current &&
xStart === prev.xStart &&
xEnd === prev.xEnd &&
zStart === prev.zStart &&
@ -602,22 +606,27 @@ export const TerrainBlock = memo(function TerrainBlock({
) {
return;
}
lastMeshRef.current = mesh;
prev.xStart = xStart;
prev.xEnd = xEnd;
prev.zStart = zStart;
prev.zEnd = zEnd;
// Build new assignments array
const newAssignments: (TileAssignment | null)[] = [];
const geometryOffset = blockSize / 2;
let count = 0;
for (let x = xStart; x < xEnd; x++) {
for (let z = zStart; z < zEnd; z++) {
if (x === 0 && z === 0) continue;
newAssignments.push({ tileX: x, tileZ: z });
_tileMatrix.makeTranslation(
basePosition.x + x * blockSize + geometryOffset,
0,
basePosition.z + z * blockSize + geometryOffset,
);
mesh.setMatrixAt(count, _tileMatrix);
count++;
}
}
while (newAssignments.length < poolSize) {
newAssignments.push(null);
}
setTileAssignments(newAssignments);
mesh.count = count;
mesh.instanceMatrix.needsUpdate = true;
});
if (
!terrain ||
@ -650,27 +659,25 @@ export const TerrainBlock = memo(function TerrainBlock({
detailTextureName={detailTexture}
lightmap={terrainLightmap}
/>
{/* Pooled tiles - stable keys, always mounted */}
{poolIndices.map((poolIndex) => {
const assignment = tileAssignments[poolIndex];
return (
<TerrainTile
key={poolIndex}
tileX={assignment?.tileX ?? 0}
tileZ={assignment?.tileZ ?? 0}
blockSize={blockSize}
basePosition={basePosition}
textureNames={terrain.textureNames}
geometry={sharedGeometry}
displacementMap={sharedDisplacementMap}
visibilityMask={pooledVisibilityMask}
alphaTextures={sharedAlphaTextures}
detailTextureName={detailTexture}
lightmap={terrainLightmap}
visible={assignment !== null}
/>
);
})}
{/* Pooled tiles single InstancedMesh, matrices updated in useFrame.
All pooled tiles share the same geometry, material, and visibility mask.
Only position differs (set via instance matrices). */}
<instancedMesh
ref={pooledMeshRef}
args={[sharedGeometry, undefined, poolSize]}
castShadow
receiveShadow
frustumCulled={false}
>
<TerrainMaterial
displacementMap={sharedDisplacementMap}
visibilityMask={pooledVisibilityMask}
textureNames={terrain.textureNames}
alphaTextures={sharedAlphaTextures}
detailTextureName={detailTexture}
lightmap={terrainLightmap}
/>
</instancedMesh>
</>
);
});

View file

@ -140,7 +140,7 @@ const BlendedTerrainTextures = memo(function BlendedTerrainTextures({
);
});
const TerrainMaterial = memo(function TerrainMaterial({
export const TerrainMaterial = memo(function TerrainMaterial({
displacementMap,
visibilityMask,
textureNames,

View file

@ -1,7 +1,14 @@
import { memo, Suspense, useEffect, useMemo, useRef, useState } from "react";
import { Box, useTexture } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { DoubleSide, NoColorSpace, PlaneGeometry, RepeatWrapping } from "three";
import {
DoubleSide,
InstancedMesh as ThreeInstancedMesh,
Matrix4,
NoColorSpace,
PlaneGeometry,
RepeatWrapping,
} from "three";
import { textureToUrl } from "../loaders";
import {
torqueToThree,
@ -191,7 +198,10 @@ export const WaterBlock = memo(function WaterBlock({
// Only update state if reps actually changed (avoid unnecessary re-renders)
setReps((prevReps) => {
if (JSON.stringify(prevReps) === JSON.stringify(newReps)) {
if (
prevReps.length === newReps.length &&
prevReps.every((r, i) => r[0] === newReps[i][0] && r[1] === newReps[i][1])
) {
return prevReps;
}
return newReps;
@ -335,8 +345,14 @@ const WaterReps = memo(function WaterReps({
});
}, [opacity, waveMagnitude, envMapIntensity, baseTexture, envTexture]);
// Single animation loop for the shared material
// Single animation loop for the shared material + instance matrix updates.
const elapsedRef = useRef(0);
const meshRef = useRef<ThreeInstancedMesh>(null);
const matrixRef = useRef(new Matrix4());
// Track which mesh + reps we last populated — forces a full update when
// r3f recreates the InstancedMesh or when reps change (camera moves).
const lastMeshRef = useRef<ThreeInstancedMesh | null>(null);
const lastRepsRef = useRef<Array<[number, number]> | null>(null);
useFrame((_, delta) => {
if (!animationEnabled) {
@ -346,6 +362,23 @@ const WaterReps = memo(function WaterReps({
elapsedRef.current += delta;
material.uniforms.uTime.value = elapsedRef.current;
}
// Update instance matrices when reps change or mesh is recreated.
const mesh = meshRef.current;
if (!mesh) return;
if (mesh === lastMeshRef.current && reps === lastRepsRef.current) return;
lastMeshRef.current = mesh;
lastRepsRef.current = reps;
const mat = matrixRef.current;
for (let i = 0; i < reps.length; i++) {
const [repX, repZ] = reps[i];
const worldX = basePosition[0] + repX * REP_SIZE - TERRAIN_OFFSET;
const worldZ = basePosition[2] + repZ * REP_SIZE - TERRAIN_OFFSET;
mat.makeTranslation(worldX, basePosition[1], worldZ);
mesh.setMatrixAt(i, mat);
}
mesh.count = reps.length;
mesh.instanceMatrix.needsUpdate = true;
});
useEffect(() => {
@ -355,21 +388,10 @@ const WaterReps = memo(function WaterReps({
}, [material]);
return (
<>
{reps.map(([repX, repZ]) => {
// Convert from terrain space to world space by subtracting TERRAIN_OFFSET
// Matches Torque's L2Wm transform: L2Wv = (-1024, -1024, 0)
const worldX = basePosition[0] + repX * REP_SIZE - TERRAIN_OFFSET;
const worldZ = basePosition[2] + repZ * REP_SIZE - TERRAIN_OFFSET;
return (
<mesh
key={`${repX},${repZ}`}
geometry={surfaceGeometry}
material={material}
position={[worldX, basePosition[1], worldZ]}
/>
);
})}
</>
<instancedMesh
ref={meshRef}
args={[surfaceGeometry, material, 9]}
frustumCulled={false}
/>
);
});

View file

@ -189,7 +189,11 @@ export const fogVertexShader = `
export const fogVertexShaderWorldPos = `
#ifdef USE_FOG
vFogWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
vec4 _fogPos = vec4(position, 1.0);
#ifdef USE_INSTANCING
_fogPos = instanceMatrix * _fogPos;
#endif
vFogWorldPosition = (modelMatrix * _fogPos).xyz;
#endif
`;
@ -243,7 +247,11 @@ export function installCustomFogShader(): void {
// This ensures fog doesn't change when rotating the camera
vFogDepth = length(mvPosition.xyz);
#ifdef USE_FOG_WORLD_POSITION
vFogWorldPosition = (modelMatrix * vec4(transformed, 1.0)).xyz;
vec4 _fogPos2 = vec4(transformed, 1.0);
#ifdef USE_INSTANCING
_fogPos2 = instanceMatrix * _fogPos2;
#endif
vFogWorldPosition = (modelMatrix * _fogPos2).xyz;
#endif
#endif
`;
@ -310,7 +318,11 @@ export function injectCustomFog(
"#include <fog_vertex>",
`#include <fog_vertex>
#ifdef USE_FOG
vFogWorldPosition = (modelMatrix * vec4(transformed, 1.0)).xyz;
vec4 _fogPos3 = vec4(transformed, 1.0);
#ifdef USE_INSTANCING
_fogPos3 = instanceMatrix * _fogPos3;
#endif
vFogWorldPosition = (modelMatrix * _fogPos3).xyz;
#endif`,
);

View file

@ -1,3 +1,4 @@
import { useMemo } from "react";
import { createStore } from "zustand/vanilla";
import { subscribeWithSelector } from "zustand/middleware";
import { useStoreWithEqualityFn } from "zustand/traditional";
@ -375,11 +376,11 @@ export function useRuntimeObjectById(
id == null ? -1 : (state.runtime.objectVersionById[id] ?? -1),
);
if (id == null || !runtime || version === -1) {
return undefined;
}
const object = runtime.state.objectsById.get(id);
return object ? { ...object } : undefined;
return useMemo(() => {
if (id == null || !runtime || version === -1) return undefined;
const object = runtime.state.objectsById.get(id);
return object ? { ...object } : undefined;
}, [id, runtime, version]);
}
export function useRuntimeObjectField<T = any>(
@ -431,11 +432,13 @@ export function useRuntimeObjectByName(
objectId == null ? -1 : (state.runtime.objectVersionById[objectId] ?? -1),
);
if (!runtime || !normalizedName || objectId == null || version === -1) {
return undefined;
}
const object = runtime.state.objectsById.get(objectId);
return object ? { ...object } : undefined;
return useMemo(() => {
if (!runtime || !normalizedName || objectId == null || version === -1) {
return undefined;
}
const object = runtime.state.objectsById.get(objectId);
return object ? { ...object } : undefined;
}, [runtime, normalizedName, objectId, version]);
}
export function useDatablockByName(
@ -452,11 +455,13 @@ export function useDatablockByName(
objectId == null ? -1 : (state.runtime.objectVersionById[objectId] ?? -1),
);
if (!runtime || !normalizedName || objectId == null || version === -1) {
return undefined;
}
const object = runtime.state.objectsById.get(objectId);
return object ? { ...object } : undefined;
return useMemo(() => {
if (!runtime || !normalizedName || objectId == null || version === -1) {
return undefined;
}
const object = runtime.state.objectsById.get(objectId);
return object ? { ...object } : undefined;
}, [runtime, normalizedName, objectId, version]);
}
export function useRuntimeChildIds(

View file

@ -29,6 +29,26 @@ export class LiveStreamAdapter extends StreamEngine {
private _snapshot: StreamSnapshot | null = null;
private _snapshotTick = -1;
private _ready = false;
// Generation counters for HUD caching in buildSnapshot() — avoids
// rebuilding arrays every tick when HUD state hasn't changed.
private _teamScoresGen = 0;
private _rosterGen = 0;
private _weaponsHudGen = 0;
private _inventoryHudGen = 0;
private _cachedHud: {
teamScoresGen: number;
rosterGen: number;
weaponsHudGen: number;
inventoryHudGen: number;
weaponsHud: StreamSnapshot["weaponsHud"];
inventoryHud: StreamSnapshot["inventoryHud"];
backpackPackIndex: number;
backpackActive: boolean;
backpackHud: StreamSnapshot["backpackHud"];
teamScores: StreamSnapshot["teamScores"];
playerRoster: StreamSnapshot["playerRoster"];
} | null = null;
/** Class names for datablocks, tracked from SimDataBlockEvents. */
private dataBlockClassNames = new Map<number, string>();
@ -101,6 +121,24 @@ export class LiveStreamAdapter extends StreamEngine {
return [...shapes];
}
// ── Generation counter hooks ──
protected onTeamScoresChanged(): void {
this._teamScoresGen++;
}
protected onRosterChanged(): void {
this._rosterGen++;
}
protected onWeaponsHudChanged(): void {
this._weaponsHudGen++;
}
protected onInventoryHudChanged(): void {
this._inventoryHudGen++;
}
// ── StreamingPlayback interface ──
reset(): void {
@ -109,6 +147,7 @@ export class LiveStreamAdapter extends StreamEngine {
this.currentTimeSec = 0;
this._snapshot = null;
this._snapshotTick = -1;
this._cachedHud = null;
this.dataBlockClassNames.clear();
this.observerMode = "fly";
this.missionName = null;
@ -206,6 +245,7 @@ export class LiveStreamAdapter extends StreamEngine {
this._ready = false;
this._snapshot = null;
this._snapshotTick = -1;
this._cachedHud = null;
this.observerMode = "fly";
this.lastMoveAck = 0;
// Clear stale mission info — new values arrive via MsgClientReady
@ -604,8 +644,46 @@ export class LiveStreamAdapter extends StreamEngine {
const entities = this.buildEntityList();
const timeSec = this.currentTimeSec;
const { chatMessages, audioEvents } = this.buildTimeFilteredEvents(timeSec);
const { weaponsHud, inventoryHud, backpackHud, teamScores, playerRoster } =
this.buildHudState();
// Reuse cached HUD arrays when generation counters haven't changed.
const prev = this._cachedHud;
let weaponsHud: StreamSnapshot["weaponsHud"];
let inventoryHud: StreamSnapshot["inventoryHud"];
let backpackHud: StreamSnapshot["backpackHud"];
let teamScores: StreamSnapshot["teamScores"];
let playerRoster: StreamSnapshot["playerRoster"];
if (
prev &&
prev.weaponsHudGen === this._weaponsHudGen &&
prev.inventoryHudGen === this._inventoryHudGen &&
prev.teamScoresGen === this._teamScoresGen &&
prev.rosterGen === this._rosterGen &&
prev.backpackPackIndex === this.backpackHud.packIndex &&
prev.backpackActive === this.backpackHud.active
) {
weaponsHud = prev.weaponsHud;
inventoryHud = prev.inventoryHud;
backpackHud = prev.backpackHud;
teamScores = prev.teamScores;
playerRoster = prev.playerRoster;
} else {
({ weaponsHud, inventoryHud, backpackHud, teamScores, playerRoster } =
this.buildHudState());
this._cachedHud = {
weaponsHudGen: this._weaponsHudGen,
inventoryHudGen: this._inventoryHudGen,
teamScoresGen: this._teamScoresGen,
rosterGen: this._rosterGen,
backpackPackIndex: this.backpackHud.packIndex,
backpackActive: this.backpackHud.active,
weaponsHud,
inventoryHud,
backpackHud,
teamScores,
playerRoster,
};
}
// Default observer camera if none exists
if (!this.camera) {

View file

@ -115,7 +115,11 @@ varying vec3 vTerrainWorldPos;`,
shader.vertexShader = shader.vertexShader.replace(
"#include <worldpos_vertex>",
`#include <worldpos_vertex>
vTerrainWorldPos = (modelMatrix * vec4(transformed, 1.0)).xyz;`,
vec4 _terrainPos = vec4(transformed, 1.0);
#ifdef USE_INSTANCING
_terrainPos = instanceMatrix * _terrainPos;
#endif
vTerrainWorldPos = (modelMatrix * _terrainPos).xyz;`,
);
}

View file

@ -45,8 +45,15 @@ const vertexShader = /* glsl */ `
}
void main() {
// Apply instance transform when using InstancedMesh.
#ifdef USE_INSTANCING
mat4 localModel = modelMatrix * instanceMatrix;
#else
mat4 localModel = modelMatrix;
#endif
// Get world position for wave calculation
vec4 worldPos = modelMatrix * vec4(position, 1.0);
vec4 worldPos = localModel * vec4(position, 1.0);
vWorldPosition = worldPos.xyz;
// Apply wave displacement to Y (vertical axis in Three.js)
@ -55,7 +62,7 @@ const vertexShader = /* glsl */ `
// Calculate final world position after displacement for fog
#ifdef USE_FOG
vec4 displacedWorldPos = modelMatrix * vec4(displaced, 1.0);
vec4 displacedWorldPos = localModel * vec4(displaced, 1.0);
vFogWorldPosition = displacedWorldPos.xyz;
#endif
@ -63,7 +70,7 @@ const vertexShader = /* glsl */ `
vViewVector = cameraPosition - worldPos.xyz;
vDistance = length(vViewVector);
vec4 mvPosition = viewMatrix * modelMatrix * vec4(displaced, 1.0);
vec4 mvPosition = viewMatrix * localModel * vec4(displaced, 1.0);
gl_Position = projectionMatrix * mvPosition;
// Set fog depth (distance from camera) - normally done by fog_vertex include