From 913ab51a89d04a08c7e622164114cca597042d32 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 12:31:35 -0600 Subject: [PATCH 1/7] Add Sproinger Sound Effect --- .../elements/environment/sproinger/jump.ogg | Bin 0 -> 8030 bytes .../sproinger/sproinger.element.yaml | 4 ++- src/assets.rs | 18 +++++++++--- src/audio.rs | 11 +++++++ src/map/elements/sproinger.rs | 27 ++++++++++++++---- src/metadata.rs | 15 ++++++++++ src/metadata/map.rs | 1 + src/player/input.rs | 9 ++++++ src/prelude.rs | 6 +++- 9 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 assets/map/elements/environment/sproinger/jump.ogg diff --git a/assets/map/elements/environment/sproinger/jump.ogg b/assets/map/elements/environment/sproinger/jump.ogg new file mode 100644 index 0000000000000000000000000000000000000000..fdf1988baf1761ee4e1644ecdbda1a36c4c6f1f0 GIT binary patch literal 8030 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 literal 0 HcmV?d00001 diff --git a/assets/map/elements/environment/sproinger/sproinger.element.yaml b/assets/map/elements/environment/sproinger/sproinger.element.yaml index 65ea0d519e..8c58068d48 100644 --- a/assets/map/elements/environment/sproinger/sproinger.element.yaml +++ b/assets/map/elements/environment/sproinger/sproinger.element.yaml @@ -1,4 +1,6 @@ name: Sproinger category: Gameplay builtin: !Sproinger - atlas: ./sproinger.atlas.yaml \ No newline at end of file + atlas: ./sproinger.atlas.yaml + sound: + file: ./jump.ogg \ No newline at end of file diff --git a/src/assets.rs b/src/assets.rs index 145070ace9..ad0af9d4b0 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -367,22 +367,32 @@ impl AssetLoader for MapElementMetaLoader { match &mut meta.builtin { BuiltinElementKind::None => (), BuiltinElementKind::PlayerSpawner => (), - BuiltinElementKind::Sproinger { + BuiltinElementKind::AnimatedDecoration { atlas, atlas_handle, + .. } - | BuiltinElementKind::AnimatedDecoration { + | BuiltinElementKind::Sword { atlas, atlas_handle, - .. + } => { + let (path, handle) = get_relative_asset(load_context, self_path, atlas); + *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); + dependencies.push(path); } - | BuiltinElementKind::Sword { + BuiltinElementKind::Sproinger { atlas, atlas_handle, + sound, } => { let (path, handle) = get_relative_asset(load_context, self_path, atlas); *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); + + let (sound_path, sound_handle) = + get_relative_asset(load_context, self_path, &sound.file); + dependencies.push(sound_path); + sound.handle = sound_handle.typed(); } BuiltinElementKind::Grenades { atlas, diff --git a/src/audio.rs b/src/audio.rs index a5b7980f18..db6f2f9d4a 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -15,11 +15,14 @@ impl Plugin for AudioPlugin { .init_resource::() .init_resource::() .add_audio_channel::() + .add_audio_channel::() + .add_startup_system(setup_audio_defaults) .add_system(music_system.run_if_resource_exists::()); } } pub struct MusicChannel; +pub struct EffectsChannel; #[derive(Clone, Debug, Default)] pub struct CurrentMusic { @@ -30,6 +33,14 @@ pub struct CurrentMusic { #[derive(Deref, DerefMut, Clone, Debug, Default)] pub struct ShuffledPlaylist(pub Vec>); +fn setup_audio_defaults( + music: Res>, + effects: Res>, +) { + music.set_volume(0.15); + effects.set_volume(0.075); +} + /// Loops through all the game music as the game is on. fn music_system( game: Res, diff --git a/src/map/elements/sproinger.rs b/src/map/elements/sproinger.rs index aa52ac4e86..ea421e525d 100644 --- a/src/map/elements/sproinger.rs +++ b/src/map/elements/sproinger.rs @@ -1,5 +1,3 @@ -use crate::metadata::BuiltinElementKind; - use super::*; const FORCE: f32 = 30.0; @@ -58,14 +56,33 @@ fn pre_update_in_game( } fn update_in_game( - mut sproingers: Query<(Entity, &mut Sproinger, &mut AnimatedSprite)>, + mut sproingers: Query<( + Entity, + &mut Sproinger, + &Handle, + &mut AnimatedSprite, + )>, mut bodies: Query<&mut KinematicBody>, collision_world: CollisionWorld, + element_assets: ResMut>, + player_inputs: Res, + sound_effects: Res>, ) { - for (sproinger_ent, mut sproinger, mut sprite) in &mut sproingers { + for (sproinger_ent, mut sproinger, meta_handle, mut sprite) in &mut sproingers { + let meta = element_assets.get(meta_handle).unwrap(); + let BuiltinElementKind::Sproinger { sound, .. } = &meta.builtin else { + continue; + }; + if sproinger.sproinging { match sproinger.frame { - 1 => sprite.index = 2, + 1 => { + // Only play the sound effect if this is a frame that will not be rolled back + if player_inputs.is_confirmed { + sound_effects.play(sound.handle.clone()); + } + sprite.index = 2 + } 4 => sprite.index = 3, 8 => sprite.index = 4, 12 => sprite.index = 5, diff --git a/src/metadata.rs b/src/metadata.rs index e900eb3b27..1072759f24 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -92,6 +92,21 @@ pub struct ImageMeta { pub egui_texture_id: bevy_egui::egui::TextureId, } +#[derive(HasLoadProgress, Deserialize, Serialize, Clone, Debug)] +#[serde(deny_unknown_fields)] +pub struct SoundMeta { + pub file: String, + #[serde(skip)] + pub handle: Handle, + + #[serde(default = "default_one")] + pub volume: f32, +} + +fn default_one() -> f32 { + 1.0 +} + #[derive(Deserialize, Serialize, Clone, Debug)] pub struct TextureAtlasMeta { pub image: String, diff --git a/src/metadata/map.rs b/src/metadata/map.rs index de7a59787c..c646d4c381 100644 --- a/src/metadata/map.rs +++ b/src/metadata/map.rs @@ -244,6 +244,7 @@ pub enum BuiltinElementKind { atlas: String, #[serde(skip)] atlas_handle: AssetHandle, + sound: SoundMeta, }, /// This is a sword Sword { diff --git a/src/player/input.rs b/src/player/input.rs index 9effcbeb62..a9dc6d8853 100644 --- a/src/player/input.rs +++ b/src/player/input.rs @@ -99,12 +99,16 @@ pub enum PlayerAction { #[derive(Reflect, Clone, Debug, Component)] #[reflect(Default, Resource)] pub struct PlayerInputs { + /// This will be `true` if _all_ of the inputs for all players for this frame have been + /// confirmed and will not be rolled back. + pub is_confirmed: bool, pub players: Vec, } impl Default for PlayerInputs { fn default() -> Self { Self { + is_confirmed: false, players: vec![default(); MAX_PLAYERS], // has_updated: false, } @@ -218,6 +222,11 @@ fn update_user_input( inputs: Res>, mut player_inputs: ResMut, ) { + player_inputs.is_confirmed = inputs + .iter() + .map(|x| x.1) + .all(|x| x == InputStatus::Confirmed); + for (player_idx, (input, _)) in inputs.iter().enumerate() { let PlayerInput { control, diff --git a/src/prelude.rs b/src/prelude.rs index 9448a141bf..d24375c0c7 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,9 +1,13 @@ pub use crate::{ - assets::AssetHandle, schedule::RollbackScheduleAppExt, utils::event::FixedUpdateEventAppExt, + assets::AssetHandle, + audio::{EffectsChannel, MusicChannel}, + schedule::RollbackScheduleAppExt, + utils::event::FixedUpdateEventAppExt, GameState, InGameState, RollbackStage, }; pub use bevy::prelude::*; pub use bevy_ggrs::{Rollback, RollbackIdProvider}; +pub use bevy_kira_audio::prelude::*; pub use iyes_loopless::prelude::*; pub use leafwing_input_manager::prelude::*; pub use serde::{Deserialize, Serialize}; From 7551f3681aa1ab10b61947495f96fad1528bfec6 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 12:54:37 -0600 Subject: [PATCH 2/7] Add Sword and Grenade Sounds --- assets/map/elements/item/grenade/explosion.ogg | Bin 0 -> 11528 bytes .../elements/item/grenade/grenade.element.yaml | 2 ++ .../map/elements/item/sword/sword.element.yaml | 2 ++ assets/map/elements/item/sword/sword.ogg | Bin 0 -> 6843 bytes src/assets.rs | 17 ++++++++++++++++- src/audio.rs | 4 ++-- src/map/elements/grenade.rs | 11 +++++++++-- src/map/elements/sword.rs | 13 +++++++++++++ src/metadata/map.rs | 2 ++ src/ui/main_menu.rs | 2 +- 10 files changed, 47 insertions(+), 6 deletions(-) create mode 100755 assets/map/elements/item/grenade/explosion.ogg create mode 100644 assets/map/elements/item/sword/sword.ogg diff --git a/assets/map/elements/item/grenade/explosion.ogg b/assets/map/elements/item/grenade/explosion.ogg new file mode 100755 index 0000000000000000000000000000000000000000..95bc9aeb74cc8e3e1e50d0309995416767affbcf GIT binary patch literal 11528 zcmb7qcRXBO_wUiW=s^&j(Fqbnh#I30qXyBVr5L?O@1jPJ-X$c4=%UxrdnalTq9%xY z$n(DUeeWOlcklV^*|W}Cd#|{&J~Re2mzR!a zHi&Bmnq1lS7Xa+5quqReK~ul(`S0tx=e5LFXvgN3{MCP6u^4~#h=5`}n^({I)E%uE z?QP6-ZnQHhF$xI?J`lJkD9XsG_R^J6P(Xl<(aO@*(vcDI+|u420l7AUhV@qoyNs+3 z8h{G`e#|P=?S4aV;Q&Aa4!G=ol4p10>4N8*B1H<%&}(Y7OmWB~v=*fH8VhMX`#>Io zQP_eK05AbR2yUw5lFWAFDFe+qsU|H~*EJOsCXhfAB$+s4@SQ1sPG(zjg8`RF9}55{ zNE(+ZkOKCEDd=AnBtO|K98!>M)(a`5L-Y%FF$NHeZ|22o$lyWpG@x9?c?mEm?}Pzj zuMuY+@#FCsV<3qPsN`SOjUSBQSU{%54f9&_UwwbwVg&rIJy(jQ=&Pg~7^WLIpc^D* z(Yr}QnMno;&kw+0B+=Y0k z=p@(Wq|%e1-Gh8e@UKMxmmR#M$$8|p9(Kh)93&SR92FiQSJf0&9sPeOS`=??;stbs zDZ?ts)(`jIThp6q@dMRTXXDBe{PDgzeTLycC&7|4Y;u(R|FN^fO0laG-X!oBA z?0PX0HZGXg*$ z$$v&MQ!uqzC{tm&BR*GAUR*d=FX!iep+27Ls;mtq{=K4&M3zvnY6Qw7GOlADg zd=PtLmyet<;LZmF9FqSRQQ)F7TD*OXO>={f;ABS-6Ag4^WpX>%Qa|ax%3s$(Pk?JU-M}%yEK;y5JwQzc z@9zTtgB-=z6kV}&J+Z9HpIB8#cm{q7s~-vvlgoqQqD5&mOzAvIWvL}hHr#MbA~0^gr%0$=Ggas_+IxvmVYA$1PoZ@VXX51g`5^aI$01rpLkRc z|N1C74DJq2^0)tU0RW)oEur%DR>GJ0$l)-3by|Fx{h46Hd985qQt=4NLVkjYDN=^ETAO-H-lH;r-B5ZNS_pt zLjy=~neyMlo

q9f=|N>EDw>nMSW&ZgRE~xH4GOS);1c2JA-y-C$3fL zA}vAAbfUweuF>>~h^CX#Fx*n#39heWIeluRf8wkO_clzlyq2CiEZz>Dp736FGBUc> ztfPP8Jv*7WHsQQ{rZQR$I_Ny=?7ev6Y@On4bS6J}>>T9has6U)*;!kj%J#(11o@1zj_2YVuF4m=}qBo@SCf)RrIK|Zkz zl+>I=Xd};}UkNWij|!^9Yep!uo}ADx2FXrHl7a9Bkr@!=w^KoF%8@#Dw!9N0P`m5| zYFP+x!Gx_!`8cg0HWNY(x}Fa1ZlGX7Xrsu97`Dv_9_O}|c@*Yr=?R45T=annP%gp5 z1T(_ob{$waGEdvwu5yja9F?6wrOZ_c3LFI2sLlJuu8pVvH9i53MF$K}P?Z>GF{lax z>F5_z0#%7`a)Lcncsr<|VdbDINO1?Kinl{gR*5$$!HgHuF=f_Y+mU35lZ|`}jRc2l z7%5gWVM~Z(vKPINYxtau36?dfC zp}uw{o2&Cq(3$s3b|l#i)Sjjqz6GI9_y9bRk~OeF*y7#5HjuM}IuM(wGd+HYu{{|9 zz(*rc1&=inTf+WO2q2)m^D6|*}!WRD;w)R5_dURRWn~pRW;P>@4 zPv4=OrikTqCF>x${3wV@mut?jFnqk4_b&$w;A@UHeB9Z2p8Ps7ngk>N^rnq72nW?s zr)$paiT9{5eA3wx+~-Z5Z#WYU=6cth>1qcfu^00oB5ntpCePIEoj36lcI~TR04?Nn zfFHiS9{qCObDoNuQDFmsDWMEDQxKsHm=z|-Jb|zQz_S)KfUzY|NaJ}o6kr51O~!Tu zyK?ZbG%E%xkP3$0-2UIHn^X1wyP^a(b(evqt7mQ7xE%84Z-Ro$Fo9MuBR2eP3>tMEJCpJsoh@fy9u*01v+Rim%n=a-BzU5ziZ~~o2eeObrim5slMWT^Oh*ud0G5La zf@*H^;U|!Pc!6*K;bkYlg#Pl_5;Q=FUbh2z(4N12uP2S(=^q{>|61R*6p{}n-JE~3 zl>|`w4@LHG3ihvdc`)cdJ-}{wOgDY6tL(sQE!Whw-5ZK4p8^10ErCbkGt3MNZT-L~ z_NQ*ZP2hv6G9${s9-?qP(ZSt}?To?rkdAaDAtZpVKm`(*kcbit4vnWWB%s6qvsses z)Cv6!I;X%}Gyn$|4+cn^zR8vi#3jjXY5DS{3Vhm;u?T)5$AcY)H!iIyNDuJv34Ftl z4(?Q#>A-TLS@P%G6DN@&@h53t0q~!+e8s!}@F19DZV59Z2ZnR=v<7aNw*a6En}l?j zPBEkl=SgTcu96a%L4oN!(1HWBn4-(c33m-IAE1#j3(3I9Zba7=Cg$I)|N03L6Z7vQ zUkmiF`1+CWnyV%SKSAv$uR& zV7%Q%XAn15CabAgvT&uiTlLPL3~}g794F`ftErBN5brR-`gq(`W8U&>-bcozpNNlVdGqae{&k33ebnoF1v+hyq;!7v{n&Fa+HOFv~ZP6d~P7qb@ z=7#xE)EY(66h2=Z7d)zG#CM;(4J_1Crel@_%-t)jsy~kN^rs#E%xQ&2`HYQTmF8t{ z%IV!x(;4>l9;#(2n%rZ&YNzq!D8ZLw=Gf#gf>*+2ZEQRN5EDwF2M0L#HNOT&B0da# zU(K6K>XIf}%^?hbKetXx8{$N{pClnFV%J#L%qp)$-}p<)&SbO6Gjlm^LEJZdWi9!| z;IsGgZ`%96v~-)%)H~bt2B%D1ln}L?X_RWAgmyc0bCMkLFfLw7iSdmVRG)QXrgKyV z0+TSs^TewUjtRLhFv-&&m$TLqpLZVF!O{MlkGG)h`qc?QZGPM>tE3F>e)W7^;An=; z^LE!`6@8abSi!~~k}i^FzNx9yM=HsA>o5q}kyxAgwQLQpqi^;FEegBTp;}!VO@BOq zjFpI=nLs@3^Rp0njJc&T_Ir!&bbASdmtmsepM3M;vx21bC%8n-&p*qDef3G#i7X%3 zad&hYe1;Uka2%FK`^Z08*>$NuR{u$JU1$kkhLEBmZhq9GYn!%Pxl6F*xdFpM+h;e4 zr-I($*=v$BesML0AA)*bacGD2dQFaomhY()Ok^uTd|a( z-iGY;M;GY6Eh4Iej`UU2oh9D6UH)j|>K@MG_G!w&Aotb1bCJh*WzN(Q72f<9Nn#8& zX(`dJjAaNUeV0#@5OUUTsd<4c5c2Vy^j;qeS8e+p!eoxOYAmeBlxx$GJ!{Nr^1jIV zb}1VH3Oh^7)+6G8F2Nne?+XZvwfB;5X{coj1V8d&ee~CMd69S?tjB%9w6T9Y@-Q;z z)O+jg)&0hZO9QCR$Nk7(%Yzx>y`sd4vHp#2t2?VKpLMY{rWA6jNWaz`6jj9Q8530Z z;D%!L0^jk0x4h@wVh$nNjUI$0+8*P9=zh9gP@z@5jd?y#?e(_mpK!{F8C_%F#Y)#FGW`1yjNtCr{XAK6=x3$x5=J>yz`a_-ANLOY__ra^;cSj5(d*O50^-8u?aO z;7R|94`0Rk2Z7)_Mn(2%SBH#TL~o(YNMxhKH*b`fd!vqBcu6VCQ(p(__7$yIOkP&~ z$)q)(dYijmLYP?t6+0FOWesdh59K#cB3-6JpxfT+97`=~w3#^v6CRjR`D%vK%T#@z zy1to>i zF(Fu1=?Jd(Qflha<7ob%u#^5n+~(=*bhx2PdKBv2XOv=Ls#+_zGCz$~obd%_?MK{S zJ73<)&^gFf4Ge@Dm5=(Kkl4s2qkiZU33DM=xJVfA1_c<+e`~d;Y=m20SXq=g} zV=o0z-$;{x-D3}TTV3z!u)1RlGsogoP4Zdmju?kHIIU%48+%c9Vw9t`csz))WC;pI zO+}+#_&>7Om>7q_oTslI{3sVseO*~%qw!G!cd#?Gs~UrNeiMJw=7ds^M$CGk?dS}i z`MDRfi*Vb*B(^k5D0k(~z4E>Yf|`zIVm`XJ#Fi&vje8oO_hKROp+%n-pEq;7r4Wg8 zSaPsy;vW&~R^%6H(p4@j#wbqv(Mpv?CMHe1%KD4r{$hNDLfx1{BP3q3;xMMwLd%xvU z#6{9&k3OISXtkYR%a;z9SVZ;s#=xVs8LrGKtyB5jx6-|nW>>EaiX5KK{YXk_h^bOb zscA0tR5qP{Fm~=vxXz%_I`Zwen`1idcan%u!~DP(QGo$Q!})Y(7^6B<###iB6*pZ| zs?u!odvdZDxuzT=68*x>l_Z4+abLdvgvRdq+*O&_dp*5h(TmlKmA_y9s2)oQ#Zatj zV3bcrcV% ze#Orlx8Yr2hN!0&-uQ@{SV@29sX<^Kte*U(52VLndiMLkadss~sBQSbKGvNu>|0{? z^ruFCNh;*yrD_8N#|6>I`vZCOa6ZE_5<$k$JT-Rg@=_1~n6z&yadq4x&w4+Hno%-3 zpR7Ifkzn(~@xTFyIhgA+Esu(vKeNV_lsuVvV!*Go*z+f9kYm=T>z7T2^+#4#wA^y+ zkGXRblb<8xa=3ro@x5|;{ma^E&5P?6O$Ee!Vlt7&MZoWX^diH)xwM+w%^mFpOtaq3 z+qEL>nZhXxf8y(iTebs26fLVG!YP?PY5L42U-4c_4ICeSxAunIUm&6GnLhf&EzX*x z_O$Smhn@k~%<{n_J9c`J+Tpk?FojX?3-EZR#I=*~=3_-gyG!xFkMI|P(*`QXk~6|7 z`Dsq_tfjqJtPFS7G%>9J<_cZOkVh80_oFx&jLPeR6Xg0{If%sYD-FI(FuD9BlGgZP zI$eN!dBrw+t?H;oQ)uf`k0QA6wLDzcXvvTT0@HGS`gJBwa1 z&YY(a-4V%oFIOr^gu7yb$TYo^_jbT;KUwBtQ2E*E*>oR{p4j*bO-0e;Uvs#&&z3^O z9cna09-&F$RNsC?uvUz{j?PY8H$W#};^~l@>o~&g5yhHPbZ44Y+wh(%yCSV;P3*0- zTgQgZ%Eer-rsZZ^8DbpNEn+3hs_Vl0DFYkeFX^@Jd~p7`DTiKhywuxXHfAfKBJoPE zwk*yz>i)FnFf$B5;j1iG5cV4dyXalfGefnbIwxyjwDzTIt`TeT_(m$De1R{gNriO# z7eZXE@1i6;B|lAiu!})?`wSCIQ0Wa&-=rU_aZ0{ZHGLMZnwZ}X4>s|NB#h!jWYJ~V zuARzKNfhe?ar8 zQ)-)b(;U1s`Xz(fCf|aTFoJ$Eveiw`aYAd~_i6L6w4nX&#oKh=ty^e*UU<5{S5NLK zZaj|i7A1L<$XgaSz0ehznr=xXY*~PIMiz zO0sl-Gmlp?QCBrzxMY<&jPp@`H>~5Qt$n#Z{YJw{@A|G8cD7NVK#|$)9BzZ$78f4A z6tYykxo~0kU+i%6+T9Q1v-&lJl_Pa-I33mhVck8(&t2S#woUOvjX9ZlX1wZoNZ|d!a=~={IpH<>4eR`-f?pDJq^D zmAlx@Gf#5QroYk`ilk+_?(FTOQiccJg#Ijrr-z_vS#2SFVcj-5C9Fm*lNPf9dWa1e*~f9SNJJxo|o4!#k>|d+c4QXO|+1${+Yc z;+LrP-|w$~dM6G4`rzSZ&8quYSNUqyV)>tkrEBSzc18yehYqUHtQE9ch0E_zFfL{0 zPHd5z{TcF1iftK~LPM}ZpWY*gCuSA2p`9_M4)ODzmHHBFrju?bDKEB=gy z#eYg@{%_QTbKNU$NEjIbd+CIh6CCXFdivg@I?)v zLk}clmDi`j3lFRMNM~UR%k~m?<(ObsMpBMO?qo7nw;$W!y5ZS~-6#69QpB}K$+Z0l zmvTYO?b+$)T9>koTOry$uCs$W>7jS{Z}%LUZc;&EKAXN0 zSQ5SCn0}8;wcvT8{!{3GXq}(<-#cJ5Z~EAwCvlr;f=)pOn=yt_ls4A`hNKs9F-FAv zde3t5@#COKU~_Co$dnq>3#656GN+FYSHQ~>K2*J!+`E#WkA{?2bi4;Jtx8PUy?Qhy z@Rd!^Wp(3&UWyCQMTG`M9S?14Rq?G%&V>kasTM4+di0fs5+8qf?BL%n?e(QTNVa3@ z$+MY99L8}LIv($Wc2`B!1wK6ToGip;^F$x1&}~!GaqsZ&9-$5+k*DEkRP#t9uslh3 z75Ki+F28NwrnS*g1`&gsjWXQ4aKL;T{=Z*1fNxBID+|OK`)L1I-`9!3rk0Mj4mK7R z7FI@fJ}w9kFNBMSi<1+=#m>S7;hcJ;%-bIjk*4~UdT~KN#zS5q)ZGs4`84Ae+*TXj zOI;J_E7)h#e7MMvz>yDjIv$@t_SfsM4#idGdSAJMYjRXF0@d`cO9|F8Qg=vyVDg}ED(w^s(a7jsC z4SRTGni~(y*ndBzJx@!1apXa;ec#}#tqwXS2a?rmDEKV`5?G zzG@2eWS*)|fn3WHB5I`C5*oo<-C+OV_1BtoZeb;bv-D!JC)LCG&v2z#d?AVGjI8ca zOQs}-`P<)&aiqsqTV(Jex*I!?WV;f^Gh^cZ`x#0tNv_^sAVM#HXSc?6C&H$ljJ!|9HG!e!YhFIK=YV^84=e1xP zXnLDt=i?EjAH$c4E{$C5glb35UUtc6D9AwF3_L(j^@+JIZ!`xJX*v?M#&Y+P=8mrj zA1@8LX||+1vzyW=KQna$KAo*UGW>guhXqsFt6in~4tONv*5>jFHzL^byONoa$M= zNJBf6Imtno^pB06P1b{E)1#5B+qVR~GxP6_5K>@hel;Nm8+>xfRz~Ak4ijx1C|fB5}oE-*@C|;5odpQ@c3gX@8R=H`HlF{vMjE zjQp2<>3+@J<9Jy3l70|CKJc{sqjVA4pIUpqHzfQ~xc(=0sD8hl5iOF<6ZrU7A5POQ&I^E?Tt)DBgC+p$V;NjgSpMWeY8yeawKvYu#}QR0^QODko! z)nf97lC)+5Kkgq|Hl8`q)hZ(I{tY`L`1l<**8K6jA~y1%~Tvsk#txz_vi@u~xyEKCg&B^6PRP3W>4 z!akXb{Z?UlwtRsG;5@$gBq;4yGtq<22lI^V0vWffy|>!o|tN-)y5`whJHEJhBT40GO!%if~%KmW81lK@8dgi0rKj)K*-Y>bX@0H zy0Luip5+&v)TXc3trP`j$TD4d>N;BcabcgEa}aY2x`H^7Q5oi}Et_z`l9H0V&s)pi z-S>oTqhsp_^BtAV_`-yXA7$1t9DN41pD#o=Pe0J{`yk$>^~1H1pj-Tv?zR=q5D%}{ z2O>Y{*>;D{sz3;t)NBb4Yg~1E-SpQ2eS5>_&*oLcbSq`WYEI@FD?OcbS;hgE0fWY` zc8_|*AO-afk}`{uLLPA+WonFF+gVMQuz&>79ng zT<}X)dgf&kaoVpIaO$oKUm=E}67n9)P>vz|NDn>Y`)=YJ_Ba(tF_biyq*I^-_4ll>{ z#cl5JAX+Th@T-jJs4a78M8`=ImIC_oaW50-(S*=Ic8^Tu0f8;`R2zp6YrWEA+Gqac z3~psjT})2EDdc=RnYSn+M~z6h1pR)Pt#;y8U9|PF$_z!U@2~T!(ad4>@7Z@DP=|bGnz=W5!PimJJW3sZDeI$uP zEU>SY&BAy8JC}-M;{7c;Zp3@o?~jXR&GuImd(f?WDqk5`RyOTQYi=L;{mkHgG`Y*{ zK0KjVMZ%fr8C>F7D?HmfhdRSE?5H-_C@%R>LO7-%{4m*xi>nAO2xpRW4fjvDyVv(5Z#!IUU+z znf=(=Z)|z z#evn4x!QS-s*=>>eo8_1* zGnAHSjSJ=9eL52xYHF>VjkQc)@^->ShMKSDVW?HBuZ;S1WJ0wZR)11!{MDC0m2$(% z4o(-lgkH|u+^f!eYz2fw6Rvr6=oi5LmCl9w@yp4qKToC1hY*S~tW~z!%8eyl{IxdB z1?qR&XiEz>^c})R4)3abAbAkFw;W_O+tWWN{;kSK`PF{sJHzAIgc$M>r-dO3O~FmJ zTLGvLH#0%?*{xqWqrMnzl}3nDr`5&U7x4PNHyJ&WX z2Gl|o=to<%J)?>;vZFZ?!h$Z$EXpcxQ+j^idMzYofay6|E5FM(*^wju$56UA}gj|9*=Q8O25?(^LHnR(l~ zHJ_#sN{okz9g9Jk3VH+xU>4c2GR^B6WH(n#ndt5CmwoWOb<~98v6zT?#5BO5+eKgx zPysPOqlHAi^{7OC&BN_0V?LiJ{CWcI^9T7cuThr@Hj9gbXb;(0vS#JAnr&Si0RrG{ zB{MMYLwtNcbZEqfC0=*#yA^I-sL~NQs+AK2M4fu<`}cq zU8K3WKZ4@n^YmNR;&A{({n(cNWZ;wE;o`lt-dG=w(A7QlJ=-X4jgKj%71c4KoG!&< zrFslxEc=9E$^e~pqv?XL?Y^Omd;4HMdMB+b4}QE^==jrW_TyX{qo3ZL;E|>sUv#L#PiU|7H?IaMYf8Fq^iM^&$6%DPA*4n*%;{SQfg+5D$ulC4-$b;U zTuRR#TxAc$_SqLUoHU(s!UGm61a7iZQi1kr5nD26X-+Q{nwTibR0w;RZdB=|i&`4|9 zJ(#(mW$7iNvqkvSYM~@o6$CBwt|T=W7n(A#=&rrcPV4Lj$QkEXPcOa&;(5cJlFFCL zbsawBMDOXR)}}=ac}C;UNzS@BMyiN_fu5xR_}*5B)oW}I&dsF|oEt+_i(18^?hm3z zzObZCp4%vv#Q?5WyT-a)UkVJKa(JJ+QA#>mx6w(Gm{)-b2-I|>saLJ;w_~s2;X8z$ zE4AqRnl;+kVZ>pam}&$nb-3fgbf7sYuiz8w%wVQi*``srk7th`QkGE!;VL=&(Lc0y z5_UA3m(~ljKotNj=wJ%_b$+ z?ZGBx$ZB&9dqz%VbimrP>$L_+{gB4RQ$utCPy{>@S{!?y{^a_rjrt2(UIrH3vRYau zr9eN;vG8udQ{()5^e2vs8_^p6O3(s;hBoG7nXblZe-xzZB9?$uQ^e{c)f#aJth@24 znmd-N@;&J)q$*E_MSWEPlVNoyfcxya@^{>yoPNRcF?1;8k3zl1~dglEsUpgKE%1rHrrX-;WNjPUGROF{OAVG-CBxUA;IlG*B*BoNFFf>tg zG*etxEMBTVuPSE&2*@H!_dgRXewK4IQ7A9Pwc+BLe>Ky>dMp49+OqqY(Q4ikOHh_u zxCg*Jr7;QJvE)5mYB$$mPn>gioO^G9cW>**YJY43+;*5~I%Jmv4&C_sl3LvPOwmYanK#p24*yVO@TL57U-dAxW;yfSF7DSlK| zk1ZMdHq*Ogb4Ptq33teTu{3H(f3B1}MCvQ`)1W zwbvn~&jwXwG^ls2P?5V24end;6t3%B3jSmciiI_nF>KhMPk>o;KaY>{7SB zJjx*3O!%@-w=SILUbJ_OtZuy%U|9_voK(FUQE*f7A-PT{eR+JO7sbM;C`(a&cjKND zhP5`_ekTvVFoMp!>d$g#_Bogk?SD3Y=1N-NRQ&goC%>OOePn$)$6xebUR^p|36O=8 zJRA#H+1A~qsr%?Es~fx)IeU&_yYq~C^9Xxe2p*&4!DZ_H73ysr7w9erbOUee#*gW7 z4%h~c*>J{uI1>q+={C-xD<}QiPJaLDoje);ZsfqQF|p5?bA3N@avs{{n7RoG{z5Z( z&Z^P3e&Sm|(8vuYbSADPSC?R+;ttOZ@6HF@~Z%3bhmL_DO1r1vW zfIa{>FVBz04xcV_wb;{oN9gs4&}n2KC`<9>YUolk+_H>Ws>Wv4BF!B&rQ-$%NcvoF zZj`ZihMUHY8YT&4g@%5M2Icxdvl~I^M-uibz>$-~lth1&It_Ujn59#_( z%=iCg{GYY}bUTD5{OQrljV+NpI|MjIa1!F(MyR|H{}F1Kfx8agUyrIGMvbjr?=ox9 zmSG1~qXL~vT_;9)q?*5lhyWiBJH#k2MORrzjnf}71V@dy>r|k<_~A&0F}^t+8!Z0E zhUEdkLns3t(CMSSol}LM9sqViwm-xdc0vvU@HqYz@U|CKXPW$DG5eAbnsb zdX!kPlvoiamh>GX_pdm6VLcA`_!Q2Ci54>}%*8bli3L#??58Z0fOW8OA9PT0@|-kMXz&(l%Fz3_w~w zbB7H4xRI*kAPdCS^d+M>h(FG8HR%XITeY?zY9B@0TW)S$AiXc!uJfA(HQ{c;n#A*q znKhCKVU?UxFL`TES%=(Cv4LyWB=%Q?$;>NJlYvTapUE^Cz?Ddz-e{AVbuvD91{x7s zNeWE{P1qy5zR79;?2iG!qA56@pI^}|g%=%Cc3<+X(Ikkudhk^kx+^Iy_kH(A@Vp@b z6WIs>Rip+R7Ov3|h1SS{d%BQ-<{t0phtd z412`QwYn8&$;YL7G8m1mMGlKbd}cs|RoA@zBED)oAluq(60W3L#L8-J*P~mITJNwL zdU1u!2&*<+8dS&VaqF10vOeQRdT9E*v2TuEgqb zxSrJxCWB!GMVUiUGCo+YjeyPi>VmZqa2RZ-VW18O26%(5v}~lp+`~~6z@zi@O|+VE1T$|1m(DoQ)Gp0k2lNdL!`H7L;qcV1wm+qz zozQelmV!ARp}hIt^IL}JV^VeE1dI*x_c@*dfGCe(NON|ka*Z}@+=MqaF(nYqHm_bg z_fcRIgommaEv-SLJ*T>rT{C*nZkfF*3;^)(xP}Rh2MB~5V9DEvwXYL27+SI<`#K@J z!G52QP&NL@`Hht=?ZY=3Z%p6d-l)7mzfp%{-${gRmUxfk?Y<8$rHnFllx=GdZ&Ne; zTYmE)Z6*7=2*W*<2{^bml@u3&2?>+fYs!9R)}>|28k*12^15EGH6LiG|B2KtX)-;{ zkkWVITr@F!!u7W&+2<^O5HB|l`-b2*E8Ncf(JwT!HME!-Xm&X&UiU8gwS^?_^^=|- zzmELNk*!Fk@`hZnK?->GOJ%4fv@Q5t0hGo>e|6=W?x9MH=0bRO`+WRppNdxR%6}!X zKfU$f1S|1UbLcHwz1a^t_J7f_`&!noe{YN}ZD!VfxDXM4W}s=HDca`JH0#TLkM`Cl zs;7h!;?hXK545(smk**ROtwuqFVBDAMsC3>x;Bp3T5cey9kx;?x8HOVty$#v)BLGao1m} zf~LQVm-vq?`^>I9(6-rc<2b(I@W|DXeJPPWpQybouJQb9HjVw!QRT2cj7DhSE`Ox@ z;j>7`_#2kLUQ7ao`=mB==Qt@=6V&fcudk#DuZ7f-b<3^h5`4gQJnzk>FP)csx)od2 z899W$LS_@b8wvYvT@3GY&o3TOpVaLLzg2qKw$AITC%-*gbVlHt-Ta#Gj`#Q(*0+56 zH>bGn-!*N$+}ooA18vSI6yzL;8ex^)^g5=h;ak>y(5kP1`XN1uB8f<&NT0CNp50*a)^)4Y#jUUbqAy;J9Y!F2R8x-k@ z(goo~%@xUSdIjsNk<( za(+K}DpcjHCmz$YY~E|1!)`_DT(J#Yd9*>`Z?+Wbo^a_N%033u=Z8|hAZ;Q4bSwnH zOZ6-oXv2knzsqTP!Fu}A@D}OUC*pr-PVr4o*f?z$^v%FdThgzyb5k>Uuk5xzKG(gR znKa)x_;iL@iaW0ubVpjU$B`Y>_W8YE4V!L-{Q8^5?5yDk*hnH2gYsPP96etTe8Rxg zugSij_*zd;RT+f4l81Ny`c3hdd7WK1x&#uz>B3USN_|dJL7{a?g5MyvIrKo+z4VM3 z_limi)5g1%ysS?l8{NVx77?Azx0+Idh{JWKP$9)iTiYnf3XwhtMNQvGT|FL|t?#LD ztVyLQ>G-6daSu{?_G;Tyh?z<+2vh6V-;B1;K;$YBP5b#yu9%i7qzLC>b)UGt<5h-*SjczKNL?JPEy4 zvUM!r^>!D^UtaV*KB2x}Igv1WbseKOTa88hX#Q(c5HILlPO9slvA zypByvnn6R6+ZXs(^fBLjpva`n8e!ePb}+$cFYDnE-+y!Z<5KEW-!ueo7J3To0pBRY z>8IuwA|BiNjtjhkh+j15v2h|+U7H}lPjg;_C7#wXy-Eo-*P8MJPE>Rh!Jns+-9RrV zu*F?GPC`JCN-{jhIVqHkOE;xu&bhRsedET@w@{pLMXu(joN(BdQXrKoGfn!@ik9fP zXakI1Pwf3Hea5Xz{P0dURWM3N8Z36mZ&h}X7Oj8=Pe}W>P(Zu3o zQ)0lt4>6~Qi@u@Glo&5%)+4`ubl~_s;UTkom(IFref-<8mYTDVtJR|0ll%Lx?=AiQ z&?o#~Hg38TaKxKA5U2a-gd@BC==h=Z50IrhQ@BVJ_&p(xoW9RM^?Bn4n;c@kMgh9} zrxr|GQK`hj#btAyuuKAi?DESOf+XUcoEjHTn^s(Yd0XdYRzRIF@&|q z7p*hGS52kRq){aU^Joo}A|I)c6BRlY6!h(5YkaS92}QS_5}|195z@)h;CrykTotLf z8&L)7=m7&eDT>teg0-uym@^VIr-G(TF@k3p+q4fwT-n^zh36Zv_-vrc3&}sHS(XuJy-EMVrl+mJZ4Auo8Y$JHhq!q&~sIJqo|a9?VzOrspT6!adG_F zL>9ew;OxoRT80vhZfr!(^tAF4Y@)rB(Ulh->uOF0?^ySl7&$f(wVbJ;`CeN6 zr-run4~`5A$v%Vqz52qe-aDx0o$7m|-!|67D9T}$98xJlG2Rnz5dV8IieCl(j~Mvx V3eZpv*tPzhDZE>KJA?Nt{|&9yIKlt` literal 0 HcmV?d00001 diff --git a/src/assets.rs b/src/assets.rs index ad0af9d4b0..2a4703a0ae 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -371,14 +371,24 @@ impl AssetLoader for MapElementMetaLoader { atlas, atlas_handle, .. + } => { + let (path, handle) = get_relative_asset(load_context, self_path, atlas); + *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); + dependencies.push(path); } - | BuiltinElementKind::Sword { + BuiltinElementKind::Sword { atlas, atlas_handle, + sound, } => { let (path, handle) = get_relative_asset(load_context, self_path, atlas); *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); + + let (sound_path, sound_handle) = + get_relative_asset(load_context, self_path, &sound.file); + dependencies.push(sound_path); + sound.handle = sound_handle.typed(); } BuiltinElementKind::Sproinger { atlas, @@ -399,6 +409,7 @@ impl AssetLoader for MapElementMetaLoader { atlas_handle, explosion_atlas, explosion_atlas_handle, + explosion_sound, .. } => { for (atlas, atlas_handle) in [ @@ -409,6 +420,10 @@ impl AssetLoader for MapElementMetaLoader { *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); } + let (sound_path, sound_handle) = + get_relative_asset(load_context, self_path, &explosion_sound.file); + dependencies.push(sound_path); + explosion_sound.handle = sound_handle.typed(); } } diff --git a/src/audio.rs b/src/audio.rs index db6f2f9d4a..39f384e217 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -37,8 +37,8 @@ fn setup_audio_defaults( music: Res>, effects: Res>, ) { - music.set_volume(0.15); - effects.set_volume(0.075); + music.set_volume(0.12); + effects.set_volume(0.1); } /// Loops through all the game music as the game is on. diff --git a/src/map/elements/grenade.rs b/src/map/elements/grenade.rs index 44e2bc3207..76eb4ff002 100644 --- a/src/map/elements/grenade.rs +++ b/src/map/elements/grenade.rs @@ -92,7 +92,7 @@ fn pre_update_in_game( repeat: false, ..default() }) - .insert(map_element_handle.clone()) + .insert(map_element_handle.clone_weak()) .insert_bundle(VisibilityBundle::default()) .insert_bundle(TransformBundle { local: *transform, @@ -194,7 +194,7 @@ fn update_idle_grenades( atlas: atlas_handle.inner.clone(), ..default() }) - .insert(meta_handle.clone()) + .insert(meta_handle.clone_weak()) .insert(body.clone()) .insert(LitGrenade { spawner: grenade.spawner, @@ -243,6 +243,8 @@ fn update_lit_grenades( >, mut ridp: ResMut, element_assets: ResMut>, + player_inputs: Res, + effects: Res>, ) { let mut items = grenades.iter_mut().collect::>(); items.sort_by_key(|x| x.0.id()); @@ -256,6 +258,7 @@ fn update_lit_grenades( explosion_lifetime, explosion_fps, explosion_frames, + explosion_sound, .. } = &meta.builtin else { unreachable!(); @@ -264,6 +267,10 @@ fn update_lit_grenades( grenade.age += 1.0 / crate::FPS as f32; if grenade.age >= *fuse_time { + if player_inputs.is_confirmed { + effects.play(explosion_sound.handle.clone_weak()); + } + // Despawn the grenade commands.entity(item_ent).despawn(); // Cause the item to re-spawn by re-triggering spawner hydration diff --git a/src/map/elements/sword.rs b/src/map/elements/sword.rs index 60466a0e25..ff64ff9b4f 100644 --- a/src/map/elements/sword.rs +++ b/src/map/elements/sword.rs @@ -90,6 +90,7 @@ fn update_in_game( &mut SwordState, &mut AnimatedSprite, &mut KinematicBody, + &Handle, Option<&Parent>, Option<&ItemUsed>, Option<&ItemDropped>, @@ -97,6 +98,9 @@ fn update_in_game( Without, >, mut ridp: ResMut, + player_inputs: Res, + effects: Res>, + element_assets: Res>, ) { // Helper to spawn damage regions let mut spawn_damage_region = @@ -117,11 +121,17 @@ fn update_in_game( mut state, mut sprite, mut body, + meta_handle, parent, item_used, item_dropped, ) in &mut swords { + let meta = element_assets.get(meta_handle).unwrap(); + let BuiltinElementKind::Sword { sound, .. } = &meta.builtin else { + unreachable!(); + }; + // For all tiems that are being held if let Some(parent) = parent { let (player_sprite, player_transform, ..) = @@ -217,6 +227,9 @@ fn update_in_game( sprite.start = 8; sprite.end = 12; *state = SwordState::Swinging { frame: 0 }; + if player_inputs.is_confirmed { + effects.play(sound.handle.clone_weak()); + } } } diff --git a/src/metadata/map.rs b/src/metadata/map.rs index c646d4c381..07b026754c 100644 --- a/src/metadata/map.rs +++ b/src/metadata/map.rs @@ -218,6 +218,7 @@ pub enum BuiltinElementKind { explosion_lifetime: f32, explosion_frames: usize, explosion_fps: f32, + explosion_sound: SoundMeta, /// The time in seconds before a grenade explodes fuse_time: f32, #[serde(default)] @@ -251,5 +252,6 @@ pub enum BuiltinElementKind { atlas: String, #[serde(skip)] atlas_handle: AssetHandle, + sound: SoundMeta, }, } diff --git a/src/ui/main_menu.rs b/src/ui/main_menu.rs index 498f6b0bf2..a333648e2b 100644 --- a/src/ui/main_menu.rs +++ b/src/ui/main_menu.rs @@ -75,7 +75,7 @@ pub fn setup_main_menu( } // Spawn menu background - let bg_handle = game.main_menu.background_image.image_handle.clone(); + let bg_handle = game.main_menu.background_image.image_handle.clone_weak(); let img_size = game.main_menu.background_image.image_size; let ratio = img_size.x / img_size.y; let height = game.camera_height as f32; From 9f24939f6df5b9102a3a4899983c796b6045a84f Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 16:18:04 -0600 Subject: [PATCH 3/7] Add Player Jump and Land Sounds --- .../sproinger/sproinger.element.yaml | 3 +- .../item/grenade/grenade.element.yaml | 3 +- .../elements/item/sword/sword.element.yaml | 3 +- assets/player/skins/catty/catty.player.yaml | 6 ++++ assets/player/skins/fishy/fishy.player.yaml | 6 ++++ .../skins/lionfishy/lionfishy.player.yaml | 6 ++++ assets/player/skins/orcy/orcy.player.yaml | 6 ++++ assets/player/skins/pescy/pescy.player.yaml | 6 ++++ assets/player/skins/sharky/sharky.player.yaml | 7 +++- assets/player/sounds/jump.ogg | Bin 0 -> 8030 bytes assets/player/sounds/land.ogg | Bin 0 -> 4665 bytes src/assets.rs | 33 ++++++++++++------ src/map/elements/grenade.rs | 4 +-- src/map/elements/sproinger.rs | 4 +-- src/map/elements/sword.rs | 4 +-- src/metadata.rs | 15 -------- src/metadata/map.rs | 12 +++++-- src/metadata/player.rs | 15 ++++++++ src/player.rs | 1 + src/player/state/states.rs | 1 + src/player/state/states/midair.rs | 19 ++++++++-- src/player/state/states/walk.rs | 16 ++++++++- 22 files changed, 125 insertions(+), 45 deletions(-) create mode 100644 assets/player/sounds/jump.ogg create mode 100755 assets/player/sounds/land.ogg diff --git a/assets/map/elements/environment/sproinger/sproinger.element.yaml b/assets/map/elements/environment/sproinger/sproinger.element.yaml index 8c58068d48..476cf2c43c 100644 --- a/assets/map/elements/environment/sproinger/sproinger.element.yaml +++ b/assets/map/elements/environment/sproinger/sproinger.element.yaml @@ -2,5 +2,4 @@ name: Sproinger category: Gameplay builtin: !Sproinger atlas: ./sproinger.atlas.yaml - sound: - file: ./jump.ogg \ No newline at end of file + sound: ./jump.ogg \ No newline at end of file diff --git a/assets/map/elements/item/grenade/grenade.element.yaml b/assets/map/elements/item/grenade/grenade.element.yaml index fee520f617..9bc6dddcbf 100644 --- a/assets/map/elements/item/grenade/grenade.element.yaml +++ b/assets/map/elements/item/grenade/grenade.element.yaml @@ -10,8 +10,7 @@ builtin: !Grenades explosion_lifetime: 1.0 explosion_frames: 12 explosion_fps: 8 - explosion_sound: - file: ./explosion.ogg + explosion_sound: ./explosion.ogg body_size: [18, 18] grab_offset: [-7, -6] diff --git a/assets/map/elements/item/sword/sword.element.yaml b/assets/map/elements/item/sword/sword.element.yaml index aef41ec0eb..cd5f0aed5a 100644 --- a/assets/map/elements/item/sword/sword.element.yaml +++ b/assets/map/elements/item/sword/sword.element.yaml @@ -2,6 +2,5 @@ name: Sword category: Weapons builtin: !Sword atlas: ./sword.atlas.yaml - sound: - file: ./sword.ogg + sound: ./sword.ogg \ No newline at end of file diff --git a/assets/player/skins/catty/catty.player.yaml b/assets/player/skins/catty/catty.player.yaml index a438acd14a..4047baf2a1 100644 --- a/assets/player/skins/catty/catty.player.yaml +++ b/assets/player/skins/catty/catty.player.yaml @@ -1,5 +1,11 @@ name: Catty +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + spritesheet: image: catty.png tile_size: [96, 80] diff --git a/assets/player/skins/fishy/fishy.player.yaml b/assets/player/skins/fishy/fishy.player.yaml index a0096e679c..fd07f1f108 100644 --- a/assets/player/skins/fishy/fishy.player.yaml +++ b/assets/player/skins/fishy/fishy.player.yaml @@ -1,5 +1,11 @@ name: Fishy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + spritesheet: image: fishy.png tile_size: [96, 80] diff --git a/assets/player/skins/lionfishy/lionfishy.player.yaml b/assets/player/skins/lionfishy/lionfishy.player.yaml index b2ca4919fd..bd2d49d885 100644 --- a/assets/player/skins/lionfishy/lionfishy.player.yaml +++ b/assets/player/skins/lionfishy/lionfishy.player.yaml @@ -1,5 +1,11 @@ name: Lionfishy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + spritesheet: image: lionfishy.png tile_size: [96, 80] diff --git a/assets/player/skins/orcy/orcy.player.yaml b/assets/player/skins/orcy/orcy.player.yaml index bed21c9112..3d25a6d023 100644 --- a/assets/player/skins/orcy/orcy.player.yaml +++ b/assets/player/skins/orcy/orcy.player.yaml @@ -1,5 +1,11 @@ name: Orcy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + spritesheet: image: orcy.png tile_size: [96, 80] diff --git a/assets/player/skins/pescy/pescy.player.yaml b/assets/player/skins/pescy/pescy.player.yaml index 12ec12d6cf..0b01ab8587 100644 --- a/assets/player/skins/pescy/pescy.player.yaml +++ b/assets/player/skins/pescy/pescy.player.yaml @@ -1,5 +1,11 @@ name: Pescy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + spritesheet: image: pescy.png tile_size: [96, 80] diff --git a/assets/player/skins/sharky/sharky.player.yaml b/assets/player/skins/sharky/sharky.player.yaml index c1b8ebedae..9f7472c455 100644 --- a/assets/player/skins/sharky/sharky.player.yaml +++ b/assets/player/skins/sharky/sharky.player.yaml @@ -1,5 +1,11 @@ name: Sharky +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + spritesheet: image: sharky.png tile_size: [96, 80] @@ -26,4 +32,3 @@ spritesheet: death_1: frames: [70, 76] repeat: false - diff --git a/assets/player/sounds/jump.ogg b/assets/player/sounds/jump.ogg new file mode 100644 index 0000000000000000000000000000000000000000..fdf1988baf1761ee4e1644ecdbda1a36c4c6f1f0 GIT binary patch literal 8030 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 literal 0 HcmV?d00001 diff --git a/assets/player/sounds/land.ogg b/assets/player/sounds/land.ogg new file mode 100755 index 0000000000000000000000000000000000000000..4f36f5f6693a361cb16af6862ff4e25431e84697 GIT binary patch literal 4665 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 MH`&>&`DB3jAHA^5W&i*H literal 0 HcmV?d00001 diff --git a/src/assets.rs b/src/assets.rs index 2a4703a0ae..1cc33ea448 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -238,6 +238,7 @@ impl AssetLoader for PlayerMetaLoader { ) -> bevy::utils::BoxedFuture<'a, Result<(), anyhow::Error>> { Box::pin(async move { let self_path = load_context.path(); + let mut dependencies = Vec::new(); let mut meta: PlayerMeta = if self_path.extension() == Some(OsStr::new("json")) { serde_json::from_slice(bytes)? } else { @@ -248,6 +249,15 @@ impl AssetLoader for PlayerMetaLoader { let (atlas_path, atlas_handle) = get_relative_asset(load_context, load_context.path(), &meta.spritesheet.image); + for (sound, sound_handle) in [ + (&meta.sounds.jump, &mut meta.sounds.jump_handle), + (&meta.sounds.land, &mut meta.sounds.land_handle), + ] { + let (path, handle) = get_relative_asset(load_context, self_path, sound); + dependencies.push(path); + *sound_handle = handle.typed(); + } + let atlas_handle = load_context.set_labeled_asset( "atlas", LoadedAsset::new(TextureAtlas::from_grid( @@ -260,7 +270,7 @@ impl AssetLoader for PlayerMetaLoader { ); meta.spritesheet.atlas_handle = AssetHandle::new(atlas_path, atlas_handle); - load_context.set_default_asset(LoadedAsset::new(meta)); + load_context.set_default_asset(LoadedAsset::new(meta).with_dependencies(dependencies)); Ok(()) }) @@ -380,29 +390,29 @@ impl AssetLoader for MapElementMetaLoader { atlas, atlas_handle, sound, + sound_handle, } => { let (path, handle) = get_relative_asset(load_context, self_path, atlas); *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); - let (sound_path, sound_handle) = - get_relative_asset(load_context, self_path, &sound.file); - dependencies.push(sound_path); - sound.handle = sound_handle.typed(); + let (path, handle) = get_relative_asset(load_context, self_path, sound); + dependencies.push(path); + *sound_handle = handle.typed(); } BuiltinElementKind::Sproinger { atlas, atlas_handle, sound, + sound_handle, } => { let (path, handle) = get_relative_asset(load_context, self_path, atlas); *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); - let (sound_path, sound_handle) = - get_relative_asset(load_context, self_path, &sound.file); - dependencies.push(sound_path); - sound.handle = sound_handle.typed(); + let (path, handle) = get_relative_asset(load_context, self_path, sound); + dependencies.push(path); + *sound_handle = handle.typed(); } BuiltinElementKind::Grenades { atlas, @@ -410,6 +420,7 @@ impl AssetLoader for MapElementMetaLoader { explosion_atlas, explosion_atlas_handle, explosion_sound, + explosion_sound_handle, .. } => { for (atlas, atlas_handle) in [ @@ -421,9 +432,9 @@ impl AssetLoader for MapElementMetaLoader { dependencies.push(path); } let (sound_path, sound_handle) = - get_relative_asset(load_context, self_path, &explosion_sound.file); + get_relative_asset(load_context, self_path, explosion_sound); dependencies.push(sound_path); - explosion_sound.handle = sound_handle.typed(); + *explosion_sound_handle = sound_handle.typed(); } } diff --git a/src/map/elements/grenade.rs b/src/map/elements/grenade.rs index 76eb4ff002..fc3f8065ac 100644 --- a/src/map/elements/grenade.rs +++ b/src/map/elements/grenade.rs @@ -258,7 +258,7 @@ fn update_lit_grenades( explosion_lifetime, explosion_fps, explosion_frames, - explosion_sound, + explosion_sound_handle, .. } = &meta.builtin else { unreachable!(); @@ -268,7 +268,7 @@ fn update_lit_grenades( if grenade.age >= *fuse_time { if player_inputs.is_confirmed { - effects.play(explosion_sound.handle.clone_weak()); + effects.play(explosion_sound_handle.clone_weak()); } // Despawn the grenade diff --git a/src/map/elements/sproinger.rs b/src/map/elements/sproinger.rs index ea421e525d..3fa1e6fd06 100644 --- a/src/map/elements/sproinger.rs +++ b/src/map/elements/sproinger.rs @@ -70,7 +70,7 @@ fn update_in_game( ) { for (sproinger_ent, mut sproinger, meta_handle, mut sprite) in &mut sproingers { let meta = element_assets.get(meta_handle).unwrap(); - let BuiltinElementKind::Sproinger { sound, .. } = &meta.builtin else { + let BuiltinElementKind::Sproinger { sound_handle, .. } = &meta.builtin else { continue; }; @@ -79,7 +79,7 @@ fn update_in_game( 1 => { // Only play the sound effect if this is a frame that will not be rolled back if player_inputs.is_confirmed { - sound_effects.play(sound.handle.clone()); + sound_effects.play(sound_handle.clone_weak()); } sprite.index = 2 } diff --git a/src/map/elements/sword.rs b/src/map/elements/sword.rs index ff64ff9b4f..a94d16a159 100644 --- a/src/map/elements/sword.rs +++ b/src/map/elements/sword.rs @@ -128,7 +128,7 @@ fn update_in_game( ) in &mut swords { let meta = element_assets.get(meta_handle).unwrap(); - let BuiltinElementKind::Sword { sound, .. } = &meta.builtin else { + let BuiltinElementKind::Sword { sound_handle, .. } = &meta.builtin else { unreachable!(); }; @@ -228,7 +228,7 @@ fn update_in_game( sprite.end = 12; *state = SwordState::Swinging { frame: 0 }; if player_inputs.is_confirmed { - effects.play(sound.handle.clone_weak()); + effects.play(sound_handle.clone_weak()); } } } diff --git a/src/metadata.rs b/src/metadata.rs index 1072759f24..e900eb3b27 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -92,21 +92,6 @@ pub struct ImageMeta { pub egui_texture_id: bevy_egui::egui::TextureId, } -#[derive(HasLoadProgress, Deserialize, Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct SoundMeta { - pub file: String, - #[serde(skip)] - pub handle: Handle, - - #[serde(default = "default_one")] - pub volume: f32, -} - -fn default_one() -> f32 { - 1.0 -} - #[derive(Deserialize, Serialize, Clone, Debug)] pub struct TextureAtlasMeta { pub image: String, diff --git a/src/metadata/map.rs b/src/metadata/map.rs index 07b026754c..a963b898e4 100644 --- a/src/metadata/map.rs +++ b/src/metadata/map.rs @@ -218,7 +218,9 @@ pub enum BuiltinElementKind { explosion_lifetime: f32, explosion_frames: usize, explosion_fps: f32, - explosion_sound: SoundMeta, + explosion_sound: String, + #[serde(skip)] + explosion_sound_handle: Handle, /// The time in seconds before a grenade explodes fuse_time: f32, #[serde(default)] @@ -245,13 +247,17 @@ pub enum BuiltinElementKind { atlas: String, #[serde(skip)] atlas_handle: AssetHandle, - sound: SoundMeta, + sound: String, + #[serde(skip)] + sound_handle: Handle, }, /// This is a sword Sword { atlas: String, #[serde(skip)] atlas_handle: AssetHandle, - sound: SoundMeta, + sound: String, + #[serde(skip)] + sound_handle: Handle, }, } diff --git a/src/metadata/player.rs b/src/metadata/player.rs index 327386c02a..be64c5af8f 100644 --- a/src/metadata/player.rs +++ b/src/metadata/player.rs @@ -21,6 +21,7 @@ impl Plugin for PlayerMetadataPlugin { pub struct PlayerMeta { pub name: String, pub spritesheet: PlayerSpritesheetMeta, + pub sounds: PlayerSounds, } #[derive(Reflect, Deserialize, Clone, Debug, Default)] @@ -39,6 +40,20 @@ pub struct PlayerSpritesheetMeta { pub animations: HashMap, } +#[derive(Reflect, Deserialize, Clone, Debug, Default)] +#[serde(deny_unknown_fields)] +pub struct PlayerSounds { + pub land: String, + pub land_volume: f32, + #[serde(skip)] + pub land_handle: Handle, + + pub jump: String, + pub jump_volume: f32, + #[serde(skip)] + pub jump_handle: Handle, +} + impl PlayerSpritesheetMeta { pub fn get_animation_bank_and_sprite(&self) -> (AnimationBank, AnimationBankSprite) { let animations = self diff --git a/src/player.rs b/src/player.rs index b6468178f9..c856adce5c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -327,6 +327,7 @@ fn hydrate_players( entity_commands .insert(Name::new(format!("Player {}", player_idx.0))) + .insert(input.selected_player.inner.clone_weak()) .insert(PlayerState::default()) .insert(animation_bank) .insert(animation_bank_sprite) diff --git a/src/player/state/states.rs b/src/player/state/states.rs index 7cbdf76e7d..27e6842155 100644 --- a/src/player/state/states.rs +++ b/src/player/state/states.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use crate::{ animation::AnimationBankSprite, item::Item, + metadata::PlayerMeta, physics::collisions::CollisionWorld, physics::KinematicBody, player::{ diff --git a/src/player/state/states/midair.rs b/src/player/state/states/midair.rs index 1cb1f9ced9..3820a54c7f 100644 --- a/src/player/state/states/midair.rs +++ b/src/player/state/states/midair.rs @@ -4,13 +4,28 @@ pub const ID: &str = "core:midair"; pub const AIR_MOVE_SPEED: f32 = 7.0; -pub fn player_state_transition(mut players: Query<(&mut PlayerState, &KinematicBody)>) { - for (mut player_state, body) in &mut players { +pub fn player_state_transition( + mut players: Query<(&mut PlayerState, &KinematicBody, &Handle)>, + player_inputs: Res, + effects: Res>, + player_assets: Res>, +) { + for (mut player_state, body, meta_handle) in &mut players { + let meta = player_assets.get(meta_handle).unwrap(); + if player_state.id != ID { continue; } if body.is_on_ground { + // Play land sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.land_handle.clone_weak()) + // TODO: This volume should be relative to the current channel volume, not + // hard-coded, so that when the user changes the sound effect volume it's relative. + .with_volume(meta.sounds.land_volume as _); + } player_state.id = idle::ID.into(); } } diff --git a/src/player/state/states/walk.rs b/src/player/state/states/walk.rs index 5e71a5c1b6..48706d15d2 100644 --- a/src/player/state/states/walk.rs +++ b/src/player/state/states/walk.rs @@ -32,12 +32,17 @@ pub fn handle_player_state( Entity, &PlayerState, &PlayerIdx, + &Handle, &mut AnimationBankSprite, &mut KinematicBody, )>, collision_world: CollisionWorld, + effects: Res>, + player_assets: Res>, ) { - for (player_ent, player_state, player_idx, mut sprite, mut body) in &mut players { + for (player_ent, player_state, player_idx, meta_handle, mut sprite, mut body) in &mut players { + let meta = player_assets.get(meta_handle).unwrap(); + if player_state.id != ID { continue; } @@ -95,6 +100,15 @@ pub fn handle_player_state( // If we are jumping if control.jump_just_pressed { + // Play jump sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.jump_handle.clone_weak()) + // TODO: This volume should be relative to the current channel volume, not + // hard-coded, so that when the user changes the sound effect volume it's relative. + .with_volume(meta.sounds.jump_volume as _); + } + // Move up body.velocity.y = JUMP_SPEED; } From 7c7c03cb74ac3c9d4f51514a0900e27cca16000f Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 16:22:24 -0600 Subject: [PATCH 4/7] Remove Old Scripts To Avoid Confusion The TypeScript scripts aren't used anymore. They could be useful reference if we ever use bevy_mod_js_scripting again, but it's also potentially confusing to contributors and we have the git history for reference. --- assets/game/camera_controller.ts | 46 --- .../elements/decoration/anemones/anemones.ts | 18 -- .../elements/decoration/seaweed/seaweed.ts | 17 -- assets/map/elements/environment/crab/crab.ts | 84 ------ .../environment/fish_school/sproinger.ts | 1 - .../player_spawner/player_spawner.ts | 52 ---- .../environment/sproinger/sproinger.ts | 124 -------- .../elements/item/blunderbass/sproinger.ts | 1 - assets/map/elements/item/cannon/sproinger.ts | 1 - assets/map/elements/item/crate/sproinger.ts | 1 - .../map/elements/item/kick_bomb/kick_bomb.ts | 267 ------------------ .../item/kick_bomb/kick_bomb_spawner.ts | 25 -- .../elements/item/machine_gun/sproinger.ts | 1 - assets/map/elements/item/mines/sproinger.ts | 1 - assets/map/elements/item/musket/musket.ts | 1 - .../elements/item/sniper_rifle/sproinger.ts | 1 - assets/map/elements/item/sword/sword.ts | 262 ----------------- .../map/elements/item/sword/sword_spawner.ts | 25 -- assets/map/scripts/kill_out_of_bounds.ts | 5 + assets/player/states/README.md | 3 - assets/player/states/crouch.ts | 49 ---- assets/player/states/dead.ts | 42 --- assets/player/states/default.ts | 14 - assets/player/states/idle.ts | 79 ------ assets/player/states/midair.ts | 80 ------ assets/player/states/walk.ts | 83 ------ assets/ui/menu-background-zoom.ts | 4 + 27 files changed, 9 insertions(+), 1278 deletions(-) delete mode 100644 assets/game/camera_controller.ts delete mode 100644 assets/map/elements/decoration/anemones/anemones.ts delete mode 100644 assets/map/elements/decoration/seaweed/seaweed.ts delete mode 100644 assets/map/elements/environment/crab/crab.ts delete mode 100644 assets/map/elements/environment/fish_school/sproinger.ts delete mode 100644 assets/map/elements/environment/player_spawner/player_spawner.ts delete mode 100644 assets/map/elements/environment/sproinger/sproinger.ts delete mode 100644 assets/map/elements/item/blunderbass/sproinger.ts delete mode 100644 assets/map/elements/item/cannon/sproinger.ts delete mode 100644 assets/map/elements/item/crate/sproinger.ts delete mode 100644 assets/map/elements/item/kick_bomb/kick_bomb.ts delete mode 100644 assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts delete mode 100644 assets/map/elements/item/machine_gun/sproinger.ts delete mode 100644 assets/map/elements/item/mines/sproinger.ts delete mode 100644 assets/map/elements/item/musket/musket.ts delete mode 100644 assets/map/elements/item/sniper_rifle/sproinger.ts delete mode 100644 assets/map/elements/item/sword/sword.ts delete mode 100644 assets/map/elements/item/sword/sword_spawner.ts delete mode 100644 assets/player/states/README.md delete mode 100644 assets/player/states/crouch.ts delete mode 100644 assets/player/states/dead.ts delete mode 100644 assets/player/states/default.ts delete mode 100644 assets/player/states/idle.ts delete mode 100644 assets/player/states/midair.ts delete mode 100644 assets/player/states/walk.ts diff --git a/assets/game/camera_controller.ts b/assets/game/camera_controller.ts deleted file mode 100644 index bc791740c6..0000000000 --- a/assets/game/camera_controller.ts +++ /dev/null @@ -1,46 +0,0 @@ -const lerpFactor = 0.1; - -export default { - postUpdateInGame() { - const mapQuery = world.query(MapMeta)[0]; - if (!mapQuery) return; - - const playerComponents = world - .query(PlayerIdx, Transform) - .map((x) => x.components); - - const [_, cameraTransform, projection] = world.query( - GameCamera, - Transform, - OrthographicProjection - )[0].components; - - let middlePoint = { x: 0, y: 0 }; - let min = { x: 100000, y: 100000 }; - let max = { x: -100000, y: -100000 }; - - const player_count = playerComponents.length; - - for (const [_, playerTransform] of playerComponents) { - const playerPos = playerTransform.translation; - middlePoint.x += playerPos.x; - middlePoint.y += playerPos.y; - - min.x = Math.min(playerPos.x, min.x); - min.y = Math.min(playerPos.y, min.y); - max.x = Math.max(playerPos.x, max.x); - max.y = Math.max(playerPos.y, max.y); - } - - middlePoint.x /= Math.max(player_count, 1); - middlePoint.y /= Math.max(player_count, 1); - - for (const dim of ["x", "y"]) { - let delta = cameraTransform.translation[dim] - middlePoint[dim]; - let dist = delta * lerpFactor; - cameraTransform.translation[dim] -= dist; - } - - projection.scale = 1.25; - }, -}; diff --git a/assets/map/elements/decoration/anemones/anemones.ts b/assets/map/elements/decoration/anemones/anemones.ts deleted file mode 100644 index b1e20e89b8..0000000000 --- a/assets/map/elements/decoration/anemones/anemones.ts +++ /dev/null @@ -1,18 +0,0 @@ -export default { - preUpdate() { - for (const entity of MapElement.getSpawnedEntities()) { - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 4, - repeat: true, - fps: 6, - atlas: { - id: Assets.getHandleId("./anemones.atlas.yaml"), - }, - }) - ); - } - }, -}; diff --git a/assets/map/elements/decoration/seaweed/seaweed.ts b/assets/map/elements/decoration/seaweed/seaweed.ts deleted file mode 100644 index 87829d1b9f..0000000000 --- a/assets/map/elements/decoration/seaweed/seaweed.ts +++ /dev/null @@ -1,17 +0,0 @@ -export default { - preUpdate() { - for (const entity of MapElement.getSpawnedEntities()) { - let animated_sprite = Value.create(AnimatedSprite, { - start: 0, - end: 4, - repeat: true, - fps: 6, - atlas: { - id: Assets.getHandleId("./seaweed.atlas.yaml"), - }, - }); - - world.insert(entity, animated_sprite); - } - }, -}; diff --git a/assets/map/elements/environment/crab/crab.ts b/assets/map/elements/environment/crab/crab.ts deleted file mode 100644 index 9b0448186a..0000000000 --- a/assets/map/elements/environment/crab/crab.ts +++ /dev/null @@ -1,84 +0,0 @@ -const MapMeta: BevyType = { - typeName: "jumpy::metadata::map::MapMeta", -}; - -let i = 0; - -const CRABS = "crabs"; - -export default { - preUpdateInGame() { - const mapQuery = world.query(MapMeta)[0]; - if (!mapQuery) { - Script.clearEntityList(CRABS); - return; - } - - const spawnedEntities = MapElement.getSpawnedEntities(); - if (spawnedEntities.length > 0) { - Script.clearEntityList(CRABS); - } - - // Handle newly spawned map entities - for (const spanwer_entity of spawnedEntities) { - const [transform, global_transform, computed_visibility] = world - .query(Transform, GlobalTransform, ComputedVisibility) - .get(spanwer_entity); - - // Spawn a new entity for the crab and copy the transform and visibility from the map element - const entity = WorldTemp.spawn(); - Script.addEntityToList(CRABS, entity); - - world.insert(entity, Value.create(EntityName, ["Critter: Crab"])); - world.insert(entity, transform); - world.insert(entity, global_transform); - world.insert(entity, computed_visibility); - world.insert(entity, Value.create(Visibility)); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 1, - repeat: true, - fps: 3, - atlas: { - id: Assets.getHandleId("crab.atlas.yaml"), - }, - }) - ); - - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 18, - y: 12, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - }, - - updateInGame() { - i++; - const query = world.query(KinematicBody); - - for (const crab of Script.getEntityList(CRABS)) { - const components = query.get(crab); - if (!components) continue; - const [kinematicBody] = components; - - if (i % 100 == 0) { - i = 0; - kinematicBody.velocity.x = - Random.gen() * 3 * (Random.gen() >= 0.5 ? -1 : 1); - } - } - }, -}; diff --git a/assets/map/elements/environment/fish_school/sproinger.ts b/assets/map/elements/environment/fish_school/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/environment/fish_school/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/environment/player_spawner/player_spawner.ts b/assets/map/elements/environment/player_spawner/player_spawner.ts deleted file mode 100644 index 27fc1e6255..0000000000 --- a/assets/map/elements/environment/player_spawner/player_spawner.ts +++ /dev/null @@ -1,52 +0,0 @@ -const initState: { currentSpawner: number } = { - currentSpawner: 0, -}; - -const state = Script.state(initState); - -export default { - preUpdate() { - const player_inputs = world.resource(PlayerInputs); - - const mapQuery = world.query(MapMeta)[0]; - if (!mapQuery) { - Script.clearEntityList("playerSpawners"); - return; - } - - const spawnedEntities = MapElement.getSpawnedEntities(); - if (spawnedEntities.length > 0) { - spawnedEntities.forEach((e) => - Script.addEntityToList("playerSpawners", e) - ); - } - - // Collect all the alive players on the map - const alive_players = world.query(PlayerIdx).map((x) => x.components[0][0]); - - // For every player - for (let i = 0; i < 4; i++) { - // Get the player input - const player = player_inputs.players[i]; - - const spawners = Script.getEntityList("playerSpawners"); - - // If the player is active, but not alive - if (player.active && !alive_players.includes(i)) { - // Get the next spawner - state.currentSpawner += 1; - state.currentSpawner %= spawners.length; - - const spawner = spawners[state.currentSpawner]; - - // Get the spawner transform - const [spawnerTransform] = world.query(Transform).get(spawner); - - // Spawn the player - const player = WorldTemp.spawn(); - world.insert(player, Value.create(PlayerIdx, [i])); - world.insert(player, spawnerTransform); - } - } - }, -}; diff --git a/assets/map/elements/environment/sproinger/sproinger.ts b/assets/map/elements/environment/sproinger/sproinger.ts deleted file mode 100644 index 10d48d3650..0000000000 --- a/assets/map/elements/environment/sproinger/sproinger.ts +++ /dev/null @@ -1,124 +0,0 @@ -// Define the sproinger state types -type SproingerState = { - sproinging: boolean; - frame: number; -}; - -// Add our constants -const FORCE = 25; - -export default { - preUpdateInGame() { - // Check for the existence of the map - const map = world.query(MapMeta)[0]; - // If there is no map - if (!map) { - // clear our sproinger list - Script.clearEntityList("sproingers"); - return; - } - - // Get the list of spawned entities - const spawnedEntities = MapElement.getSpawnedEntities(); - // If there are spawned entities, that means the map was loaded or reloaded. - if (spawnedEntities.length > 0) { - // So clear our sproinger list - Script.clearEntityList("sproingers"); - } - - // For every new sproinger entity - for (const entity of spawnedEntities) { - // Add this entity to our list of sproingers. - // - // Note: Because we cannot persist entity refs across frames, - // we must first convert the entity to a JSON representation. - Script.addEntityToList("sproingers", entity); - - // Add the sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 6, - repeat: false, - fps: 0, - atlas: { - id: Assets.getHandleId("./sproinger.atlas.yaml"), - }, - }) - ); - // And the physics body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 32, - y: 8, - }, - offset: { - y: -6, - }, - has_mass: false, - }) - ); - } - }, - - updateInGame() { - const bodies = world.query(KinematicBody); - const animatedSprites = world.query(AnimatedSprite); - - // Loop over all our sproingers - for (const entity of Script.getEntityList("sproingers")) { - // Get our sproinger sprite - const [sprite] = animatedSprites.get(entity); - - // Get the script-local state for the sproinger entity - const entState = Script.getEntityState(entity, { - frame: 0, - sproinging: false, - }); - - // If the sproinger is currently sproinging - if (entState.sproinging) { - // Play the sproinging animation - switch (entState.frame) { - case 0: - sprite.index = 2; - break; - case 4: - sprite.index = 3; - break; - case 8: - sprite.index = 4; - break; - case 12: - sprite.index = 5; - break; - case 20: - sprite.index = 0; - entState.sproinging = false; - entState.frame = 0; - break; - } - entState.frame += 1; - } - - // See if the spoinger has any collisions - for (const collidedEntity of CollisionWorld.actorCollisions(entity)) { - // Get the kinematic body of the collided entity - const components = bodies.get(collidedEntity); - if (!components) continue; - const [body] = components; - - if (!entState.sproinging) { - // Apply the sproing force to the body - body.velocity.y = FORCE; - - // Go into a sproinging state - entState.sproinging = true; - } - } - } - }, -}; diff --git a/assets/map/elements/item/blunderbass/sproinger.ts b/assets/map/elements/item/blunderbass/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/blunderbass/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/cannon/sproinger.ts b/assets/map/elements/item/cannon/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/cannon/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/crate/sproinger.ts b/assets/map/elements/item/crate/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/crate/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/kick_bomb/kick_bomb.ts b/assets/map/elements/item/kick_bomb/kick_bomb.ts deleted file mode 100644 index 4911b17ca9..0000000000 --- a/assets/map/elements/item/kick_bomb/kick_bomb.ts +++ /dev/null @@ -1,267 +0,0 @@ -const scriptPath = Script.getInfo().path; - -type LitBombState = { - frames: number; -}; - -const LIT_BOMBS = "kickBombsLit"; - -export default { - preUpdateInGame() { - // Hydrate newly spawned sword items - const names = world.query(EntityName); - const items = world.query(Item); - for (const { entity, components } of items) { - const [item] = components; - - // If this is one of our items without a name - if (item.script == scriptPath && !names.get(entity)) { - // Hydrate the entity - world.insert(entity, Value.create(EntityName, ["Item: Kick Bomb"])); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 5, - repeat: false, - fps: 0, - atlas: { - id: Assets.getHandleId("kick_bomb.atlas.yaml"), - }, - }) - ); - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 26, - y: 26, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - } - }, - - updateInGame() { - const players = world.query( - AnimatedSprite, - Transform, - KinematicBody, - PlayerIdx, - GlobalTransform, - ComputedVisibility - ); - const parents = world.query(Parent); - const items = world.query( - Item, - Transform, - KinematicBody, - AnimatedSprite, - GlobalTransform - ); - const transforms = world.query( - Transform, - GlobalTransform, - Visibility, - ComputedVisibility - ); - const usedItems = world.query(ItemUsed); - const droppedItems = world.query(ItemDropped); - - // Update items that are being held - // - // This section will make the item follow the player around and match the player's facing - // direction. - for (const { entity: itemEnt, components } of items) { - const [item, itemTransform, body, sprite] = components; - if (item.script != scriptPath) continue; - - let parentComponents = parents.get(itemEnt); - // If this item isn't being held, skip the item - if (!parentComponents) continue; - - const [parent] = parentComponents; - const [playerSprite] = players.get(parent[0]); - - // Deactivate item collision - body.is_deactivated = true; - - // Set animation to default position if we are being held - sprite.index = 0; - - // Flip the sprite to match our player orientation - const flip = playerSprite.flip_x; - sprite.flip_x = flip; - const flipFactor = flip ? -1 : 1; - // Align the sprite with the player's position - itemTransform.translation = Value.create(Vec3, { - x: 13 * flipFactor, - y: 0, - }); - - // For every item that is being used - if (!!usedItems.get(itemEnt)) { - // Get the player info - const [parent] = parentComponents; - const playerEnt = parent[0]; - const [ - playerSprite, - transform, - _body, - _idx, - globalTransform, - computedVisibility, - ] = players.get(playerEnt); - const flip = playerSprite.flip_x; - const flipFactor = flip ? -1 : 1; - - // Despawn the item from the player's hand - Player.setInventory(playerEnt, null); - // WorldTemp.despawnRecursive(itemEnt); - - // Spawn a new, lit bomb to the map - const entity = WorldTemp.spawn(); - Script.addEntityToList(LIT_BOMBS, entity); - world.insert(entity, Value.create(EntityName, ["Kick Bomb ( Lit )"])); - world.insert(entity, transform); - world.insert(entity, globalTransform); - world.insert(entity, computedVisibility); - world.insert(entity, Value.create(Visibility)); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 3, - end: 5, - repeat: true, - fps: 8, - atlas: { - id: Assets.getHandleId("kick_bomb.atlas.yaml"), - }, - }) - ); - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 26, - y: 26, - }, - velocity: { - x: 10 * flipFactor, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - } - - // Handle lit bombs - const litBombs = Script.getEntityList(LIT_BOMBS); - Script.clearEntityList(LIT_BOMBS); - for (const bombEntity of litBombs) { - // Get the bomb's state - const state = Script.getEntityState(bombEntity, { - frames: 0, - }); - const [transform, globalTransform, visibility, computedVisibility] = - transforms.get(bombEntity); - - if (state.frames >= 60) { - // Spawn damage region entity - const damageRegionEnt = WorldTemp.spawn(); - world.insert(damageRegionEnt, transform); - world.insert(damageRegionEnt, globalTransform); - world.insert(damageRegionEnt, visibility); - world.insert(damageRegionEnt, computedVisibility); - world.insert( - damageRegionEnt, - Value.create(DamageRegion, { - size: { - x: 26 * 3.5, - y: 26 * 3.5, - }, - }) - ); - world.insert( - damageRegionEnt, - Value.create(Lifetime, { - lifetime: (1 / 9) * 4, - }) - ); - // Spawn explosion sprite entity - const explosionSpriteEnt = WorldTemp.spawn(); - world.insert(explosionSpriteEnt, transform); - world.insert(explosionSpriteEnt, globalTransform); - world.insert(explosionSpriteEnt, visibility); - world.insert(explosionSpriteEnt, computedVisibility); - world.insert( - explosionSpriteEnt, - Value.create(AnimatedSprite, { - start: 0, - end: 11, - repeat: false, - fps: 9, - atlas: { - id: Assets.getHandleId("explosion.atlas.yaml"), - }, - }) - ); - world.insert( - explosionSpriteEnt, - Value.create(Lifetime, { - lifetime: (1 / 9) * 11, - }) - ); - - // Despawn the lit bomb - WorldTemp.despawnRecursive(bombEntity); - } else { - state.frames += 1; - Script.addEntityToList(LIT_BOMBS, bombEntity); - } - } - - // Update dropped items - for (const { - entity: itemEnt, - components: [item], - } of items) { - if (item.script != scriptPath) continue; - - const droppedItemComponents = droppedItems.get(itemEnt); - if (!!droppedItemComponents) { - const [droppedItem] = droppedItemComponents; - const [_item, itemTransform, body, sprite] = items.get(itemEnt); - const [_, playerTransform, playerBody] = players.get( - droppedItem.player - ); - let flip = sprite.flip_x; - let flipFactor = flip ? -1 : 1; - - // Re-activate physics body on the item - body.is_deactivated = false; - // Make sure item maintains player velocity - body.velocity = playerBody.velocity; - body.is_spawning = true; - - // Drop item at the middle of the player - itemTransform.translation.y = playerTransform.translation.y; - itemTransform.translation.x = - playerTransform.translation.x + 13 * flipFactor; - itemTransform.translation.z = playerTransform.translation.z; - } - } - }, -}; diff --git a/assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts b/assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts deleted file mode 100644 index 5a16d6fbc4..0000000000 --- a/assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts +++ /dev/null @@ -1,25 +0,0 @@ -export default { - preUpdate() { - const spawnedEntities = MapElement.getSpawnedEntities(); - - // Handle newly spawned map entities - for (const spanwer_entity of spawnedEntities) { - const [transform, global_transform, computed_visibility] = world - .query(Transform, GlobalTransform, ComputedVisibility) - .get(spanwer_entity); - - // Spawn a new entity for the bomb item and copy the transform from the map element - const entity = WorldTemp.spawn(); - world.insert( - entity, - Value.create(Item, { - script: Assets.getAbsolutePath("kick_bomb.ts"), - }) - ); - world.insert(entity, transform); - world.insert(entity, global_transform); - world.insert(entity, computed_visibility); - world.insert(entity, Value.create(Visibility)); - } - }, -}; diff --git a/assets/map/elements/item/machine_gun/sproinger.ts b/assets/map/elements/item/machine_gun/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/machine_gun/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/mines/sproinger.ts b/assets/map/elements/item/mines/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/mines/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/musket/musket.ts b/assets/map/elements/item/musket/musket.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/musket/musket.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/sniper_rifle/sproinger.ts b/assets/map/elements/item/sniper_rifle/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/sniper_rifle/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/sword/sword.ts b/assets/map/elements/item/sword/sword.ts deleted file mode 100644 index 22f82660ca..0000000000 --- a/assets/map/elements/item/sword/sword.ts +++ /dev/null @@ -1,262 +0,0 @@ -const scriptPath = Script.getInfo().path; - -type Idle = { status: "idle" }; -type Swinging = { status: "swinging"; frame: number }; -type Cooldown = { status: "cooldown"; frame: number }; -type ItemState = Idle | Swinging | Cooldown; -const itemStateInit: ItemState = { status: "idle" }; - -const COOLDOWN_FRAMES = 15; -const ATTACK_FPS = 10; - -export default { - preUpdateInGame() { - // Hydrate newly spawned sword items - const names = world.query(EntityName); - const items = world.query(Item); - for (const { entity, components } of items) { - const [item] = components; - - // If this is one of our items without a name - if (item.script == scriptPath && !names.get(entity)) { - // Hydrate the entity - world.insert(entity, Value.create(EntityName, ["Item: Sword"])); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 0, - repeat: false, - fps: ATTACK_FPS, - atlas: { - id: Assets.getHandleId("sword.atlas.yaml"), - }, - }) - ); - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 64, - y: 16, - }, - offset: { - y: 38, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - } - }, - - updateInGame() { - const players = world.query( - AnimatedSprite, - Transform, - KinematicBody, - PlayerIdx - ); - const parents = world.query(Parent); - const items = world.query(Item, Transform, KinematicBody, AnimatedSprite); - const usedItems = world.query(ItemUsed); - const droppedItems = world.query(ItemDropped); - - // Helper to spawn a damage region - const spawnDamageRegion = ( - owner: Entity, - x: number, - y: number, - width: number, - height: number - ) => { - /// This is a hack to get a global transform because scripts can't construct it with - /// Value.create(). ( Fixed in Bevy 0.9 ) - const [_item, _transform, _kinematicBody, _animatedSprite] = - items[0].components; - - // Spawn damage region entity - let entity = WorldTemp.spawn(); - world.insert( - entity, - Value.create(Transform, { - translation: { - x, - y, - }, - }) - ); - world.insert( - entity, - Value.create(DamageRegion, { - size: { - x: width, - y: height, - }, - }) - ); - world.insert(entity, Value.create(DamageRegionOwner, [owner])); - world.insert( - entity, - Value.create(Lifetime, { - lifetime: 1 / 60, - }) - ); - }; - - // Update items that are being held - // - // This section will make the item follow the player around and match the player's facing - // direction. - for (const { entity: itemEnt, components } of items) { - const [item, itemTransform, body, sprite] = components; - if (item.script != scriptPath) continue; - - const state = Script.getEntityState(itemEnt, itemStateInit); - - let parentComponents = parents.get(itemEnt); - // If this item isn't being held, skip the item - if (!parentComponents) continue; - - const [parent] = parentComponents; - const [playerSprite, playerTransform] = players.get(parent[0]); - - // Deactivate item collision - body.is_deactivated = true; - - // Set animation to default position if we aren't swinging - if (state.status != "swinging") { - sprite.start = 4; - sprite.end = 4; - sprite.index = 0; - sprite.repeat = false; - } - - // Flip the sprite to match our player orientation - const flip = playerSprite.flip_x; - sprite.flip_x = flip; - const flipFactor = flip ? -1 : 1; - // Align the sprite with the player's position - itemTransform.translation = Value.create(Vec3, { - x: 13 * (flip ? -1 : 1), - y: 21, - }); - - // If we're swinging the weapon - if (state.status == "swinging") { - // If we are at the end of the swing animation - if (sprite.index >= sprite.end - sprite.start - 1) { - // Go to cooldown frames - Script.setEntityState(itemEnt, { - status: "cooldown", - frame: 0, - }); - - // Set the current attack frame to the animation frame index - } else { - state.frame = sprite.index; - } - - // Trigger frame collisions for each sword animation position - switch (state.frame) { - case 0: - spawnDamageRegion( - parent[0], - playerTransform.translation.x + 20 * flipFactor, - playerTransform.translation.y + 20, - 30, - 70 - ); - break; - case 1: - spawnDamageRegion( - parent[0], - playerTransform.translation.x + 25 * flipFactor, - playerTransform.translation.y + 20, - 40, - 50 - ); - break; - case 2: - spawnDamageRegion( - parent[0], - playerTransform.translation.x + 20 * flipFactor, - playerTransform.translation.y, - 40, - 50 - ); - break; - } - - state.frame += 1; - - // If we are in cooldown frames - } else if (state.status == "cooldown") { - // If cooldown frames have finished - if (state.frame >= COOLDOWN_FRAMES) { - // Go back to idle state - Script.setEntityState(itemEnt, { status: "idle" }); - } else { - state.frame += 1; - } - } - - // If the item is being used - if (!!usedItems.get(itemEnt)) { - // Get the current item state - const state = Script.getEntityState(itemEnt, itemStateInit); - - if (state.status == "idle") { - const [_item, _itemTransform, _body, sprite] = items.get(itemEnt); - - // Start attacking animation - sprite.index = 0; - sprite.start = 8; - sprite.end = 12; - - // And move to an attacking state - Script.setEntityState(itemEnt, { - status: "swinging", - frame: 0, - }); - } - } - } - - // Update dropped items - for (const { - entity: itemEnt, - components: [item], - } of items) { - if (item.script != scriptPath) continue; - - const droppedItemComponents = droppedItems.get(itemEnt); - if (!!droppedItemComponents) { - const [droppedItem] = droppedItemComponents; - const [_item, itemTransform, body, sprite] = items.get(itemEnt); - const [_, playerTransform, playerBody] = players.get( - droppedItem.player - ); - - // Re-activate physics body on the item - body.is_deactivated = false; - // Put sword in rest position - sprite.start = 0; - sprite.end = 0; - // Make sure item maintains player velocity - body.velocity = playerBody.velocity; - body.is_spawning = true; - - // Drop item at the middle of the player - itemTransform.translation.y = playerTransform.translation.y - 30; - itemTransform.translation.x = playerTransform.translation.x; - itemTransform.translation.z = playerTransform.translation.z; - } - } - }, -}; diff --git a/assets/map/elements/item/sword/sword_spawner.ts b/assets/map/elements/item/sword/sword_spawner.ts deleted file mode 100644 index 77d916b47c..0000000000 --- a/assets/map/elements/item/sword/sword_spawner.ts +++ /dev/null @@ -1,25 +0,0 @@ -export default { - preUpdate() { - const spawnedEntities = MapElement.getSpawnedEntities(); - - // Handle newly spawned map entities - for (const spanwer_entity of spawnedEntities) { - const [transform, global_transform, computed_visibility] = world - .query(Transform, GlobalTransform, ComputedVisibility) - .get(spanwer_entity); - - // Spawn a new entity for the sword and copy the transform and visibility from the map element - const entity = WorldTemp.spawn(); - world.insert( - entity, - Value.create(Item, { - script: Assets.getAbsolutePath("./sword.ts"), - }) - ); - world.insert(entity, transform); - world.insert(entity, global_transform); - world.insert(entity, computed_visibility); - world.insert(entity, Value.create(Visibility)); - } - }, -}; diff --git a/assets/map/scripts/kill_out_of_bounds.ts b/assets/map/scripts/kill_out_of_bounds.ts index 4569b7c234..d54119988d 100644 --- a/assets/map/scripts/kill_out_of_bounds.ts +++ b/assets/map/scripts/kill_out_of_bounds.ts @@ -1,3 +1,8 @@ +/** + * TODO: Migrate to rust. + * + * This script isn't currently running. + */ const killZoneBorder = 500; export default { diff --git a/assets/player/states/README.md b/assets/player/states/README.md deleted file mode 100644 index c016d744a4..0000000000 --- a/assets/player/states/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Player States - -These are the TypeScript implementations of the player states. For now they are unused as we migrated them to Rust for performance reasons. \ No newline at end of file diff --git a/assets/player/states/crouch.ts b/assets/player/states/crouch.ts deleted file mode 100644 index 3c5b27ab9d..0000000000 --- a/assets/player/states/crouch.ts +++ /dev/null @@ -1,49 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const player_inputs = world.resource(PlayerInputs); - const playerComponents = world - .query(PlayerState, PlayerIdx, KinematicBody) - .map((x) => x.components); - - for (const [playerState, playerIdx, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - const control = player_inputs.players[playerIdx[0]].control; - - if (!body.is_on_ground || !(control.move_direction.y < -0.5)) { - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - - // For every player - const playerComponents = world - .query(PlayerState, PlayerIdx, AnimationBankSprite, KinematicBody) - .map((x) => x.components); - for (const [ - playerState, - playerIdx, - animationBankSprite, - body, - ] of playerComponents) { - // In this state - if (playerState.id != scriptId) continue; - - // Set the current animation - if (playerState.age == 0) { - animationBankSprite.current_animation = "crouch"; - } - - // Add basic physics controls - const control = player_inputs.players[playerIdx[0]].control; - - if (control.jump_just_pressed) { - body.fall_through = true; - } - } - }, -}; diff --git a/assets/player/states/dead.ts b/assets/player/states/dead.ts deleted file mode 100644 index 737269b19e..0000000000 --- a/assets/player/states/dead.ts +++ /dev/null @@ -1,42 +0,0 @@ -const scriptId = Script.getInfo().path; - -const DYING_PLAYERS = "dyingPlayers"; - -/** Responsible for transitioning players to the dead state whenever they are killed */ -export default { - playerStateTransition() { - const players = world.query(PlayerState, PlayerKilled); - - // Transition all players that have been killed to this state - for (const { entity } of players) { - if (!Script.entityListContains(DYING_PLAYERS, entity)) { - const [playerState] = players.get(entity); - playerState.id = Assets.getAbsolutePath("./dead.ts"); - Script.addEntityToList(DYING_PLAYERS, entity); - } - } - }, - handlePlayerState() { - const players = world.query(PlayerState, AnimationBankSprite); - - for (const { - entity, - components: [playerState, animationBankSprite], - } of players) { - // In this state - if (playerState.id != scriptId) continue; - - // Set animation when we enter the state - if (playerState.age == 0) { - animationBankSprite.current_animation = "death_1"; - } - - // Despawn player after 1.5 seconds ( 90 frames ) - if (playerState.age >= 90) { - Script.removeEntityFromList(DYING_PLAYERS, entity); - Player.despawn(entity); - Script.setEntityState(entity, undefined); - } - } - }, -}; diff --git a/assets/player/states/default.ts b/assets/player/states/default.ts deleted file mode 100644 index 694c80ca86..0000000000 --- a/assets/player/states/default.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** Responsible for transitioning players in the default, meaningless state to "idle" */ -export default { - playerStateTransition() { - for (const [playerState] of world - .query(PlayerState) - .map((x) => x.components)) { - // Loop over players in the default state - if (playerState.id !== "") continue; - - // Transition to the idle state - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - }, -}; diff --git a/assets/player/states/idle.ts b/assets/player/states/idle.ts deleted file mode 100644 index 2c8d77b31a..0000000000 --- a/assets/player/states/idle.ts +++ /dev/null @@ -1,79 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const player_inputs = world.resource(PlayerInputs); - const playerComponents = world - .query(PlayerState, PlayerIdx, KinematicBody) - .map((x) => x.components); - - for (const [playerState, playerIdx, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - const control = player_inputs.players[playerIdx[0]].control; - - if (!body.is_on_ground) { - playerState.id = Assets.getAbsolutePath("./midair.ts"); - } else if (control.move_direction.y < -0.5) { - playerState.id = Assets.getAbsolutePath("./crouch.ts"); - } else if (control.move_direction.x != 0) { - playerState.id = Assets.getAbsolutePath("./walk.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - - let items = world.query(Item); - - // For every player - for (const { entity: playerEnt, components } of world.query( - PlayerState, - PlayerIdx, - AnimationBankSprite, - KinematicBody - )) { - const [playerState, playerIdx, animationBankSprite, body] = components; - - // In this state - if (playerState.id != scriptId) continue; - - // Set the current animation - if (playerState.age == 0) { - animationBankSprite.current_animation = "idle"; - } - - // Add basic physics controls - const control = player_inputs.players[playerIdx[0]].control; - - // If we are grabbing - if (control.grab_just_pressed) { - // Get inventory - const currentInventory = Player.getInventory(playerEnt); - - if (!currentInventory) { - // For each actor colliding with the player - for (const collider of CollisionWorld.actorCollisions(playerEnt)) { - const item = items.get(collider); - if (!!item) { - Player.setInventory(playerEnt, collider); - break; - } - } - } else { - Player.setInventory(playerEnt, null); - } - } - - // Use item if we have one - if (control.shoot_just_pressed && Player.getInventory(playerEnt)) { - Player.useItem(playerEnt); - } - - if (control.jump_just_pressed) { - body.velocity.y = 15; - } - body.velocity.x = 0; - } - }, -}; diff --git a/assets/player/states/midair.ts b/assets/player/states/midair.ts deleted file mode 100644 index 94a670dd2f..0000000000 --- a/assets/player/states/midair.ts +++ /dev/null @@ -1,80 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const playerComponents = world - .query(PlayerState, KinematicBody) - .map((x) => x.components); - - for (const [playerState, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - if (body.is_on_ground) { - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - const items = world.query(Item); - - // For every player - for (const { entity: playerEnt, components } of world.query( - PlayerState, - PlayerIdx, - AnimationBankSprite, - KinematicBody - )) { - const [playerState, playerIdx, animationBankSprite, body] = components; - if (playerState.id != scriptId) continue; - - // Set the current animation - if (body.velocity.y > 0) { - animationBankSprite.current_animation = "rise"; - } else { - animationBankSprite.current_animation = "fall"; - } - - const control = player_inputs.players[playerIdx[0]].control; - - // If we are grabbing - if (control.grab_just_pressed) { - const current_inventory = Player.getInventory(playerEnt); - if (!current_inventory) { - // For each actor colliding with the player - for (const collider of CollisionWorld.actorCollisions(playerEnt)) { - const item = items.get(collider); - if (!!item) { - const [_item] = item; - Player.setInventory(playerEnt, collider); - break; - } - } - } else { - Player.setInventory(playerEnt, null); - } - } - - // Use item if we have one - if (control.shoot_just_pressed && Player.getInventory(playerEnt)) { - Player.useItem(playerEnt); - } - - // Add controls - body.velocity.x = control.move_direction.x * 5; - - // Fall through platforms when pressing down - if (control.move_direction.y < -0.5 && control.jump_pressed) { - body.fall_through = true; - } else { - body.fall_through = false; - } - - if (body.velocity.x > 0) { - animationBankSprite.flip_x = false; - } else if (body.velocity.x < 0) { - animationBankSprite.flip_x = true; - } - } - }, -}; diff --git a/assets/player/states/walk.ts b/assets/player/states/walk.ts deleted file mode 100644 index e17cb76752..0000000000 --- a/assets/player/states/walk.ts +++ /dev/null @@ -1,83 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const player_inputs = world.resource(PlayerInputs); - const playerComponents = world - .query(PlayerState, PlayerIdx, KinematicBody) - .map((x) => x.components); - - for (const [playerState, playerIdx, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - const control = player_inputs.players[playerIdx[0]].control; - - if (!body.is_on_ground) { - playerState.id = Assets.getAbsolutePath("./midair.ts"); - } else if (body.is_on_ground && control.move_direction.y < -0.5) { - playerState.id = Assets.getAbsolutePath("./crouch.ts"); - } else if (control.move_direction.x == 0) { - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - - const items = world.query(Item); - - // For every player - for (const { entity: playerEnt, components } of world.query( - PlayerState, - PlayerIdx, - AnimationBankSprite, - KinematicBody - )) { - const [playerState, playerIdx, animationBankSprite, body] = components; - - // Add basic physics controls - const control = player_inputs.players[playerIdx[0]].control; - - // In this state - if (playerState.id != scriptId) continue; - - // Set the current animation - if (playerState.age == 0) { - animationBankSprite.current_animation = "walk"; - } - - // If we are grabbing - if (control.grab_just_pressed) { - const current_inventory = Player.getInventory(playerEnt); - if (!current_inventory) { - // For each actor colliding with the player - for (const collider of CollisionWorld.actorCollisions(playerEnt)) { - const item = items.get(collider); - if (!!item) { - Player.setInventory(playerEnt, collider); - break; - } - } - } else { - Player.setInventory(playerEnt, null); - } - } - - // Use item if we have one - if (control.shoot_just_pressed && Player.getInventory(playerEnt)) { - Player.useItem(playerEnt); - } - - // Add jump - if (control.jump_just_pressed) { - body.velocity.y = 15; - } - body.velocity.x = control.move_direction.x * 5; - if (control.move_direction.x > 0) { - animationBankSprite.flip_x = false; - } else if (control.move_direction.x < 0) { - animationBankSprite.flip_x = true; - } - } - }, -}; diff --git a/assets/ui/menu-background-zoom.ts b/assets/ui/menu-background-zoom.ts index 8ca513067a..62f3eb0e27 100644 --- a/assets/ui/menu-background-zoom.ts +++ b/assets/ui/menu-background-zoom.ts @@ -1,3 +1,7 @@ +/** + * TODO: Migrate to Rust + */ + type MenuBackground = unknown; const MenuBackground: BevyType = { typeName: "jumpy::ui::main_menu::MainMenuBackground", From 2f93430256c1ddcbff391e1ac5d9d94d4d55e728 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 17:01:39 -0600 Subject: [PATCH 5/7] Add Player Grab and Drop Sounds --- assets/player/skins/catty/catty.player.yaml | 4 +++ assets/player/skins/fishy/fishy.player.yaml | 4 +++ .../skins/lionfishy/lionfishy.player.yaml | 4 +++ assets/player/skins/orcy/orcy.player.yaml | 4 +++ assets/player/skins/pescy/pescy.player.yaml | 4 +++ assets/player/skins/sharky/sharky.player.yaml | 4 +++ assets/player/sounds/drop.ogg | Bin 0 -> 4266 bytes assets/player/sounds/grab.ogg | Bin 0 -> 5309 bytes src/assets.rs | 2 ++ src/map/elements/grenade.rs | 11 +++++-- src/metadata/player.rs | 10 ++++++ src/player/state/states/idle.rs | 30 +++++++++++++++++- src/player/state/states/walk.rs | 14 ++++++++ 13 files changed, 88 insertions(+), 3 deletions(-) create mode 100755 assets/player/sounds/drop.ogg create mode 100644 assets/player/sounds/grab.ogg diff --git a/assets/player/skins/catty/catty.player.yaml b/assets/player/skins/catty/catty.player.yaml index 4047baf2a1..462cc2dad9 100644 --- a/assets/player/skins/catty/catty.player.yaml +++ b/assets/player/skins/catty/catty.player.yaml @@ -5,6 +5,10 @@ sounds: jump_volume: 0.05 land: ../../sounds/land.ogg land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 spritesheet: image: catty.png diff --git a/assets/player/skins/fishy/fishy.player.yaml b/assets/player/skins/fishy/fishy.player.yaml index fd07f1f108..f983b6f21b 100644 --- a/assets/player/skins/fishy/fishy.player.yaml +++ b/assets/player/skins/fishy/fishy.player.yaml @@ -5,6 +5,10 @@ sounds: jump_volume: 0.05 land: ../../sounds/land.ogg land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 spritesheet: image: fishy.png diff --git a/assets/player/skins/lionfishy/lionfishy.player.yaml b/assets/player/skins/lionfishy/lionfishy.player.yaml index bd2d49d885..c611bc45db 100644 --- a/assets/player/skins/lionfishy/lionfishy.player.yaml +++ b/assets/player/skins/lionfishy/lionfishy.player.yaml @@ -5,6 +5,10 @@ sounds: jump_volume: 0.05 land: ../../sounds/land.ogg land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 spritesheet: image: lionfishy.png diff --git a/assets/player/skins/orcy/orcy.player.yaml b/assets/player/skins/orcy/orcy.player.yaml index 3d25a6d023..4c108ea8e4 100644 --- a/assets/player/skins/orcy/orcy.player.yaml +++ b/assets/player/skins/orcy/orcy.player.yaml @@ -5,6 +5,10 @@ sounds: jump_volume: 0.05 land: ../../sounds/land.ogg land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 spritesheet: image: orcy.png diff --git a/assets/player/skins/pescy/pescy.player.yaml b/assets/player/skins/pescy/pescy.player.yaml index 0b01ab8587..a6941b46a9 100644 --- a/assets/player/skins/pescy/pescy.player.yaml +++ b/assets/player/skins/pescy/pescy.player.yaml @@ -5,6 +5,10 @@ sounds: jump_volume: 0.05 land: ../../sounds/land.ogg land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 spritesheet: image: pescy.png diff --git a/assets/player/skins/sharky/sharky.player.yaml b/assets/player/skins/sharky/sharky.player.yaml index 9f7472c455..6bb7d63d8f 100644 --- a/assets/player/skins/sharky/sharky.player.yaml +++ b/assets/player/skins/sharky/sharky.player.yaml @@ -5,6 +5,10 @@ sounds: jump_volume: 0.05 land: ../../sounds/land.ogg land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 spritesheet: image: sharky.png diff --git a/assets/player/sounds/drop.ogg b/assets/player/sounds/drop.ogg new file mode 100755 index 0000000000000000000000000000000000000000..e058c9ea09f80cb29762133a49a31f0060967817 GIT binary patch literal 4266 zcmb7HdstIP7QaE{WyJ6h14Wx4R6e=m!HW~K-Pl$7iT@OL}P!_?cI^`kd$?fG$*0W{|8>b$a$}Mma zTjzR}k3}uuPu-_H@tWIYv^H`z1Onu3gwL^L2HT>vu{VZxeq`gCsL zpe)#P+DXfM&9(zd+kr*fK{E%2xr5S`sA9T@Z1rM=Qq`fXa2A`LE>Ncl)D;447(#>z zB3lLHf9#0sI22U7nOwG+P-aIco8DfgpOe?92gSl6sdX%z-d^%3pu{1e?DInvaRt?v zs;cK@XHAeP5DH9z+rxu}a|cV}4wWHe^~HqhhX1vD$M-rx-XNAe2W)lSKgHe?(|Rf?MV&1D-OLY|76W?n*g>QG;a%MYRJx>Q#%JO+y_-|0~SFH zw;nwo@`E`$Q)kD=U2gs(?Gqp0y zGpaiUp=Y+V$tuqX734WdlEQjgB2*Cis=8{chN^`M8oFAlqYjy$F>I0z1D^Gq#I)Nw z2Fyzst~Qj7Mu4@EL)EjF+AIN8AU?B2-WICUhbR>)WS>eDcgRyC=BgxDPPZLC*7L8xeWsis^wV9LJ;?FkZ@ggh!&~>f@Paqgh2pq+nB2tee zdpE^cx4|pO@jqbMbJF(iN&8(b_CdqW125e6ymV7qP(iwctY<6Ni&R#;5D&J>ou^{) z)M>oYR$lb=%*fWv$>q1YR`fP<0Br2YCDQ?aL{7;M+e%TQM3@s4Ya^$34>-pLy<8EbV zSw?&j1$}s-Qdn|$pvbQGz>k=%`G?k&Z`MClT;-d800fN+VZhmm&9?RF$InUXcQYSJ zE(|jgB|@<$eWTQp-zUEi%Go9NP>{i65wlNzZHz&eH`uHJhe0yktH3vig?;21N%k;JCJ_#k2`8EGV~T?ISQ4rr6KZn6ou+3Ce$F`n zD*Dg?J;=0YaVJgX%NTZJ{4G!^@=~UU;3$&In~O z+y$edtnsBlRYj0iEnu)j(XE1*gM#s8FV!{hD40lPN2d!$mwD0JVt+(cI8Y@D3Req4 zL;|)2RlA-QUO`ot^TI1cpOy0_w7yCaRV`*SM7-#7_GB6_aydx*O2n$j1=6YOA~ts4 z@>WWgyE2rmVu^s=aSg00T+RcW(Q?6LID2%-osr5` zvUriHtjI9l=rTKUNyK1fMwjzo>9SyQL*A$+b1Ie1hBb#pE@h5u%V#vAsn>z3R^XsW zCCZ#!62(=C*srPDSDCDeOs<^w+3Va%*_-agqRW>TE##iH@o zf{D2M?O!cU|I&SuKmILgp;dUl{fhH9FSj1yMI3HO7;jkk`_0EU+do{mNxI+u7fY5} z%Zm2MQckZk0x{P-YK^qhik{FU5922iH5fX-PK@;-5F0d!flX=~k^x@0n?5T6 zryCGxT<0#Onlhi@z;&M3TyM#pk%-ZrP8)N?bSF}|n1hyehA|7}^`TsT^NbZ&Q75+A z<AawPUX+V|dydziD?1X&kQ zMeK_3p%E*@93r7>gwx;FRS|7iCoiQJf!B>LB45`eu9bF1=!_T1m$0yL>@FvFutMOz zG{$Kp%PaVa&9heALHUe^ueg0tlNi)IGsfxnn#INrv>C3W00*sn2&7g`qJT7OyJDQ6 z0jh|aF(5#Ut8IWEnh_8yEl?%vs^%;1^i*>95H+^key^?y{y^Jub#y6!I(j>}kSc=> z0BnsB*ycEPVRH=d-I7y7xXwx;)2UmMT}tn&6k_OolI&nQy$Vn?g1C%MZ^~uT=`uNh ztqBaNDDH58JQyja0pVR!kqD?OqCl;E8>B3K1PIaGy-k}%o%MJu*v%-03tTz#Z->n zeDins{i+}9-0rIf*$_5_q!)XTd3S)xp|HH z(6^u>=Ykydd~9F;y~_+XhsmT#%l$}mIB^-1-o#SS0;Ez+)QRSl-C!5wR?$Tu8KV-3 z-B|9AAWNh8BtSVzrC4qwNfYHmlgY8%B6n>R6HEc#v@Mr0PmsDl;Xi9Tt>HAvXF+x1 zCAZ=>xzF7fK8GhOTvZt9BQUm+V#WuTz@YfT}Hv4`SnS!&pJn@^B1*+W_0`J`@% z&=dgJmrep|ka{?Pu)@nJUE$SmBt9sWaf+xUf*%~{yk1-4AMr(`2&|ntGx5N z{l>ahr&>Qe{=qX(3)A<8r63}tSc-zj!ye;=1>erlS8X{k7;J{o5K|KZ-Go`Kn zmpz67`MpLo8mOQ^IS+LhLLD)BzP@ff%Be+^xt%M8X^x2CL0?~2^}}C?`ufNxpZ<`c zP7HtY!F>9j=NuDfXQK0ngZ&4@_btu6^oSmJ{!wz%z{>lq`0+Qdo^E?E;uJAB(7-7) zEvYH^vgh>6o+HIJp~2?9%y)|3+Z5UT)4tf^-3Gl!6VdnU^awuYP#xBvB9{jqDo+g>BiWIblT()(tn#csmR|pb)0q6&!}W{B z;qD{B=Xsy*ss5rR(A>sPRPZKwP0+0wW6^RV^-|60S=?M^D#=up^{rv_6>e z&QFU!4taIGY%^uv%pqac!TDJG>CNAlcOR*@tMS^8DcoOTg#S5KS=H_}9q+oK%`@9< z;_?P+f7L&O4WGE6lIS}mL!8xJ$sf(H$};OX-CzF?>dvV%+II1Y{%xFNH~p}YLnwXE zb4DF&+6=rgSyHGfZU<&G4cjjNs`4F<+tX}A*9TpcHYAyen{UOexlwDNR zJpQNs>HN6|qS@tm#qIjTU*!}X`m*GTlijOZj?j;&4Yus5yw)A(Y~oiXXB_=g;zHH* zyG{>&Fns((wC?Ay#3oV90lV3Eit2w+>shXSe^<)!{jW*y>_xfIv=^VglfHlQ)z>Xy Y>hpvjGAGh|CEDArTy+L4jf?1P}-y5E3NxGE)L61f*30s6(kyfZ z5D+7B5eX0q2wp+)UVBmGA@6r+)zMZ2D;?WPJ5Fb+z5AS?S36y6y4Lj9U3atD+56ky z<9x5ZzjLC~(&B&~SZhs_^Wo@JNTWZ*Ipgx)&lZX$C_pc`75#zjTO9Ut85fOGzHBHZ zx)X5ijVbGpAAiyU^mVL!AVz|CclyTY>@;MTSQw89K*Ett-V9&w&5SLG$By^+A`EYD zH{@N>UQsq8Nf+(fC842maE3Z2GG*n5nh^7yu~^ugbp1esuMzv%`{AtRsC8ofVaM zD;C{4i z6xBTZ1aYL3JT^rh`-VJWGRNcZNV&6>;0nybpv#$%KC zEJ1hHt=BuII)Vdru6_zvn!<&qxbLelkR5K-1F5J<>OAE4eajZZ%G|_?clTGNm8hCe zsUB)-O)(UJgD7abw@<#juPkl90vlCLVpZcW?X2`6I$%Lt4(=iAdT2J)7_;yYfIek$ zse{>`p%UhxBp@^=crYjOrjmEF>)*^?I03pHHkOTNNL;{RMZkoO&%_LK%qA+988!0@ zdK~c}7B5f{%9(eoGNky;<;j>?q>wG?EI!CwCkY}HpIt;$ld9D*KTFkvIt}sk%(W8U zY4;vY^=Zkt-*U~aafkagl5yJbss6fClPbx0xVcKLo9(wgZQQ1rhA@Za8p{EPWQZr8 zRvBwPNr1G1N!3zw4-w8vl&9UhdU!g17*ol(=Jz$@*Ze+%6eXXY&g?Nsg0t^aYaWl8 zpfD(RZ7{*YhXwtXyg(W_a|kIYGZGRhjg$)Koa2@ib&MfegY&Vn?Ho;E4A;S3opT7& z905Q^cr}VChe^U>N>fd?DZRNtA*T;}{Kx2~5l?hz?Hl)B>F6T_nKLd)G)wlYF$P_ry{B4fkqBkejKjOhFMW}$n;gmeNCOPS~vAdpZJCh zgIO2PSTOT<=4A;^=H9wgl(dk0S6gsbd+ZPPhed*_*Sb!1s0l#R2}?(%u#_=aQ@Dd| zqI2+C=7jDc4xS+2JVA}PK#iLA9DBlyUS&?%gurl#vrU?^&7H9m#cfHN@e$4NMRR$g zPr5~KUn&rE7uQ%JhrOOTWuN<&xrQsK0>yePb2O)FztGhGBy;N0 zcAzW(6Ynju_AP2$Zx!@VKs?%}X z6g(YrLhN64006z^<`L*oLXG8m&2fF^xL$nTHvT_rb7*Qo!&U;|06^cx#p&#cV|8Kl z(5`t!>;q~)*->71C|+V=%PbB*N)eh;)-$Rs{Tpj$9ph*Y5}srig;yMI;or!m8F}Gh z+~UDm2VgmfqmJlNBlMvk(H1@f##X_|s%`~X)6Cu{Ox9|^+WKGmp+@O5C(ype1qzBL z;$YXUd!GdK+HC8!3Hg_VtPzucA`5B+1x?tj$$}a|LBEo$U*mcIpU3}c3&60$S;Bui z_F2jXJ*h7a9H9m(knl;SG*vLkOm~d5K?HV83zgA~?s`Y9!FmEWm=^W;a^@Q&)Wh4pN?qde^K5=O^d|ywQV#%*K!Ll-BYI^i0+zzl>>U9Z z(@%F~5pgK89{O}nOgB4Y4`!+xAQ*ysF~pH+X6&MGm0Dasbiy-YCisL%tXe*`o;kJ} zX;r_xztLo373wXP*SF}w>jj$K5HYTUIuta4T~T~~Qo3pld}U+6#2R*zeeLr8dJlP{rls91 zmKXvHA9#Rk4IxtqYI$^pg~A{x$-Y>}vVBEw4XH9oDsE|Mf%lCb4z zDLZM+nr8N>I%+R8e$JZ921#U~r%Jpv4tlHezq4%YXfv3TmYY1r|u)}CY<*$c7PRfG-LS`E*s4^{5-~eaV%dO}V zgZ-*QJV5e_^m}*6EIx9rAs#cdbG%>;@W#-ifyIo6R9Mdy5mF|@!_-}*4Kh+;42RR! zRUNQQmT?m^yapEimXU_p#8Sq3E!0F^B|O@B*^W)8b)I2 z0aB*-z!Hi)pLmqvf5|$clrfMfvl{5POKI)Wx|CX7=$}q(>oQ6y?d<7V$QbJ(xt6wj zb;W0n8G`BnU%+x(@a^MF3qDKV4NnQ2^fr76gF%vl#sYLXUc)W*gAWE@oX#q_Tr7HE zH5kLDsT)ceOV|clpNeUsQ9pD8R;tQr?n;dWQecIvn|c=NqubzeI9`yI2V{lf!EucO zE;VZ98U-YS>mmY_f#EeMU(~>G8Sd4ki24e*WD2U5h+u(8{AU{+Fwu_Ct zwIxkGi<0Sf6EmTKxpW=g#o5G6$XJ0kX6mxjS1_E%f+{D1Nu9sy5$OttI2Z{_2TUxoWO7-;be?Dyl5c~-T z7pqPZbv;i%q(29AT<$G@12{N3iS6wtMN+dXmseQ$Ks=jpRNn)^8N1*9`i4{O?n0X! zIcFXAJ}1=&u*#!4v4Vq{67o9d-yjqhSE}23cipvf&j|bmmWQSUE2}Yb=#fF=u;L+n zc*#u@4gd%|u3^I?0Efd0ENqQi`#Qmbp9au|ew{#XFt;DxQm=dKt)PgIpr9Y4AjLnl zNOqho@Ooh#SEXm}_}D7RV^`O`RCWT)Gkw@8=snEz$7VWGcjVKHs&&X%eYf@RxI z8gW44CoFvSoKp#k0(s9@l*!LO5PN=j;L2fE>q(MJ-`z;cy_JyN3tM_Rr@ncoTVv@$04~F)4D-9oE~`b4>!t^Pcc*#bGh5uW+M*s9`4k#1KAI@9BB?Kc<%DO zyZyibA@<>u36rKHH@eN+&Lw?y-icp%*(%~8S-7WCP%zsrIT5s><2otHyi8bXZ1vRO zv8+1?cj&JtLrDha@&kW#yyT42?s=2^<6=iv(z;7y$<$A+G6p?nHpY+kdRx2pjXDNd z2Hl=my+I&f+dkW2)kSK!Yka=bmc!URiZES71|P)Fq5K6FmC+AiE)N=`tSPQe>*Er5*9 zCH`+u1vSf_Juo}p{C06_{B=bZ#nAPwpnC5FTZ@h*^D`ek`u*mF0`0!5o9O(yjxC#8 zA1Sy0cS_secJ4NH%=>a+(PW@y#n(P`b)nO#B0jj*KVUNbFQRV^$M`I2g{@ct| zkpH+qtKUE0d?Q}SlR0XH21eW`4RzzUPoB>DIFEjol6CTE!TEhNTO=zV{r2Opzl&{C zUVZkTGe=h+Fur>-F`_M8U4ehTGf#vTg6vemiuJ~iT8B9se3gBH1m*^_)?D~z3wx&# zy$zS@CqL&acXj_Z;J5%Jy#3=3-%1YHj|f0yblOdo|R zts{Ro2&}_Bf424hhgn8P#M0K4kA;GB!*80=(); - let (.., player_transform, player_body) = + let (player_sprite, player_transform, player_body) = players.get(dropped.player).expect("Parent is not a player"); // Re-activate physics @@ -223,8 +223,15 @@ fn update_idle_grenades( body.velocity = player_body.velocity; body.is_spawning = true; + let horizontal_flip_factor = if player_sprite.flip_x { + Vec2::new(-1.0, 1.0) + } else { + Vec2::ONE + }; + // Drop item at player position - transform.translation = player_transform.translation + grab_offset.extend(0.0); + transform.translation = + player_transform.translation + (*grab_offset * horizontal_flip_factor).extend(0.0); } } } diff --git a/src/metadata/player.rs b/src/metadata/player.rs index be64c5af8f..8baf54e177 100644 --- a/src/metadata/player.rs +++ b/src/metadata/player.rs @@ -52,6 +52,16 @@ pub struct PlayerSounds { pub jump_volume: f32, #[serde(skip)] pub jump_handle: Handle, + + pub grab: String, + pub grab_volume: f32, + #[serde(skip)] + pub grab_handle: Handle, + + pub drop: String, + pub drop_volume: f32, + #[serde(skip)] + pub drop_handle: Handle, } impl PlayerSpritesheetMeta { diff --git a/src/player/state/states/idle.rs b/src/player/state/states/idle.rs index 3a27674e40..51d8cf408d 100644 --- a/src/player/state/states/idle.rs +++ b/src/player/state/states/idle.rs @@ -31,12 +31,17 @@ pub fn handle_player_state( Entity, &PlayerState, &PlayerIdx, + &Handle, &mut AnimationBankSprite, &mut KinematicBody, )>, collision_world: CollisionWorld, + player_assets: Res>, + effects: Res>, ) { - for (player_ent, player_state, player_idx, mut sprite, mut body) in &mut players { + for (player_ent, player_state, player_idx, meta_handle, mut sprite, mut body) in &mut players { + let meta = player_assets.get(meta_handle).unwrap(); + if player_state.id != ID { continue; } @@ -78,12 +83,26 @@ pub fn handle_player_state( // Grab the first item we are touching if let Some((item, _)) = colliders.get(0) { commands.add(PlayerSetInventoryCommand::new(player_ent, Some(*item))); + + // Play grab sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.grab_handle.clone_weak()) + .with_volume(meta.sounds.grab_volume as _); + } } // If we are already carrying an item } else { // Drop it commands.add(PlayerSetInventoryCommand::new(player_ent, None)); + + // Play drop sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.drop_handle.clone_weak()) + .with_volume(meta.sounds.drop_volume as _); + } } } @@ -94,6 +113,15 @@ pub fn handle_player_state( // If we are jumping if control.jump_just_pressed { + // Play jump sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.jump_handle.clone_weak()) + // TODO: This volume should be relative to the current channel volume, not + // hard-coded, so that when the user changes the sound effect volume it's relative. + .with_volume(meta.sounds.jump_volume as _); + } + // Move up body.velocity.y = JUMP_SPEED; } diff --git a/src/player/state/states/walk.rs b/src/player/state/states/walk.rs index 48706d15d2..8a07566f54 100644 --- a/src/player/state/states/walk.rs +++ b/src/player/state/states/walk.rs @@ -84,12 +84,26 @@ pub fn handle_player_state( // Grab the first item we are touching if let Some((item, _)) = colliders.get(0) { commands.add(PlayerSetInventoryCommand::new(player_ent, Some(*item))); + + // Play grab sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.grab_handle.clone_weak()) + .with_volume(meta.sounds.grab_volume as _); + } } // If we are already carrying an item } else { // Drop it commands.add(PlayerSetInventoryCommand::new(player_ent, None)); + + // Play drop sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.drop_handle.clone_weak()) + .with_volume(meta.sounds.drop_volume as _); + } } } From b7cded5a47b1da1fd1df0ed5b8f5c4c0a8359243 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 17:16:16 -0600 Subject: [PATCH 6/7] Remove bevy_mod_js_scripting For Now To avoid the unused dependencies, comment out all the script loading code and disable the scripting plugin. --- Cargo.lock | 1003 +---------------- Cargo.toml | 3 +- assets/default.game.yaml | 4 - .../environment/crab/crab.element.yaml | 2 - .../fish_school/fish_school.element.yaml | 2 - .../item/blunderbass/blunderbass.element.yaml | 2 - .../elements/item/cannon/cannon.element.yaml | 2 - .../elements/item/crate/crate.element.yaml | 2 - .../item/kick_bomb/kick_bomb.element.yaml | 5 +- .../item/machine_gun/machine_gun.element.yaml | 2 - .../elements/item/mines/mines.element.yaml | 2 - .../elements/item/musket/musket.element.yaml | 2 - .../sniper_rifle/sniper_rifle.element.yaml | 2 - src/assets.rs | 36 +- src/loading.rs | 19 +- src/main.rs | 5 +- src/map.rs | 32 +- src/metadata.rs | 12 +- src/metadata/map.rs | 8 +- 19 files changed, 79 insertions(+), 1066 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63fda22145..d81bc947c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,16 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "ab_glyph" version = "0.2.18" @@ -185,20 +175,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "ast_node" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf94863c5fdfee166d0907c44e5fee970123b2b7307046d35d1e671aa93afbba" -dependencies = [ - "darling", - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - [[package]] name = "async-channel" version = "1.7.1" @@ -310,27 +286,12 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "better_scoped_tls" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73e8ecdec39e98aa3b19e8cd0b8ed8f77ccb86a6b0b2dc7cd86d105438a2123" -dependencies = [ - "scoped-tls", -] - [[package]] name = "bevy" version = "0.8.1" @@ -733,38 +694,6 @@ dependencies = [ "glam", ] -[[package]] -name = "bevy_mod_js_scripting" -version = "0.1.0" -source = "git+https://github.com/zicklag/bevy_mod_js_scripting.git?branch=jumpy#9781be0f8035ba43fa4498d88f1efba658ab4ed5" -dependencies = [ - "anyhow", - "bevy", - "bevy_ecs_dynamic", - "bevy_reflect", - "bevy_reflect_fns", - "deno_core", - "fixedbitset", - "indexmap", - "js-sys", - "pollster", - "serde", - "serde-wasm-bindgen", - "serde_json", - "serde_v8", - "slotmap", - "swc_atoms", - "swc_common", - "swc_ecma_codegen", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_typescript", - "swc_ecma_visit", - "type-map 0.5.0", - "wasm-bindgen", - "wasm_mutex", -] - [[package]] name = "bevy_pbr" version = "0.8.1" @@ -835,15 +764,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "bevy_reflect_fns" -version = "0.1.0" -source = "git+https://github.com/jakobhellermann/bevy_reflect_fns?rev=22e85021851e0cfe27b87e428f6313dd8c26abde#22e85021851e0cfe27b87e428f6313dd8c26abde" -dependencies = [ - "bevy_reflect", - "thiserror", -] - [[package]] name = "bevy_render" version = "0.8.1" @@ -1170,15 +1090,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-buffer" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.2.0" @@ -1444,12 +1355,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed2b28323eee4fb66bb824401daa3e46bd445b9a9298a3d382b320710ba69dd" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "copyless" version = "0.1.5" @@ -1583,15 +1488,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cpufeatures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.3.2" @@ -1620,16 +1516,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "cty" version = "0.2.2" @@ -1682,28 +1568,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dashmap" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core 0.9.4", -] - -[[package]] -name = "debug_unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -dependencies = [ - "unreachable", -] - [[package]] name = "deflate" version = "0.8.6" @@ -1714,66 +1578,17 @@ dependencies = [ "byteorder", ] -[[package]] -name = "deno_core" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88475da37fe0544b7372fd4705560df496498eb5eeb40ce19bfe7787ed0600ca" -dependencies = [ - "anyhow", - "deno_ops", - "futures", - "indexmap", - "libc", - "log", - "once_cell", - "parking_lot 0.12.1", - "pin-project", - "serde", - "serde_json", - "serde_v8", - "sourcemap", - "url", - "v8", -] - -[[package]] -name = "deno_ops" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e217fd2f9a61bc581f6b13868a46ef800efb7532348fd86cc4fe49204d203ea6" -dependencies = [ - "once_cell", - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "syn", -] - [[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.0", "syn", ] -[[package]] -name = "digest" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "directories" version = "4.0.1" @@ -1893,18 +1708,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "enum_kind" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b940da354ae81ef0926c5eaa428207b8f4f091d3956c891dfbd124162bed99" -dependencies = [ - "pmutil", - "proc-macro2", - "swc_macros_common", - "syn", -] - [[package]] name = "env_logger" version = "0.8.4" @@ -2112,18 +1915,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "from_variant" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0981e470d2ab9f643df3921d54f1952ea100c39fdb6a3fdc820e20d2291df6c" -dependencies = [ - "pmutil", - "proc-macro2", - "swc_macros_common", - "syn", -] - [[package]] name = "fsevent-sys" version = "4.1.0" @@ -2133,16 +1924,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fslock" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57eafdd0c16f57161105ae1b98a1238f97645f2f588438b2949c99a2af9616bf" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "futures" version = "0.3.25" @@ -2151,7 +1932,6 @@ checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -2174,17 +1954,6 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" -[[package]] -name = "futures-executor" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.25" @@ -2256,16 +2025,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generic-array" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "gethostname" version = "0.2.3" @@ -2528,12 +2287,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - [[package]] name = "image" version = "0.23.14" @@ -2625,7 +2378,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" dependencies = [ - "type-map 0.4.0", + "type-map", "unic-langid", ] @@ -2648,19 +2401,6 @@ dependencies = [ "mach", ] -[[package]] -name = "is-macro" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c068d4c6b922cd6284c609cfa6dec0e41615c9c5a1a4ba729a970d8daba05fb" -dependencies = [ - "Inflector", - "pmutil", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "itertools" version = "0.10.5" @@ -2738,7 +2478,7 @@ version = "0.4.3" dependencies = [ "anyhow", "async-channel", - "base64 0.13.1", + "base64", "bevy", "bevy-has-load-progress", "bevy-inspector-egui", @@ -2749,7 +2489,6 @@ dependencies = [ "bevy_fluent", "bevy_ggrs", "bevy_kira_audio", - "bevy_mod_js_scripting", "bevy_prototype_lyon", "bevy_tweening", "bitfield", @@ -2778,6 +2517,7 @@ dependencies = [ "rand", "rustls", "serde", + "serde_json", "serde_yaml", "sys-locale", "thiserror", @@ -2905,79 +2645,6 @@ dependencies = [ "syn", ] -[[package]] -name = "lexical" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" -dependencies = [ - "lexical-util", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.137" @@ -3296,12 +2963,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - [[package]] name = "nix" version = "0.22.3" @@ -3389,18 +3050,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "serde", -] - [[package]] name = "num-derive" version = "0.3.3" @@ -3671,7 +3320,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "base64 0.13.1", + "base64", ] [[package]] @@ -3700,74 +3349,30 @@ dependencies = [ ] [[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros", - "phf_shared", - "proc-macro-hack", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" +name = "pin-project" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ - "phf_shared", - "rand", + "pin-project-internal", ] [[package]] -name = "phf_macros" -version = "0.10.0" +name = "pin-project-internal" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", "proc-macro2", "quote", "syn", ] [[package]] -name = "phf_shared" -version = "0.10.0" +name = "pin-project-lite" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher 0.3.10", -] - -[[package]] -name = "pin-project" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -3781,17 +3386,6 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" -[[package]] -name = "pmutil" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "png" version = "0.16.8" @@ -3830,12 +3424,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "pollster" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" - [[package]] name = "postcard" version = "1.0.2" @@ -3870,12 +3458,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - [[package]] name = "pretty-type-name" version = "1.0.0" @@ -3917,12 +3499,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" version = "1.0.47" @@ -4163,7 +3739,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" dependencies = [ - "base64 0.13.1", + "base64", "bitflags", "serde", ] @@ -4180,24 +3756,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.14", -] - [[package]] name = "rustls" version = "0.20.7" @@ -4228,7 +3786,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ - "base64 0.13.1", + "base64", ] [[package]] @@ -4276,12 +3834,6 @@ dependencies = [ "windows-sys 0.36.1", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.1.0" @@ -4327,27 +3879,6 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.147" @@ -4357,26 +3888,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - -[[package]] -name = "serde_bytes" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" -dependencies = [ - "serde", -] - [[package]] name = "serde_derive" version = "1.0.147" @@ -4390,30 +3901,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ - "indexmap", "itoa", "ryu", "serde", ] -[[package]] -name = "serde_v8" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c3efa9cff97d5a543df0508c37af619e422fb92eb525f38d255d46df7a0eb7" -dependencies = [ - "bytes", - "derive_more", - "serde", - "serde_bytes", - "smallvec", - "v8", -] - [[package]] name = "serde_yaml" version = "0.9.14" @@ -4427,17 +3923,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest", -] - [[package]] name = "sha1_smol" version = "1.0.0" @@ -4474,12 +3959,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -[[package]] -name = "siphasher" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - [[package]] name = "slab" version = "0.4.7" @@ -4495,7 +3974,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" dependencies = [ - "serde", "version_check", ] @@ -4518,22 +3996,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "sourcemap" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e031f2463ecbdd5f34c950f89f5c1e1032f22c0f8e3dc4bdb2e8b6658cf61eb" -dependencies = [ - "base64 0.11.0", - "if_chain", - "lazy_static", - "regex", - "rustc_version 0.2.3", - "serde", - "serde_json", - "url", -] - [[package]] name = "spin" version = "0.5.2" @@ -4550,18 +4012,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdweb" version = "0.1.3" @@ -4574,45 +4024,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" -[[package]] -name = "string_cache" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.1", - "phf_shared", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", -] - -[[package]] -name = "string_enum" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "994453cd270ad0265796eb24abf5540091ed03e681c5f3c12bc33e4db33253e1" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - [[package]] name = "strsim" version = "0.10.0" @@ -4632,297 +4043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff" dependencies = [ "float-cmp", - "siphasher 0.2.3", -] - -[[package]] -name = "swc_atoms" -version = "0.4.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8033a868fbebf5829797ac0c543499622b657e2d33a08ca6ab12547b8bafc" -dependencies = [ - "once_cell", - "rustc-hash", - "serde", - "string_cache", - "string_cache_codegen", - "triomphe", -] - -[[package]] -name = "swc_common" -version = "0.27.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b0b6107e44797d0549bdb5b47a97682c3b914140269c01d2acdb16a1b885f6" -dependencies = [ - "ahash 0.7.6", - "ast_node", - "better_scoped_tls", - "cfg-if 1.0.0", - "debug_unreachable", - "either", - "from_variant", - "num-bigint", - "once_cell", - "rustc-hash", - "serde", - "siphasher 0.3.10", - "string_cache", - "swc_atoms", - "swc_eq_ignore_macros", - "swc_visit", - "tracing", - "unicode-width", - "url", -] - -[[package]] -name = "swc_config" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4de36224eb9498fccd4e68971f0b83326ccf8592c2d424f257f3a1c76b2b211" -dependencies = [ - "indexmap", - "serde", - "serde_json", - "swc_config_macro", -] - -[[package]] -name = "swc_config_macro" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb64bc03d90fd5c90d6ab917bb2b1d7fbd31957df39e31ea24a3f554b4372251" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_ast" -version = "0.90.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f712949db06518bec7b7e050aa3bcde749a74fbf79f4f520ab179d0445b63593" -dependencies = [ - "bitflags", - "is-macro", - "num-bigint", - "scoped-tls", - "serde", - "string_enum", - "swc_atoms", - "swc_common", - "unicode-id", -] - -[[package]] -name = "swc_ecma_codegen" -version = "0.121.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa47424bed05de6077eda3271d6764f87c2735a8f3798dea23c95898e5e0deb" -dependencies = [ - "memchr", - "num-bigint", - "once_cell", - "rustc-hash", - "serde", - "sourcemap", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen_macros", - "tracing", -] - -[[package]] -name = "swc_ecma_codegen_macros" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0159c99f81f52e48fe692ef7af1b0990b45d3006b14c6629be0b1ffee1b23aea" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.117.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88ffca99514bc8bfa8bf4f2d74fb673caa844e521b55035b8cfd10472b801d4" -dependencies = [ - "either", - "enum_kind", - "lexical", - "num-bigint", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "0.103.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aad7af4a1ae307e547a0f5ab6b081ffa6a22af89abe2f8a953a735a398ba9d" -dependencies = [ - "better_scoped_tls", - "bitflags", - "num_cpus", - "once_cell", - "phf", - "rustc-hash", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebf907935ec5492256b523ae7935a824d9fdc0368dcadc41375bad0dca91cd8b" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_transforms_react" -version = "0.141.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57461fea819904faf5aeac39e49229995701a31fa5041929b7909885a69cc0a" -dependencies = [ - "ahash 0.7.6", - "base64 0.13.1", - "dashmap", - "indexmap", - "once_cell", - "regex", - "serde", - "sha-1", - "string_enum", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_typescript" -version = "0.145.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0cba6d14b04900e5068d69c7492149c4e9320a9fcf79fca0e7224811c1d14" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_react", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_utils" -version = "0.99.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92cff624945ded0b2bb07e9dfb44d57745abcc415b6025c6c3d2dc3a7af5396" -dependencies = [ - "indexmap", - "once_cell", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_visit", - "tracing", - "unicode-id", -] - -[[package]] -name = "swc_ecma_visit" -version = "0.76.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da9fbd418ce4dc3c7b10e74a919ecc6f56c376d63a6a03766655c6c2283475d" -dependencies = [ - "num-bigint", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_eq_ignore_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c20468634668c2bbab581947bb8c75c97158d5a6959f4ba33df20983b20b4f6" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "swc_macros_common" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4be988307882648d9bc7c71a6a73322b7520ef0211e920489a98f8391d8caa2" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "swc_visit" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f2bcb7223e185c4c7cbf5e0c1207dec6d2bfd5e72e3fb7b3e8d179747e9130" -dependencies = [ - "either", - "swc_visit_macros", -] - -[[package]] -name = "swc_visit_macros" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1f3561674d84947694d41fb6d5737d19539222779baeac1b3a071a2b29428" -dependencies = [ - "Inflector", - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", + "siphasher", ] [[package]] @@ -5247,16 +4368,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "triomphe" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" -dependencies = [ - "serde", - "stable_deref_trait", -] - [[package]] name = "ttf-parser" version = "0.17.1" @@ -5283,21 +4394,6 @@ dependencies = [ "rustc-hash", ] -[[package]] -name = "type-map" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" -dependencies = [ - "rustc-hash", -] - -[[package]] -name = "typed-arena" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" - [[package]] name = "typenum" version = "1.15.0" @@ -5339,12 +4435,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" -[[package]] -name = "unicode-id" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" - [[package]] name = "unicode-ident" version = "1.0.5" @@ -5372,15 +4462,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -dependencies = [ - "void", -] - [[package]] name = "unsafe-libyaml" version = "0.2.4" @@ -5402,7 +4483,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -5416,19 +4496,6 @@ dependencies = [ "sha1_smol", ] -[[package]] -name = "v8" -version = "0.47.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be156dece7a023d5959a72dc0d398d6c95100ec601a2cea10d868da143e85166" -dependencies = [ - "bitflags", - "fslock", - "lazy_static", - "libc", - "which", -] - [[package]] name = "valuable" version = "0.1.0" @@ -5453,12 +4520,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "waker-fn" version = "1.1.0" @@ -5548,15 +4609,6 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" -[[package]] -name = "wasm_mutex" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbdddc3b163fc2d639800b3411a5428d1e151ba2a400a560b1545e39f1e68cd" -dependencies = [ - "serde", -] - [[package]] name = "web-sys" version = "0.3.60" @@ -5616,7 +4668,7 @@ dependencies = [ "js-sys", "log", "naga", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "raw-window-handle", "smallvec", "wasm-bindgen", @@ -5642,7 +4694,7 @@ dependencies = [ "fxhash", "log", "naga", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "profiling", "raw-window-handle", "smallvec", @@ -5679,7 +4731,7 @@ dependencies = [ "metal", "naga", "objc", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "profiling", "range-alloc", "raw-window-handle", @@ -5700,17 +4752,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "which" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" -dependencies = [ - "either", - "libc", - "once_cell", -] - [[package]] name = "widestring" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index b45225b1ae..7af5685346 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ bevy_egui = "0.16.1" bevy_fluent = "0.4.0" bevy_ggrs = { git = "https://github.com/zicklag/bevy_ggrs.git", branch = "jumpy" } bevy_kira_audio = { version = "0.12.0", features = ["ogg"], default-features = false } -bevy_mod_js_scripting = { git = "https://github.com/zicklag/bevy_mod_js_scripting.git", branch = "jumpy" } +# bevy_mod_js_scripting = { git = "https://github.com/zicklag/bevy_mod_js_scripting.git", branch = "jumpy" } bevy_prototype_lyon = "0.6.0" bevy_tweening = { version = "0.5", default-features = false } bitfield = "0.14.0" @@ -69,6 +69,7 @@ thiserror = "1.0.31" tracing = { version = "0.1.37", features = ["release_max_level_debug"] } turborand = { version = "0.8.0", features = ["atomic", "serialize"] } unic-langid = "0.9.0" +serde_json = "1.0.89" [dependencies.bevy] version = "0.8" diff --git a/assets/default.game.yaml b/assets/default.game.yaml index d68516142c..4e93003ccb 100644 --- a/assets/default.game.yaml +++ b/assets/default.game.yaml @@ -45,10 +45,6 @@ playlist: - music/krill_or_be_krilled.ogg - music/whale_theme.ogg -scripts: - - map/scripts/kill_out_of_bounds.ts - - ui/menu-background-zoom.ts - main_menu: title_font: family: fairfax diff --git a/assets/map/elements/environment/crab/crab.element.yaml b/assets/map/elements/environment/crab/crab.element.yaml index 8e818d5ea9..8a1e147d23 100644 --- a/assets/map/elements/environment/crab/crab.element.yaml +++ b/assets/map/elements/environment/crab/crab.element.yaml @@ -1,7 +1,5 @@ name: Crab category: Critters -scripts: - # - ./crab.ts editor_size: [17, 12] preload_assets: - ./crab.atlas.yaml diff --git a/assets/map/elements/environment/fish_school/fish_school.element.yaml b/assets/map/elements/environment/fish_school/fish_school.element.yaml index b40f5763aa..7a1fee617d 100644 --- a/assets/map/elements/environment/fish_school/fish_school.element.yaml +++ b/assets/map/elements/environment/fish_school/fish_school.element.yaml @@ -1,4 +1,2 @@ name: Fish School category: Critters -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/blunderbass/blunderbass.element.yaml b/assets/map/elements/item/blunderbass/blunderbass.element.yaml index 8f6760fb95..a55bd88c21 100644 --- a/assets/map/elements/item/blunderbass/blunderbass.element.yaml +++ b/assets/map/elements/item/blunderbass/blunderbass.element.yaml @@ -1,4 +1,2 @@ name: Blunderbass category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/cannon/cannon.element.yaml b/assets/map/elements/item/cannon/cannon.element.yaml index ee74a4a546..67ff6b53e0 100644 --- a/assets/map/elements/item/cannon/cannon.element.yaml +++ b/assets/map/elements/item/cannon/cannon.element.yaml @@ -1,4 +1,2 @@ name: Canon category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/crate/crate.element.yaml b/assets/map/elements/item/crate/crate.element.yaml index 5db25a2c33..1f875fb200 100644 --- a/assets/map/elements/item/crate/crate.element.yaml +++ b/assets/map/elements/item/crate/crate.element.yaml @@ -1,4 +1,2 @@ name: Crate category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml b/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml index 9d92f99c02..1eb4dfe297 100644 --- a/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml +++ b/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml @@ -1,8 +1,5 @@ name: Kick Bomb category: Weapons -scripts: - # - ./kick_bomb_spawner.ts - # - ./kick_bomb.ts preload_assets: - ./kick_bomb.atlas.yaml - - ./explosion.atlas.yaml \ No newline at end of file + - ./explosion.atlas.yaml diff --git a/assets/map/elements/item/machine_gun/machine_gun.element.yaml b/assets/map/elements/item/machine_gun/machine_gun.element.yaml index e27ed529f1..8b9eb1005f 100644 --- a/assets/map/elements/item/machine_gun/machine_gun.element.yaml +++ b/assets/map/elements/item/machine_gun/machine_gun.element.yaml @@ -1,4 +1,2 @@ name: Machine Gun category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/mines/mines.element.yaml b/assets/map/elements/item/mines/mines.element.yaml index 9ec2ea0d61..529141d8ee 100644 --- a/assets/map/elements/item/mines/mines.element.yaml +++ b/assets/map/elements/item/mines/mines.element.yaml @@ -1,4 +1,2 @@ name: Mines category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/musket/musket.element.yaml b/assets/map/elements/item/musket/musket.element.yaml index f0b0a09c39..06e1644f9d 100644 --- a/assets/map/elements/item/musket/musket.element.yaml +++ b/assets/map/elements/item/musket/musket.element.yaml @@ -1,4 +1,2 @@ name: Musket category: Weapons -scripts: - # - ./musket.ts diff --git a/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml b/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml index 58680c0180..c8d682c337 100644 --- a/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml +++ b/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml @@ -1,4 +1,2 @@ name: Sniper Rifle category: Weapons -scripts: - # - ./sproinger.ts diff --git a/src/assets.rs b/src/assets.rs index ebe7c1950a..eb8e290580 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -8,7 +8,6 @@ use bevy::{ reflect::TypeUuid, }; use bevy_egui::egui; -use bevy_mod_js_scripting::{serde_json, JsScript}; use normalize_path::NormalizePath; use crate::{ @@ -26,7 +25,8 @@ pub struct AssetPlugin; impl Plugin for AssetPlugin { fn build(&self, app: &mut App) { - app.register_type::>() + app + // .register_type::>() .register_type::>() .add_jumpy_asset::() .add_asset_loader(GameMetaLoader) @@ -208,14 +208,14 @@ impl AssetLoader for GameMetaLoader { ); } - // Load the script handles - for script_relative_path in &meta.scripts { - let (script_path, script_handle) = - get_relative_asset(load_context, self_path, script_relative_path); - dependencies.push(script_path.clone()); - meta.script_handles - .push(AssetHandle::new(script_path, script_handle.typed())); - } + // // Load the script handles + // for script_relative_path in &meta.scripts { + // let (script_path, script_handle) = + // get_relative_asset(load_context, self_path, script_relative_path); + // dependencies.push(script_path.clone()); + // meta.script_handles + // .push(AssetHandle::new(script_path, script_handle.typed())); + // } load_context.set_default_asset(LoadedAsset::new(meta).with_dependencies(dependencies)); @@ -366,14 +366,14 @@ impl AssetLoader for MapElementMetaLoader { let mut dependencies = Vec::new(); - // Load the element script - for script in &meta.scripts { - let (script_path, script_handle) = - get_relative_asset(load_context, self_path, script); - meta.script_handles - .push(AssetHandle::new(script_path.clone(), script_handle.typed())); - dependencies.push(script_path); - } + // // Load the element script + // for script in &meta.scripts { + // let (script_path, script_handle) = + // get_relative_asset(load_context, self_path, script); + // meta.script_handles + // .push(AssetHandle::new(script_path.clone(), script_handle.typed())); + // dependencies.push(script_path); + // } // Load assets for built-in types match &mut meta.builtin { diff --git a/src/loading.rs b/src/loading.rs index b1da6724df..630cf9b42d 100644 --- a/src/loading.rs +++ b/src/loading.rs @@ -2,7 +2,6 @@ use bevy::{ecs::system::SystemParam, render::camera::ScalingMode}; use bevy_egui::{egui, EguiContext}; use bevy_fluent::Locale; use bevy_has_load_progress::{HasLoadProgress, LoadingResources}; -use bevy_mod_js_scripting::ActiveScripts; use leafwing_input_manager::{ axislike::{AxisType, SingleAxis}, prelude::InputMap, @@ -99,7 +98,7 @@ pub struct GameLoader<'w, 's> { game_assets: ResMut<'w, Assets>, egui_ctx: Option>, events: EventReader<'w, 's, AssetEvent>, - active_scripts: ResMut<'w, ActiveScripts>, + // active_scripts: ResMut<'w, ActiveScripts>, storage: ResMut<'w, Storage>, player_assets: ResMut<'w, Assets>, texture_atlas_assets: Res<'w, Assets>, @@ -126,7 +125,7 @@ impl<'w, 's> GameLoader<'w, 's> { game_handle, mut game_assets, mut egui_ctx, - mut active_scripts, + // mut active_scripts, mut clear_color, mut storage, mut player_assets, @@ -142,10 +141,10 @@ impl<'w, 's> GameLoader<'w, 's> { // event, we need to skip the next update event. *skip_next_asset_update_event = true; - // Clear the active scripts - active_scripts.clear(); + // // Clear the active scripts + // active_scripts.clear(); - // One-time initialization + // One-time initialization } else { if let Some(ctx) = egui_ctx.as_mut() { // Initialize empty fonts for all game fonts. @@ -238,10 +237,10 @@ impl<'w, 's> GameLoader<'w, 's> { } } - // Set the active scripts - for script_handle in &game.script_handles { - active_scripts.insert(script_handle.inner.clone_weak()); - } + // // Set the active scripts + // for script_handle in &game.script_handles { + // active_scripts.insert(script_handle.inner.clone_weak()); + // } // Insert the game resource commands.insert_resource(game.clone()); diff --git a/src/main.rs b/src/main.rs index a8d75a1275..da2d2bbbb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,7 +47,7 @@ pub mod prelude; pub mod random; pub mod run_criteria; pub mod schedule; -pub mod scripting; +// pub mod scripting; pub mod session; pub mod ui; pub mod utils; @@ -74,7 +74,6 @@ use crate::{ player::PlayerPlugin, prelude::*, random::RandomPlugin, - scripting::ScriptingPlugin, session::SessionPlugin, ui::UiPlugin, utils::{is_in_game_run_criteria, UtilsPlugin}, @@ -232,7 +231,7 @@ pub fn main() { .add_plugin(WorkaroundsPlugin) .add_plugin(DebugPlugin) .add_plugin(RandomPlugin) - .add_plugin(ScriptingPlugin) + // .add_plugin(ScriptingPlugin) .add_plugin(NetworkingPlugin) .add_plugin(SessionPlugin); diff --git a/src/map.rs b/src/map.rs index 1f3cd288ee..a1dbf4c5d8 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,6 @@ -use bevy::{render::view::RenderLayers, utils::HashSet}; +use bevy::render::view::RenderLayers; use bevy_ecs_tilemap::prelude::*; -use bevy_mod_js_scripting::{ActiveScripts, JsScript}; +// use bevy_mod_js_scripting::{ActiveScripts, JsScript}; use bevy_parallax::ParallaxResource; use bevy_prototype_lyon::{prelude::*, shapes::Rectangle}; @@ -21,7 +21,7 @@ pub struct MapPlugin; impl Plugin for MapPlugin { fn build(&self, app: &mut App) { app.add_plugin(TilemapPlugin) - .init_resource::() + // .init_resource::() .add_system(hydrate_maps) .extend_rollback_plugin(|plugin| { plugin @@ -38,9 +38,9 @@ impl Plugin for MapPlugin { #[reflect(Component, Default)] pub struct MapElementHydrated; -/// Contains the scripts that have been added for the currently loaded map -#[derive(Deref, DerefMut, Default)] -pub struct MapScripts(pub HashSet>); +// /// Contains the scripts that have been added for the currently loaded map +// #[derive(Deref, DerefMut, Default)] +// pub struct MapScripts(pub HashSet>); /// Marker component for the map grid #[derive(Component)] @@ -54,8 +54,8 @@ pub fn hydrate_maps( asset_server: Res, mut texture_atlas_assets: ResMut>, element_assets: ResMut>, - mut active_scripts: ResMut, - mut map_scripts: ResMut, + // mut active_scripts: ResMut, + // mut map_scripts: ResMut, mut rids: ResMut, unspawned_maps: Query<(Entity, &AssetHandle), Without>, ) { @@ -101,10 +101,10 @@ pub fn hydrate_maps( .id(); map_children.push(grid_entity); - // Clear any previously loaded map scripts - for script in map_scripts.drain() { - active_scripts.remove(&script); - } + // // Clear any previously loaded map scripts + // for script in map_scripts.drain() { + // active_scripts.remove(&script); + // } let mut current_map_element_idx = 0; @@ -195,10 +195,10 @@ pub fn hydrate_maps( for element in &element_layer.elements { let element_meta = element_assets.get(&element.element_handle).unwrap().clone(); - for script_handle in &element_meta.script_handles { - active_scripts.insert(script_handle.inner.clone_weak()); - map_scripts.insert(script_handle.inner.clone_weak()); - } + // for script_handle in &element_meta.script_handles { + // active_scripts.insert(script_handle.inner.clone_weak()); + // map_scripts.insert(script_handle.inner.clone_weak()); + // } let element_name = &element_meta.name; diff --git a/src/metadata.rs b/src/metadata.rs index e900eb3b27..0443750382 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -5,7 +5,6 @@ use crate::prelude::*; use bevy::{reflect::TypeUuid, utils::HashMap}; use bevy_has_load_progress::HasLoadProgress; use bevy_kira_audio::AudioSource; -use bevy_mod_js_scripting::JsScript; mod localization; mod map; @@ -51,12 +50,11 @@ pub struct GameMeta { pub playlist: Vec, #[serde(skip)] pub playlist_handles: Vec>, - - /// Scripts that run on both the server and the client - #[serde(default)] - pub scripts: Vec, - #[serde(skip)] - pub script_handles: Vec>, + // /// Scripts that run on both the server and the client + // #[serde(default)] + // pub scripts: Vec, + // #[serde(skip)] + // pub script_handles: Vec>, } #[derive(HasLoadProgress, Deserialize, Clone, Debug)] diff --git a/src/metadata/map.rs b/src/metadata/map.rs index a963b898e4..0dc4d741ce 100644 --- a/src/metadata/map.rs +++ b/src/metadata/map.rs @@ -173,8 +173,8 @@ impl From for ParallaxLayerData { pub struct MapElementMeta { pub name: String, pub category: String, - #[serde(default)] - pub scripts: Vec, + // #[serde(default)] + // pub scripts: Vec, #[serde(default)] #[has_load_progress(none)] pub builtin: BuiltinElementKind, @@ -183,8 +183,8 @@ pub struct MapElementMeta { #[serde(default = "editor_size_default")] pub editor_size: Vec2, - #[serde(skip)] - pub script_handles: Vec>, + // #[serde(skip)] + // pub script_handles: Vec>, /// Assets that should be pre-loaded by the game before starting #[serde(default)] pub preload_assets: Vec, From 805a189ffed9789875e2beea471544e413974c5e Mon Sep 17 00:00:00 2001 From: Zicklag Date: Tue, 29 Nov 2022 17:21:41 -0600 Subject: [PATCH 7/7] Remove Old Backup Code From src.bkup We're pretty well set on our new networking direction, so we should need this. And the git history can always summon this again. --- src.bkup/README.md | 1 - src.bkup/networking/client/player_input.rs | 50 -- src.bkup/networking/commands.rs | 411 ---------------- src.bkup/networking/frame_sync.rs | 332 ------------- .../frame_sync/dynamic_query_info.rs | 170 ------- src.bkup/networking/proto/player_input.rs | 12 - src.bkup/networking/serialization.rs | 74 --- src.bkup/networking/serialization/de.rs | 441 ------------------ src.bkup/networking/serialization/ser.rs | 169 ------- src.bkup/networking/server/player_input.rs | 35 -- src.bkup/scripting/ops/net_commands.rs | 161 ------- 11 files changed, 1856 deletions(-) delete mode 100644 src.bkup/README.md delete mode 100644 src.bkup/networking/client/player_input.rs delete mode 100644 src.bkup/networking/commands.rs delete mode 100644 src.bkup/networking/frame_sync.rs delete mode 100644 src.bkup/networking/frame_sync/dynamic_query_info.rs delete mode 100644 src.bkup/networking/proto/player_input.rs delete mode 100644 src.bkup/networking/serialization.rs delete mode 100644 src.bkup/networking/serialization/de.rs delete mode 100644 src.bkup/networking/serialization/ser.rs delete mode 100644 src.bkup/networking/server/player_input.rs delete mode 100644 src.bkup/scripting/ops/net_commands.rs diff --git a/src.bkup/README.md b/src.bkup/README.md deleted file mode 100644 index ecef0ff3de..0000000000 --- a/src.bkup/README.md +++ /dev/null @@ -1 +0,0 @@ -These are modules with code we might want later, but that aren't used in the game right now. \ No newline at end of file diff --git a/src.bkup/networking/client/player_input.rs b/src.bkup/networking/client/player_input.rs deleted file mode 100644 index 9773278f3b..0000000000 --- a/src.bkup/networking/client/player_input.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::{ - networking::proto::{ - player_input::{PlayerInputFromClient, PlayerInputFromServer}, - ClientMatchInfo, - }, - player::input::PlayerInputs, - prelude::*, -}; - -use super::NetClient; - -pub struct ClientPlayerInputPlugin; - -impl Plugin for ClientPlayerInputPlugin { - fn build(&self, app: &mut App) { - app.add_system_to_stage( - CoreStage::First, - recv_player_input_from_server.run_if_resource_exists::(), - ); - app.add_system_to_stage( - CoreStage::Last, - send_player_input_to_server - .run_if_resource_exists::() - .run_if_resource_exists::(), - ); - } -} - -fn recv_player_input_from_server( - mut client: ResMut, - mut player_inputs: ResMut, -) { - // FIXME: Unordered packets not handled correctly. We need a network tick. - while let Some(message) = client.recv_unreliable::() { - let player_input = &mut player_inputs.players[message.player_idx as usize]; - - player_input.control = message.control; - } -} - -fn send_player_input_to_server( - client: Res, - player_inputs: Res, - match_info: Res, -) { - let control = &player_inputs.players[match_info.player_idx].control; - client.send_unreliable(&PlayerInputFromClient { - control: control.clone(), - }); -} diff --git a/src.bkup/networking/commands.rs b/src.bkup/networking/commands.rs deleted file mode 100644 index 9a7d84bc52..0000000000 --- a/src.bkup/networking/commands.rs +++ /dev/null @@ -1,411 +0,0 @@ -#![allow(dead_code)] // TODO: Remove this when we use more stuff - -use std::marker::PhantomData; - -use bevy::{ - ecs::{ - entity::Entities, - system::{Command, EntityCommands, Resource, SystemParam}, - }, - reflect::TypeRegistryArc, -}; -use serde::{de::DeserializeSeed, Deserialize, Serialize}; - -use crate::{config::ENGINE_CONFIG, prelude::*, utils::ResetController}; - -use super::{ - client::NetClient, - serialization::{ - de::CompactReflectDeserializer, deserializer_from_bytes, get_type_name_cache, - ser::CompactReflectSerializer, serialize_to_bytes, TypeNameCache, - }, - server::NetServer, - NetId, NetIdMap, -}; - -pub struct NetCommandsPlugin; - -impl Plugin for NetCommandsPlugin { - fn build(&self, app: &mut App) { - app.init_resource::().add_system( - client_handle_net_commands - .run_if_resource_exists::() - .run_if_resource_exists::(), - ); - - if ENGINE_CONFIG.server_mode { - app.world.resource_scope(|world, server: Mut| { - let type_registry = world.resource::(); - let type_name_cache = get_type_name_cache(type_registry); - - server.broadcast_reliable(&type_name_cache); - - world.insert_resource(type_name_cache); - }); - } else { - app.add_system( - update_type_name_cache_from_server.run_if_resource_exists::(), - ); - } - } -} - -fn update_type_name_cache_from_server(mut client: ResMut, mut commands: Commands) { - while let Some(type_name_cache) = client.recv_reliable::() { - commands.insert_resource(type_name_cache); - } -} - -#[derive(Serialize, Deserialize, Clone)] -pub enum CommandMessage { - Spawn { - net_id: NetId, - }, - Insert { - net_id: NetId, - component_bytes: Vec, - type_name: String, - }, - InsertResource { - resource_bytes: Vec, - type_name: String, - }, - Despawn { - recursive: bool, - net_id: NetId, - }, - NextState(State), - /// This corresponds to the action implemented by the [`jumpy::utils::ResetController`]. - /// - /// Technically it's not a "Command", but it's similar enough that we put it in here. - ResetWorld, -} - -impl std::fmt::Debug for CommandMessage { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Spawn { net_id } => f.debug_struct("Spawn").field("net_id", net_id).finish(), - Self::Insert { - net_id, - component_bytes: _, - type_name, - } => f - .debug_struct("Insert") - .field("net_id", net_id) - .field("component_bytes", &"...") - .field("type_name", type_name) - .finish(), - Self::InsertResource { - resource_bytes: _, - type_name, - } => f - .debug_struct("InsertResource") - .field("resource_bytes", &"...") - .field("type_name", type_name) - .finish(), - Self::Despawn { recursive, net_id } => f - .debug_struct("Despawn") - .field("recursive", recursive) - .field("net_id", net_id) - .finish(), - Self::NextState(arg0) => f.debug_tuple("NextState").field(arg0).finish(), - Self::ResetWorld => write!(f, "ResetWorld"), - } - } -} - -#[derive(Debug, Clone, Copy, Deserialize, Serialize)] -pub enum State { - GameState(GameState), - InGameState(InGameState), -} - -impl From for State { - fn from(s: GameState) -> Self { - Self::GameState(s) - } -} -impl From for State { - fn from(s: InGameState) -> Self { - Self::InGameState(s) - } -} - -pub fn client_handle_net_commands( - entities: &Entities, - mut commands: Commands, - type_registry: Res, - mut client: Res, - mut net_ids: ResMut, - type_names: Res, - mut reset_controller: ResetController, -) { - while let Some(message) = client.recv_reliable::() { - trace!(command=?message, "Received CommandMessage from server"); - - match message { - CommandMessage::Spawn { net_id } => { - let entity = commands.spawn().insert(net_id).id(); - info!("Spawning entity"); - net_ids.insert(entity, net_id); - } - CommandMessage::Insert { - net_id, - component_bytes, - type_name, - } => { - let entity = net_ids.get_entity(net_id).expect("Entity not spawned"); - let type_registry = type_registry.read(); - let type_registration = type_registry - .get_with_name(&type_name) - .expect("Not registered in TypeRegistry"); - - let reflect_component = type_registration - .data::() - .expect("Doesn't have ReflectComponent") - .clone(); - let reflect_deserializer = - CompactReflectDeserializer::new(&type_registry, &type_names.0); - let component_data = reflect_deserializer - .deserialize(&mut deserializer_from_bytes(&component_bytes)) - .expect("Deserialize net component"); - - commands.add(InsertReflectComponent { - entity, - component_data, - reflect_component, - }); - } - CommandMessage::InsertResource { - resource_bytes, - type_name, - } => { - let type_registry = type_registry.read(); - let type_registration = type_registry - .get_with_name(&type_name) - .expect("Not registered in TypeRegistry"); - let reflect_resource = type_registration - .data::() - .expect("Doesn't have ReflectResource") - .clone(); - let reflect_deserializer = - CompactReflectDeserializer::new(&type_registry, &type_names.0); - let resource_data = reflect_deserializer - .deserialize(&mut deserializer_from_bytes(&resource_bytes)) - .expect("Deserialize component"); - - commands.add(InsertReflectResource { - reflect_resource, - resource_data, - }); - } - CommandMessage::NextState(s) => match s { - State::GameState(s) => commands.insert_resource(NextState(s)), - State::InGameState(s) => commands.insert_resource(NextState(s)), - }, - CommandMessage::Despawn { recursive, net_id } => { - if let Some(entity) = net_ids.remove_net_id(net_id) { - if entities.contains(entity) { - let mut cmds = commands.entity(entity); - if recursive { - cmds.despawn_recursive() - } else { - cmds.despawn() - } - } - } - } - CommandMessage::ResetWorld => { - reset_controller.reset_world(); - } - } - } -} - -struct InsertReflectComponent { - entity: Entity, - reflect_component: ReflectComponent, - component_data: Box, -} -impl Command for InsertReflectComponent { - fn write(self, world: &mut World) { - self.reflect_component.apply_or_insert( - world, - self.entity, - self.component_data.as_reflect(), - ); - } -} - -struct InsertReflectResource { - reflect_resource: ReflectResource, - resource_data: Box, -} -impl Command for InsertReflectResource { - fn write(self, world: &mut World) { - self.reflect_resource - .apply_or_insert(world, self.resource_data.as_reflect()); - } -} - -/// Similar to [`Commands`], but with network synchronization of the executed commands. -#[derive(SystemParam)] -pub struct NetCommands<'w, 's> { - commands: Commands<'w, 's>, - res: NetResources<'w, 's>, -} - -#[derive(SystemParam)] -pub struct NetResources<'w, 's> { - type_registry: Res<'w, TypeRegistryArc>, - net_ids: ResMut<'w, NetIdMap>, - server: Option>, - type_names: Option>, - #[system_param(ignore)] - _phantom: PhantomData<&'s ()>, -} - -impl<'w, 's> NetCommands<'w, 's> { - pub fn spawn<'a>(&'a mut self) -> NetEntityCommands<'w, 's, 'a> { - let mut entity_cmds = self.commands.spawn(); - - if let Some(server) = &mut self.res.server { - // Allocate a network identifier for the new entity - let net_id = NetId::new(); - // Add it to the queued network IDs - self.res.net_ids.insert(entity_cmds.id(), net_id); - - // Inser the network ID as a component on the entity - entity_cmds.insert(net_id); - - // Notify clients/server that an entity has been spawned - server.broadcast_reliable(&CommandMessage::Spawn { net_id }); - } - - NetEntityCommands { - entity_cmds, - res: &mut self.res, - } - } - - pub fn entity<'a>(&'a mut self, entity: Entity) -> NetEntityCommands<'w, 's, 'a> { - let entity_cmds = self.commands.entity(entity); - NetEntityCommands { - entity_cmds, - res: &mut self.res, - } - } - - pub fn next_state(&mut self, state: impl Into) -> &mut Self { - let state = state.into(); - - if let Some(server) = &mut self.res.server { - server.broadcast_reliable(&CommandMessage::NextState(state)); - } - - match state { - State::GameState(s) => self.commands.insert_resource(NextState(s)), - State::InGameState(s) => self.commands.insert_resource(NextState(s)), - } - - self - } - - pub fn insert_resource(&mut self, resource: impl Resource + Reflect) -> &mut Self { - if let Some(server) = &mut self.res.server { - // Serialize the component - let (resource_bytes, type_name) = { - let type_registry = self.res.type_registry.read(); - let type_registration = type_registry - .get(resource.type_id()) - .expect("Not registered in TypeRegistry"); - let serializer = CompactReflectSerializer::new( - resource.as_reflect(), - &type_registry, - &self.res.type_names.as_ref().unwrap().0, - ); - - let message = serialize_to_bytes(&serializer).expect("Serialize net message"); - - (message, type_registration.type_name()) - }; - - // Send the clients/server the inserted component - server.broadcast_reliable(&CommandMessage::InsertResource { - resource_bytes, - type_name: type_name.into(), - }); - } - - self.commands.insert_resource(resource); - - self - } -} - -pub struct NetEntityCommands<'w, 's, 'a> { - entity_cmds: EntityCommands<'w, 's, 'a>, - res: &'a mut NetResources<'w, 's>, -} - -impl<'w, 's, 'a> NetEntityCommands<'w, 's, 'a> { - pub fn id(&self) -> Entity { - self.entity_cmds.id() - } - pub fn insert(&mut self, c: C) -> &mut Self { - if let Some(server) = &mut self.res.server { - let entity = self.entity_cmds.id(); - - // Get the network ID - let net_id = self - .res - .net_ids - .get_net_id(entity) - .expect("Entity has no NetId"); - - // Serialize the component - let (component_bytes, type_name) = { - let type_registry = self.res.type_registry.read(); - let type_registration = type_registry.get(c.type_id()).unwrap_or_else(|| { - panic!( - "{} not registered in TypeRegistry", - std::any::type_name::() - ) - }); - let serializable = CompactReflectSerializer::new( - c.as_reflect(), - &type_registry, - &self.res.type_names.as_ref().unwrap().0, - ); - - let message = serialize_to_bytes(&serializable).expect("Serialize net message"); - - (message, type_registration.type_name()) - }; - - // Send the clients/server the inserted component - server.broadcast_reliable(&CommandMessage::Insert { - net_id, - component_bytes, - type_name: type_name.into(), - }); - } - - self.entity_cmds.insert(c); - - self - } - - pub fn despawn_recursive(self) { - if let Some(server) = &mut self.res.server { - if let Some(net_id) = self.res.net_ids.remove_entity(self.entity_cmds.id()) { - server.broadcast_reliable(&CommandMessage::Despawn { - recursive: true, - net_id, - }); - } - } - - self.entity_cmds.despawn_recursive(); - } -} diff --git a/src.bkup/networking/frame_sync.rs b/src.bkup/networking/frame_sync.rs deleted file mode 100644 index f7de0bacbc..0000000000 --- a/src.bkup/networking/frame_sync.rs +++ /dev/null @@ -1,332 +0,0 @@ -use bevy::{ - ecs::component::ComponentId, - reflect::{ReflectFromPtr, TypeRegistryArc, TypeRegistryInternal}, -}; -use bevy_ecs_dynamic::dynamic_query::{DynamicQuery, FetchKind, FetchResult}; -use serde::de::DeserializeSeed; - -use crate::prelude::*; - -use super::{ - client::NetClient, - serialization::{ - de::CompactReflectDeserializer, deserializer_from_bytes, ser::CompactReflectSerializer, - serialize_to_bytes, TypeNameCache, - }, - server::NetServer, - NetId, NetIdMap, -}; - -mod dynamic_query_info; -use self::dynamic_query_info::{DynamicQueryInfo, DynamicQueryInfoResources}; - -pub struct NetFrameSyncPlugin; - -impl Plugin for NetFrameSyncPlugin { - fn build(&self, app: &mut App) { - app.init_resource::() - .add_system_to_stage( - FixedUpdateStage::First, - client_get_sync_data.exclusive_system().at_start(), - ) - .add_system_to_stage( - FixedUpdateStage::First, - server_send_sync_data.exclusive_system().at_end(), - ); - } -} - -#[derive(Default)] -pub struct NetworkSyncConfig { - pub queries: Vec, -} - -pub struct NetworkSyncQuery { - pub query: DynamicQuery, - pub prune: bool, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct FrameSyncMessage { - pub queries: Vec, -} - -type Bytes = Vec; -type ComponentsBytes = Vec; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct FrameSyncQuery { - query_info: DynamicQueryInfo, - items: Vec, - prune: bool, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -struct FrameSyncQueryItem { - net_id: NetId, - components: ComponentsBytes, -} - -fn client_get_sync_data(world: &mut World) { - if !world.contains_resource::() { - return; - } - if !world.contains_resource::() { - return; - } - - world.resource_scope(|world, mut client: Mut| { - world.resource_scope(|world, net_ids: Mut| { - world.resource_scope(|world, type_registry: Mut| { - world.resource_scope(|world, type_names: Mut| { - let type_registry = type_registry.read(); - impl_client_get_sync_data( - world, - &mut client, - &net_ids, - &*type_registry, - &type_names, - ) - }); - }); - }); - }); -} - -fn impl_client_get_sync_data( - world: &mut World, - client: &mut NetClient, - net_ids: &NetIdMap, - type_registry: &TypeRegistryInternal, - type_names: &TypeNameCache, -) { - let mut message = None; - // We only care about the last message, so loop until we stop getting messages and store the - // latest one. - // - // FIXME: We currently send unordered packets, but assume that the latest one received is indeed the - // latest, when it could be older than a previously received packet. We need to keep a network tick - // so that we can tell which packet is the newest one we've seen. - while let Some(m) = client.recv_unreliable::() { - message = Some(m); - } - - // If we have a frame update - if let Some(message) = message { - for net_query in message.queries { - let mut query = net_query - .query_info - .with_all_fetches_mutable() - .get_query(DynamicQueryInfoResources { - world, - type_names, - type_registry, - }) - .expect("Invalid query"); - let reflect_tools = get_reflect_from_ptr(world, type_registry, &query); - - // Collect entities matching the query - let entities = query.iter_mut(world).map(|x| x.entity).collect::>(); - - // Collect entities that have a net ID - let mut net_entities = Vec::with_capacity(entities.len()); - for entity in entities { - if let Some(net_id) = net_ids.get_net_id(entity) { - net_entities.push((entity, net_id)); - - // Delete non-networked entities matching the query - } else if net_query.prune { - despawn_with_children_recursive(world, entity); - } - } - - // Sort entities by net ID - net_entities.sort_unstable_by_key(|x| x.1); - - let mut net_items_iter = net_query.items.into_iter(); - 'entities: for (entity, net_id) in net_entities { - // Get the components bytes for the matching networked entity - let components_bytes = loop { - if let Some(item) = net_items_iter.next() { - if item.net_id == net_id { - break item.components; - } - } else { - break 'entities; - } - }; - - // Collect the pointers for the components of the entity - let components_target_pointers = query - .get_mut(world, entity) - .expect("Query entity") - .into_iter() - .map(|x| { - if let FetchResult::RefMut { value, .. } = x { - value - } else { - unreachable!("All fetches should have been mutable") - } - }); - - // Loop through the components and update them from the data from the network - for ((target_pointer, component_bytes), reflect_from_ptr) in - components_target_pointers - .zip(components_bytes) - .zip(&reflect_tools) - { - let target_reflect = - unsafe { reflect_from_ptr.as_reflect_ptr_mut(target_pointer) }; - - let deserializer = - CompactReflectDeserializer::new(type_registry, &type_names.0); - - let component_data = deserializer - .deserialize(&mut deserializer_from_bytes(&component_bytes)) - .expect("Deserialize net component"); - - target_reflect.apply(component_data.as_ref()); - } - } - } - } -} - -fn server_send_sync_data(world: &mut World) { - if !world.contains_resource::() { - return; - } - if !world.contains_resource::() { - return; - } - - world.resource_scope(|world, mut server: Mut| { - world.resource_scope(|world, mut queries: Mut| { - world.resource_scope(|world, net_ids: Mut| { - world.resource_scope(|world, type_registry: Mut| { - world.resource_scope(|world, type_names: Mut| { - let type_registry = type_registry.read(); - impl_server_send_sync_data( - world, - &mut server, - &mut queries, - &net_ids, - &*type_registry, - &type_names, - ); - }); - }); - }); - }); - }); -} - -fn impl_server_send_sync_data( - world: &mut World, - server: &mut NetServer, - network_sync: &mut NetworkSyncConfig, - net_ids: &NetIdMap, - type_registry: &TypeRegistryInternal, - type_names: &TypeNameCache, -) { - let mut frame_sync_queries = Vec::with_capacity(network_sync.queries.len()); - - // Iterate over queries that need to be synced - for net_query in network_sync.queries.iter_mut() { - let query = &mut net_query.query; - let query_info = DynamicQueryInfo::from_query( - query, - DynamicQueryInfoResources { - world, - type_names, - type_registry, - }, - ); - - // Get the ReflectFromPtr and ReflectSerialize for each component type in the query - let reflect_tools = get_reflect_from_ptr(world, type_registry, query); - - // Loop over all entities matching the query - let mut serialized_items = Vec::new(); - for item in query.iter_mut(world) { - let Some(net_id) = net_ids.get_net_id(item.entity) else { - warn!("Skipping sync of entity without known NetId"); - continue; - }; - - let mut components_bytes = Vec::with_capacity(item.items.len()); - for (fetch_result, reflect_from_ptr) in item.items.into_iter().zip(reflect_tools.iter()) - { - let ptr = if let FetchResult::Ref(ptr) = fetch_result { - ptr - } else { - panic!("Only read-only query supported for network sync"); - }; - - let reflect = unsafe { reflect_from_ptr.as_reflect_ptr(ptr) }; - let serializable = - CompactReflectSerializer::new(reflect, type_registry, &type_names.0); - let bytes = serialize_to_bytes(&serializable).expect("Serialize component"); - components_bytes.push(bytes); - } - serialized_items.push(FrameSyncQueryItem { - net_id, - components: components_bytes, - }); - } - - // Sort items by net_id - serialized_items.sort_unstable_by_key(|x| x.net_id); - - frame_sync_queries.push(FrameSyncQuery { - query_info, - items: serialized_items, - prune: net_query.prune, - }); - } - - let message = FrameSyncMessage { - queries: frame_sync_queries, - }; - - server.broadcast_unreliable(&message); -} - -fn get_reflect_from_ptr<'a, 'b>( - world: &'b World, - type_registry: &'a TypeRegistryInternal, - query: &'b DynamicQuery, -) -> Vec<&'a ReflectFromPtr> { - query - .fetches() - .iter() - .map(|fetch_kind| fetch_kind.component_id()) - .map(|component_id| { - world - .components() - .get_info(component_id) - .unwrap() - .type_id() - .unwrap() - }) - .map(|type_id| { - let type_registration = type_registry.get(type_id).expect("Type not registered"); - let reflect_from_ptr = type_registration - .data::() - .expect("Missing ReflectFromPtr"); - reflect_from_ptr - }) - .collect::>() -} - -trait FetchKindExt { - fn component_id(&self) -> ComponentId; -} - -impl FetchKindExt for FetchKind { - fn component_id(&self) -> ComponentId { - match self { - FetchKind::Ref(id) | FetchKind::RefMut(id) => *id, - } - } -} diff --git a/src.bkup/networking/frame_sync/dynamic_query_info.rs b/src.bkup/networking/frame_sync/dynamic_query_info.rs deleted file mode 100644 index adbfae3d9f..0000000000 --- a/src.bkup/networking/frame_sync/dynamic_query_info.rs +++ /dev/null @@ -1,170 +0,0 @@ -use bevy::{ecs::component::ComponentId, prelude::World, reflect::TypeRegistryInternal}; -use bevy_ecs_dynamic::dynamic_query::{DynamicQuery, FetchKind, FilterKind, QueryError}; - -use crate::{networking::serialization::TypeNameCache, prelude::*}; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct DynamicQueryInfo { - fetches: Vec, - filters: Vec, -} - -/// References to the types needed to convert and construct [`DynamicQueryInfo`]. -#[derive(Copy, Clone)] -pub struct DynamicQueryInfoResources<'a> { - pub world: &'a World, - pub type_names: &'a TypeNameCache, - pub type_registry: &'a TypeRegistryInternal, -} - -impl DynamicQueryInfo { - pub fn from_query(query: &DynamicQuery, info: DynamicQueryInfoResources) -> Self { - let fetches = query - .fetches() - .iter() - .cloned() - .map(|x| FetchKindInfo::from_fetch_kind(x, info)) - .collect(); - let filters = query - .filters() - .iter() - .cloned() - .map(|x| FilterKindInfo::from_filter_kind(x, info)) - .collect(); - Self { fetches, filters } - } - - pub fn with_all_fetches_mutable(mut self) -> Self { - for fetch in &mut self.fetches { - *fetch = FetchKindInfo::RefMut(match fetch { - FetchKindInfo::Ref(id) | FetchKindInfo::RefMut(id) => *id, - }); - } - self - } - - pub fn get_query( - self: DynamicQueryInfo, - info: DynamicQueryInfoResources, - ) -> Result { - let fetches = self - .fetches - .into_iter() - .map(|x| x.get_fetch_kind(info)) - .collect(); - let filters = self - .filters - .into_iter() - .map(|x| x.get_filter_kind(info)) - .collect(); - DynamicQuery::new(info.world, fetches, filters) - } -} - -/// The index into the type name cache for this component -#[derive(Copy, Clone, Debug, Serialize, Deserialize)] -struct ComponentTypeNameIdx(pub u32); - -impl ComponentTypeNameIdx { - fn get_component_id(&self, info: DynamicQueryInfoResources) -> ComponentId { - let type_registry = info.type_registry; - - let type_name = info - .type_names - .0 - .get_str(self.0) - .expect("Missing type name in cache"); - let type_id = type_registry - .get_with_name(type_name) - .expect("Type not registered") - .type_id(); - - // FIXME(scripting): This can't support custom components created by scripts, because we - // assume the component ID can be directly tied to the type ID that we are syncing. - // We need to fix that and find a way to map component Ids on the server to component ids on the client - info.world - .components() - .get_id(type_id) - .expect("Component not found") - } - - fn from_component_id(id: ComponentId, info: DynamicQueryInfoResources) -> Self { - let world = info.world; - let type_names = info.type_names; - let type_registry = info.type_registry; - - let type_id = world - .components() - .get_info(id) - .expect("Component ID not found") - .type_id() - .expect("Component without Type ID"); - let type_name = type_registry - .get(type_id) - .expect("Type not registered") - .type_name(); - - Self( - type_names - .0 - .get_idx(type_name) - .expect("Missing type name in cache"), - ) - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -enum FetchKindInfo { - Ref(ComponentTypeNameIdx), - RefMut(ComponentTypeNameIdx), -} - -impl FetchKindInfo { - fn get_fetch_kind(&self, info: DynamicQueryInfoResources) -> FetchKind { - match self { - FetchKindInfo::Ref(id) => FetchKind::Ref(id.get_component_id(info)), - FetchKindInfo::RefMut(id) => FetchKind::RefMut(id.get_component_id(info)), - } - } - - fn from_fetch_kind(f: FetchKind, info: DynamicQueryInfoResources) -> Self { - match f { - FetchKind::Ref(id) => Self::Ref(ComponentTypeNameIdx::from_component_id(id, info)), - FetchKind::RefMut(id) => { - Self::RefMut(ComponentTypeNameIdx::from_component_id(id, info)) - } - } - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -enum FilterKindInfo { - With(ComponentTypeNameIdx), - Without(ComponentTypeNameIdx), - Changed(ComponentTypeNameIdx), - Added(ComponentTypeNameIdx), -} - -impl FilterKindInfo { - fn get_filter_kind(&self, info: DynamicQueryInfoResources) -> FilterKind { - match self { - FilterKindInfo::With(id) => FilterKind::With(id.get_component_id(info)), - FilterKindInfo::Without(id) => FilterKind::Without(id.get_component_id(info)), - FilterKindInfo::Changed(id) => FilterKind::Changed(id.get_component_id(info)), - FilterKindInfo::Added(id) => FilterKind::Added(id.get_component_id(info)), - } - } - - fn from_filter_kind(f: FilterKind, info: DynamicQueryInfoResources) -> Self { - match f { - FilterKind::With(id) => Self::With(ComponentTypeNameIdx::from_component_id(id, info)), - FilterKind::Without(id) => { - Self::Without(ComponentTypeNameIdx::from_component_id(id, info)) - } - FilterKind::Changed(id) => { - Self::Changed(ComponentTypeNameIdx::from_component_id(id, info)) - } - FilterKind::Added(id) => Self::Added(ComponentTypeNameIdx::from_component_id(id, info)), - } - } -} diff --git a/src.bkup/networking/proto/player_input.rs b/src.bkup/networking/proto/player_input.rs deleted file mode 100644 index fbfd2ee778..0000000000 --- a/src.bkup/networking/proto/player_input.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::{player::input::PlayerControl, prelude::*}; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PlayerInputFromClient { - pub control: PlayerControl, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PlayerInputFromServer { - pub player_idx: u32, - pub control: PlayerControl, -} diff --git a/src.bkup/networking/serialization.rs b/src.bkup/networking/serialization.rs deleted file mode 100644 index 06783bd7ec..0000000000 --- a/src.bkup/networking/serialization.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::prelude::*; - -use bevy::{reflect::TypeRegistry, utils::HashMap}; - -pub mod de; -pub mod ser; - -pub struct SerializationPlugin; - -impl Plugin for SerializationPlugin { - fn build(&self, app: &mut App) { - // This type isn't registered - app.register_type::(); - } -} - -pub fn serialize_to_bytes(value: &T) -> anyhow::Result> -where - T: Serialize + ?Sized, -{ - Ok(postcard::to_allocvec(value)?) -} - -pub fn deserialize_from_bytes<'a, T>(bytes: &'a [u8]) -> anyhow::Result -where - T: Deserialize<'a>, -{ - Ok(postcard::from_bytes(bytes)?) -} - -pub fn deserializer_from_bytes( - bytes: &[u8], -) -> postcard::Deserializer { - postcard::Deserializer::from_bytes(bytes) -} - -#[derive(Default, Serialize, Deserialize)] -pub struct TypeNameCache(pub StringCache); - -/// String cache that can be used to map strings to indices in order to save space. -#[derive(Debug, Clone, Reflect, Default, Serialize, Deserialize)] -#[reflect(Default)] -pub struct StringCache { - strings: Vec, - indexes: HashMap, -} - -impl StringCache { - pub fn insert(&mut self, s: &str) { - let idx = self.strings.len(); - self.strings.push(s.into()); - self.indexes - .insert(s.into(), idx.try_into().expect("Too many strings in cache")); - } - - pub fn get_idx(&self, str: &str) -> Option { - self.indexes.get(str).copied() - } - - pub fn get_str(&self, idx: u32) -> Option<&str> { - self.strings.get(idx as usize).map(|x| x.as_str()) - } -} - -pub fn get_type_name_cache(type_registry: &TypeRegistry) -> TypeNameCache { - let mut cache = StringCache::default(); - - let type_registry = type_registry.read(); - for registration in type_registry.iter() { - cache.insert(registration.type_name()); - } - - TypeNameCache(cache) -} diff --git a/src.bkup/networking/serialization/de.rs b/src.bkup/networking/serialization/de.rs deleted file mode 100644 index caac9b0b72..0000000000 --- a/src.bkup/networking/serialization/de.rs +++ /dev/null @@ -1,441 +0,0 @@ -use std::any::TypeId; - -use bevy::reflect::{ - ArrayInfo, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, DynamicTupleStruct, ListInfo, - Map, MapInfo, StructInfo, TupleInfo, TupleStructInfo, TypeInfo, TypeRegistration, - TypeRegistryInternal, -}; -use serde::de::{DeserializeSeed, Error, Visitor}; - -use super::StringCache; -use crate::prelude::*; - -macro_rules! custom_err { - ($($arg:expr),* $(,)?) => { - Error::custom(format_args!($($arg),*)) - }; -} - -pub struct CompactReflectDeserializer<'a>(DeserializerInner<'a>); - -impl<'a> CompactReflectDeserializer<'a> { - pub fn new(registry: &'a TypeRegistryInternal, type_names: &'a StringCache) -> Self { - Self(DeserializerInner { - registry, - type_names, - }) - } -} - -#[derive(Clone, Copy)] -struct DeserializerInner<'a> { - registry: &'a TypeRegistryInternal, - type_names: &'a StringCache, -} - -impl<'a> DeserializerInner<'a> { - fn get_registration_from_idx(&self, type_idx: u32) -> Result<&TypeRegistration, E> { - let type_name = self - .type_names - .get_str(type_idx) - .ok_or_else(|| custom_err!("Type name not in name cache"))?; - - self.registry - .get_with_name(type_name) - .ok_or_else(|| custom_err!("Type not in type registry")) - } - - fn get_registration_from_type_id( - &self, - type_id: TypeId, - type_name: &str, - ) -> Result<&TypeRegistration, E> { - self.registry - .get(type_id) - .ok_or_else(|| custom_err!("Type not in type registry: {}", type_name)) - } -} - -impl<'a, 'de> DeserializeSeed<'de> for CompactReflectDeserializer<'a> { - type Value = Box; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_tuple(2, OuterTypeVisitor(self.0)) - } -} - -struct OuterTypeVisitor<'a>(DeserializerInner<'a>); - -impl<'a, 'de> Visitor<'de> for OuterTypeVisitor<'a> { - type Value = Box; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple like (type_idx_in_str_cache, type_data)") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - let type_idx = seq - .next_element::()? - .ok_or_else(|| custom_err!("Missing type idx in top-level type"))?; - let registration = self.0.get_registration_from_idx(type_idx)?; - - let reflect = seq - .next_element_seed(ReflectValueDeserializer { - inner: self.0, - registration, - })? - .ok_or_else(|| custom_err!("Missing type idx in top-level type"))?; - - Ok(reflect) - } -} - -#[derive(Copy, Clone)] -struct ReflectValueDeserializer<'a> { - inner: DeserializerInner<'a>, - registration: &'a TypeRegistration, -} - -impl<'a, 'de> DeserializeSeed<'de> for ReflectValueDeserializer<'a> { - type Value = Box; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - // Handle both Value case and types that have a custom `ReflectDeserialize` - if let Some(deserialize_reflect) = self.registration.data::() { - let value = deserialize_reflect.deserialize(deserializer)?; - return Ok(value); - } - - match self.registration.type_info() { - TypeInfo::Struct(info) => { - let len = info.field_len(); - let mut dynamic_struct = deserializer.deserialize_tuple( - len, - StructVisitor { - inner: self.inner, - info, - }, - )?; - dynamic_struct.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_struct)) - } - TypeInfo::TupleStruct(info) => { - let len = info.field_len(); - let mut dynamic_tuple_struct = deserializer.deserialize_tuple( - len, - TupleStructVisitor { - inner: self.inner, - info, - }, - )?; - dynamic_tuple_struct.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_tuple_struct)) - } - TypeInfo::Tuple(info) => { - let len = info.field_len(); - let mut dynamic_tuple = deserializer.deserialize_tuple( - len, - TupleVisitor { - inner: self.inner, - info, - }, - )?; - dynamic_tuple.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_tuple)) - } - TypeInfo::List(info) => { - let mut dynamic_list = deserializer.deserialize_seq(ListVisitor { - inner: self.inner, - info, - })?; - dynamic_list.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_list)) - } - TypeInfo::Array(info) => { - let mut dynamic_list = deserializer.deserialize_seq(ArrayVisitor { - inner: self.inner, - info, - })?; - dynamic_list.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_list)) - } - TypeInfo::Map(info) => { - let mut dynamic_map = deserializer.deserialize_map(MapVisitor { - inner: self.inner, - info, - })?; - dynamic_map.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_map)) - } - TypeInfo::Value(_) => { - // This case should already be handled - Err(custom_err!( - "the TypeRegistration for {} doesn't have ReflectDeserialize", - self.registration.type_name() - )) - } - TypeInfo::Dynamic(_) => { - // We could potentially allow this but we'd have no idea what the actual types of the - // fields are and would rely on the deserializer to determine them (e.g. `i32` vs `i64`) - Err(custom_err!( - "cannot deserialize arbitrary dynamic type yet: {}", - self.registration.type_name() - )) - } - } - } -} - -struct StructVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a StructInfo, -} - -impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { - type Value = DynamicStruct; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with struct fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting struct {}", self.info.type_name()); - let mut index = 0usize; - let mut output = DynamicStruct::default(); - - while let Some(value) = seq.next_element_seed({ - let field = self.info.field_at(index).unwrap(); - let type_id = field.type_id(); - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, field.type_name())?, - } - })? { - let name = self.info.field_at(index).unwrap().name(); - trace!("Visiting field {}", name); - output.insert_boxed(name, value); - index += 1; - if index >= self.info.field_len() { - break; - } - } - - Ok(output) - } -} - -struct TupleStructVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a TupleStructInfo, -} - -impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { - type Value = DynamicTupleStruct; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple struct fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting tuple struct {}", self.info.type_name()); - let mut index = 0usize; - let mut output = DynamicTupleStruct::default(); - - while let Some(value) = seq.next_element_seed({ - let field = self.info.field_at(index).unwrap(); - let type_id = field.type_id(); - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, field.type_name())?, - } - })? { - output.insert_boxed(value); - index += 1; - if index >= self.info.field_len() { - break; - } - } - - Ok(output) - } -} - -struct TupleVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a TupleInfo, -} - -impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { - type Value = DynamicTuple; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting tuple {}", self.info.type_name()); - let mut index = 0usize; - let mut output = DynamicTuple::default(); - - while let Some(value) = seq.next_element_seed({ - let field = self.info.field_at(index).unwrap(); - let type_id = field.type_id(); - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, field.type_name())?, - } - })? { - output.insert_boxed(value); - index += 1; - if index >= self.info.field_len() { - break; - } - } - - Ok(output) - } -} - -struct ListVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a ListInfo, -} - -impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { - type Value = DynamicList; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple list fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting list {}", self.info.type_name()); - let mut output = DynamicList::default(); - - let type_id = self.info.item_type_id(); - - while let Some(value) = seq.next_element_seed({ - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, self.info.item_type_name())?, - } - })? { - output.push_box(value); - } - - Ok(output) - } -} - -struct ArrayVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a ArrayInfo, -} - -impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { - type Value = DynamicList; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple list fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting array {}", self.info.type_name()); - let mut output = DynamicList::default(); - - let type_id = self.info.item_type_id(); - - while let Some(value) = seq.next_element_seed({ - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, self.info.item_type_name())?, - } - })? { - output.push_box(value); - } - - Ok(output) - } -} - -struct MapVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a MapInfo, -} - -impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { - type Value = DynamicMap; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("map") - } - - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - trace!("Visiting map {}", self.info.type_name()); - let mut output = DynamicMap::default(); - - let key_registration = self - .inner - .get_registration_from_type_id(self.info.key_type_id(), self.info.key_type_name())?; - let value_registration = self.inner.get_registration_from_type_id( - self.info.value_type_id(), - self.info.value_type_name(), - )?; - - while let Some(key) = map.next_key_seed(ReflectValueDeserializer { - inner: self.inner, - registration: key_registration, - })? { - let value = map.next_value_seed(ReflectValueDeserializer { - registration: value_registration, - inner: self.inner, - })?; - output.insert_boxed(key, value); - } - - Ok(output) - } -} diff --git a/src.bkup/networking/serialization/ser.rs b/src.bkup/networking/serialization/ser.rs deleted file mode 100644 index 0dbab2f0c9..0000000000 --- a/src.bkup/networking/serialization/ser.rs +++ /dev/null @@ -1,169 +0,0 @@ -use bevy::reflect::{serde::Serializable, ReflectRef, TypeRegistryInternal}; -use serde::ser::{Error, SerializeMap, SerializeSeq, SerializeTuple}; - -use super::StringCache; -use crate::prelude::*; - -pub struct CompactReflectSerializer<'a>(SerializerInner<'a>); - -#[derive(Clone, Copy)] -struct SerializerInner<'a> { - value: &'a dyn Reflect, - registry: &'a TypeRegistryInternal, - type_names: &'a StringCache, -} - -impl<'a> SerializerInner<'a> { - fn serializable(&self) -> Result { - let reflect_serialize = self - .registry - .get_type_data::(self.value.type_id()) - .ok_or_else(|| { - serde::ser::Error::custom(format_args!( - "Type '{}' did not register ReflectSerialize", - self.value.type_name() - )) - })?; - Ok(reflect_serialize.get_serializable(self.value)) - } - - fn for_value<'b>(&self, value: &'a dyn Reflect) -> SerializerInner<'b> - where - 'a: 'b, - { - let mut s = *self; - s.value = value; - s - } -} - -impl<'a> CompactReflectSerializer<'a> { - pub fn new( - value: &'a dyn Reflect, - registry: &'a TypeRegistryInternal, - type_name_cache: &'a StringCache, - ) -> Self { - CompactReflectSerializer(SerializerInner { - value, - registry, - type_names: type_name_cache, - }) - } - - fn value_serializer(&self) -> ValueSerializer { - ValueSerializer(self.0) - } -} - -impl<'a> Serialize for CompactReflectSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut tup = serializer.serialize_tuple(2)?; - - let type_name = self.0.value.type_name(); - let type_idx = self.0.type_names.get_idx(type_name).ok_or_else(|| { - Error::custom(format_args!("Type name not in string cache: {}", type_name)) - })?; - tup.serialize_element(&type_idx)?; - tup.serialize_element(&self.value_serializer())?; - - tup.end() - } -} - -struct ValueSerializer<'a>(SerializerInner<'a>); - -impl<'a> Serialize for ValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let serializable = self.0.serializable::(); - if let Ok(serializable) = serializable { - return serializable.borrow().serialize(serializer); - } - - trace!("Serializing {}", self.0.value.type_name()); - - match self.0.value.reflect_ref() { - ReflectRef::Struct(s) => { - let len = s.field_len(); - let mut tup = serializer.serialize_tuple(len)?; - for (i, field) in s.iter_fields().enumerate() { - trace!("Serializing field named `{:?}`", s.name_at(i).unwrap()); - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - tup.serialize_element(&field_serializer)?; - } - tup.end() - } - ReflectRef::TupleStruct(s) => { - let len = s.field_len(); - let mut tup = serializer.serialize_tuple(len)?; - for field in s.iter_fields() { - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - tup.serialize_element(&field_serializer)?; - } - tup.end() - } - ReflectRef::Tuple(t) => { - let len = t.field_len(); - let mut tup = serializer.serialize_tuple(len)?; - for field in t.iter_fields() { - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - tup.serialize_element(&field_serializer)?; - } - tup.end() - } - ReflectRef::List(l) => { - let len = l.len(); - let mut seq = serializer.serialize_seq(Some(len))?; - for field in l.iter() { - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - seq.serialize_element(&field_serializer)?; - } - seq.end() - } - ReflectRef::Array(a) => { - let len = a.len(); - let mut seq = serializer.serialize_seq(Some(len))?; - for field in a.iter() { - let field_serializer = ValueSerializer(self.0.for_value(field)); - - seq.serialize_element(&field_serializer)?; - } - seq.end() - } - ReflectRef::Map(m) => { - let len = m.len(); - let mut map = serializer.serialize_map(Some(len))?; - for (key, value) in m.iter() { - map.serialize_entry( - &ValueSerializer(self.0.for_value(key)), - &ValueSerializer(self.0.for_value(value)), - )?; - } - - map.end() - } - ReflectRef::Value(_) => Err(serializable.err().unwrap()), - } - } -} diff --git a/src.bkup/networking/server/player_input.rs b/src.bkup/networking/server/player_input.rs deleted file mode 100644 index 86042c7353..0000000000 --- a/src.bkup/networking/server/player_input.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::{ - networking::proto::player_input::{PlayerInputFromClient, PlayerInputFromServer}, - player::input::PlayerInputs, - prelude::*, -}; - -use super::NetServer; - -pub struct ServerPlayerInputPlugin; - -impl Plugin for ServerPlayerInputPlugin { - fn build(&self, app: &mut App) { - app.add_system_to_stage(CoreStage::First, recv_player_input); - } -} - -fn recv_player_input(mut server: ResMut, mut player_inputs: ResMut) { - // FIXME: We are not ordering packets, so we may apply a stale user input, which is not good. We - // need to track a network tick to know what the latest input really is. - while let Some(incomming) = server.recv_unreliable::() { - let input = &mut player_inputs.players[incomming.client_idx]; - - input.control = incomming.message.control.clone(); - - // FIXME: We may receive multiple updates for each user, so we may send multiple updates to - // the client, but we don't want to do that, we should just send one update per changed client. - server.send_unreliable_to( - &PlayerInputFromServer { - player_idx: incomming.client_idx.try_into().unwrap(), - control: incomming.message.control, - }, - super::MessageTarget::AllExcept(incomming.client_idx), - ) - } -} diff --git a/src.bkup/scripting/ops/net_commands.rs b/src.bkup/scripting/ops/net_commands.rs deleted file mode 100644 index c4c2a76f2c..0000000000 --- a/src.bkup/scripting/ops/net_commands.rs +++ /dev/null @@ -1,161 +0,0 @@ -use anyhow::{format_err, Context}; -use bevy::ecs::system::SystemState; -use bevy::prelude::{default, ReflectComponent}; -use bevy::reflect::TypeRegistryArc; - -use bevy_mod_js_scripting::{serde_json, JsRuntimeOp, JsValueRef, JsValueRefs, OpContext}; - -use crate::networking::serialization::TypeNameCache; -use crate::networking::server::NetServer; -use crate::{ - networking::{ - commands::CommandMessage, - serialization::{ser::CompactReflectSerializer, serialize_to_bytes}, - NetIdMap, - }, - prelude::*, -}; - -pub struct NetCommandsSpawn; -impl JsRuntimeOp for NetCommandsSpawn { - fn js(&self) -> Option<&'static str> { - Some( - r#" - if (!globalThis.NetCommands) { - globalThis.NetCommands = {} - } - - globalThis.NetCommands.spawn = () => { - return Value.wrapValueRef( - bevyModJsScriptingOpSync("jumpy_net_commands_spawn") - ); - } - "#, - ) - } - - fn run( - &self, - context: OpContext<'_>, - world: &mut bevy::prelude::World, - args: serde_json::Value, - ) -> anyhow::Result { - // Expect empty arguments - let _: [(); 0] = serde_json::from_value(args).context("parse args")?; - - let value_refs = context - .op_state - .entry::() - .or_insert_with(default); - - let mut net_commands_state = SystemState::::new(world); - let entity = { - let mut net_commands = net_commands_state.get_mut(world); - net_commands.spawn().id() - }; - - net_commands_state.apply(world); - - let value_ref = JsValueRef::new_free(Box::new(entity), value_refs); - - Ok(serde_json::to_value(value_ref)?) - } -} - -pub struct NetCommandsInsert; -impl JsRuntimeOp for NetCommandsInsert { - fn js(&self) -> Option<&'static str> { - Some( - r#" - if (!globalThis.NetCommands) { - globalThis.NetCommands = {} - } - - globalThis.NetCommands.insert = (entity, component) => { - bevyModJsScriptingOpSync( - "jumpy_net_commands_insert", - Value.unwrapValueRef(entity), - Value.unwrapValueRef(component) - ); - } - "#, - ) - } - - fn run( - &self, - context: OpContext<'_>, - world: &mut bevy::prelude::World, - args: serde_json::Value, - ) -> anyhow::Result { - // Parse args - let (entity_value_ref, component_value_ref): (JsValueRef, JsValueRef) = - serde_json::from_value(args).context("parse args")?; - - let mut server = world.remove_resource::(); - - let value_refs = context - .op_state - .entry::() - .or_insert_with(default); - - // Get entity and make sure the entity exists - let entity = entity_value_ref.get_entity(world, value_refs)?; - world - .get_entity(entity) - .ok_or_else(|| format_err!("Entity does not exist"))?; - - let component_value_ref = value_refs - .get(component_value_ref.key) - .ok_or_else(|| format_err!("Value ref doesn't exist"))? - .clone(); - - // Load the type registry - let type_registry = world.resource::(); - let type_names = world.resource::(); - let net_ids = world.resource::(); - let type_registry = type_registry.read(); - - // Clone the reflect value of the component - let reflect_value_ref = component_value_ref.get(world)?; - let type_id = reflect_value_ref.type_id(); - let reflect_value = reflect_value_ref.clone_value(); - - // Get the ReflectComponent - let type_registration = type_registry.get(type_id).expect("Type not registered"); - let reflect_component = type_registration - .data::() - .ok_or_else(|| format_err!("ReflectComponent not found for component value ref"))? - .clone(); - - if let Some(server) = &mut server { - let net_id = net_ids.get_net_id(entity).expect("Entity has no NetId"); - let serializable = CompactReflectSerializer::new( - reflect_value_ref.as_reflect(), - &type_registry, - &type_names.0, - ); - let component_bytes = serialize_to_bytes(&serializable).expect("Serialize component"); - - // Send component insertion message over the network - let type_name = type_registration.type_name(); - server.broadcast_reliable(&CommandMessage::Insert { - net_id, - component_bytes, - type_name: type_name.into(), - }); - } - - // Drop our immutable borrow of the world - drop(type_registry); - drop(reflect_value_ref); - - reflect_component.apply_or_insert(world, entity, reflect_value.as_reflect()); - - if let Some(server) = server { - world.insert_resource(server); - } - - Ok(serde_json::Value::Null) - } -}