@@ -7,6 +7,7 @@ import { VECTOR3_ZERO } from "@minecraft/math";
77
88enum States {
99 NORMAL ,
10+ WEAK ,
1011 FLYING ,
1112 MOON_JUMP ,
1213 DASH
@@ -119,17 +120,19 @@ Object.defineProperties(Player.prototype, {
119120 }
120121} ) ;
121122
123+ function playerHasLight ( player : Player ) {
124+ const container = player . getComponent ( EntityInventoryComponent . componentId ) ?. container
125+ return container ?. contains ( light )
126+ }
127+
122128// Eat fruit component
123129export function startup ( ev : StartupEvent ) {
124130 ev . itemComponentRegistry . registerCustomComponent ( "whynot:light_fruit" , {
125131 onConsume ( { source} ) {
126132 const player = source as Player
127133 if ( ! player || player . typeId != "minecraft:player" || ! player . isValid ) return
128134 system . run ( ( ) => {
129- const container = player . getComponent ( EntityInventoryComponent . componentId ) ?. container
130- if ( ! container ) return
131-
132- if ( container . contains ( light ) ) return
135+ if ( playerHasLight ( player ) ) return
133136
134137 player . addItem ( light ) ;
135138 } )
@@ -189,8 +192,12 @@ function changeState(player: Player, state: States) {
189192 changeState ( player , States . NORMAL )
190193 break ;
191194
195+ case States . WEAK :
196+ break ;
197+
192198 }
193199
200+ if ( oldState == player . state ) return
194201 switch ( oldState ) {
195202 case States . FLYING :
196203 player . triggerEvent ( "whynot:remove_static_player" ) ;
@@ -199,91 +206,22 @@ function changeState(player: Player, state: States) {
199206
200207 player . removeEffect ( MinecraftEffectTypes . Invisibility )
201208 break ;
202- }
203- }
204- export function main ( ) {
205- light = new ItemStack ( "whynot:light" , 1 ) ;
206- light . lockMode = ItemLockMode . inventory ;
207- light . keepOnDeath = true ;
208-
209- world . getAllPlayers ( ) . forEach ( player => changeState ( player , States . NORMAL ) )
210- world . beforeEvents . entityHurt . subscribe ( ev => {
211- if ( ev . damageSource . cause != EntityDamageCause . fall ) return
212-
213- const player = ev . hurtEntity as Player
214- if ( ! player . isValid || player . typeId != "minecraft:player" ) return
215- if ( ! player . ignoreFall ) return
216-
217- ev . cancel = true
218- } )
219- world . afterEvents . playerButtonInput . subscribe ( ( { button, newButtonState, player} ) => {
220- const pressed = newButtonState == ButtonState . Pressed
221- if ( ! entityHasSlotTag ( player , EquipmentSlot . Mainhand , "whynot:light" ) ) return ;
222-
223- if ( button == InputButton . Sneak && newButtonState == ButtonState . Pressed &&
224- player . state == States . NORMAL && player . dashCooldown <= 0 ) {
225- changeState ( player , States . DASH )
226- }
227- if ( button != InputButton . Jump ) return
228- if ( player . airTime >= airborneAirtime && pressed && player . state == States . NORMAL ) {
229- // Activate fly
230- if ( player . fCooldown <= 0 && player . isSneaking ) {
231- changeState ( player , States . FLYING )
232- }
233- // Moon jump
234- else if ( player . airJumps > 0 ) {
235- changeState ( player , States . MOON_JUMP )
236- }
237- }
238- // Deactivate fly
239- if ( ! pressed && player . state == States . FLYING ) {
240- changeState ( player , States . NORMAL )
241- }
242- } )
243- world . afterEvents . playerHotbarSelectedSlotChange . subscribe ( ( { itemStack, player} ) => {
244- if ( itemStack ?. hasTag ( "whynot:light" ) ) return
245- changeState ( player , States . NORMAL )
246- } )
247209
248- system . runInterval ( mainTick )
210+ case States . WEAK :
211+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , true )
212+ break ;
213+ }
249214}
250215
251- function mainTick ( ) {
252- world . getAllPlayers ( ) . forEach ( player => {
253- // Set Airtime
254- if ( player . isOnGround ) {
255- if ( player . state != States . FLYING ) {
256- player . airJumps = maxAirJumps
257- player . ignoreFall = false
258- }
259- player . airTime = 0
260- }
261- else player . airTime ++
262-
263- // Water damage to fruit users
264- const container = player . getComponent ( EntityInventoryComponent . componentId ) ?. container
265- if ( container ?. contains ( light ) && player . isValid && player . isInWater ) {
266- const headBlock = player . dimension . getBlock ( player . getHeadLocation ( ) )
267- let damage = 0.0
268- if ( headBlock ?. typeId == "minecraft:water" ) {
269- damage = 0.5
270- if ( headBlock ?. above ( 1 ) ?. typeId == "minecraft:water" ) {
271- damage = 1
272- if ( headBlock ?. above ( 2 ) ?. typeId == "minecraft:water" ) {
273- damage = 2
274- }
275- }
216+ function processState ( player : Player ) {
217+ switch ( player . state ) {
218+ case States . NORMAL :
219+ if ( playerHasLight ( player ) && player . isInWater ) {
220+ changeState ( player , States . WEAK )
276221 }
277- player . applyDamage ( damage , { cause : EntityDamageCause . contact } )
278-
279- player . addEffect ( MinecraftEffectTypes . Weakness , 3 , { showParticles : false } )
280- player . addEffect ( MinecraftEffectTypes . Slowness , 3 , { showParticles : false } )
281- changeState ( player , States . NORMAL )
282- player . airJumps = 0
283- player . dashCooldown = dashCooldownTime
284- }
222+ break ;
285223
286- if ( player . state == States . FLYING ) {
224+ case States . FLYING :
287225 player . ignoreFall = true
288226 player . fCooldown = fCooldownTime
289227
@@ -354,8 +292,103 @@ function mainTick() {
354292 playSoundFrom ( player , "light_beam_loop" )
355293 flySoundCooldown . set ( player . id , flySoundDuration )
356294 }
295+
296+ if ( player . isInWater ) {
297+ changeState ( player , States . WEAK )
298+ }
299+ break ;
300+
301+ case States . WEAK :
302+ if ( ! player . isValid || ! player . isInWater ) {
303+ changeState ( player , States . NORMAL )
304+ return
305+ }
306+ const headBlock = player . dimension . getBlock ( player . getHeadLocation ( ) )
307+ let damage = 0.0
308+ if ( headBlock ?. typeId == "minecraft:water" ) {
309+ damage = 0.5
310+ player . addEffect ( MinecraftEffectTypes . Nausea , 80 , { showParticles : false } )
311+ if ( headBlock ?. above ( 1 ) ?. typeId == "minecraft:water" ) {
312+ damage = 1
313+ if ( headBlock ?. above ( 2 ) ?. typeId == "minecraft:water" ) {
314+ damage = 2
315+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , false )
316+
317+ }
318+ }
319+ }
320+ player . applyDamage ( damage , { cause : EntityDamageCause . contact } )
321+
322+ player . addEffect ( MinecraftEffectTypes . Weakness , 80 , { showParticles : false } )
323+ player . addEffect ( MinecraftEffectTypes . Slowness , 80 , { showParticles : false } )
324+ player . airJumps = 0
325+ player . airTime = 0
326+ player . dashCooldown = dashCooldownTime
327+ break ;
328+ }
329+ }
330+
331+ export function main ( ) {
332+ light = new ItemStack ( "whynot:light" , 1 ) ;
333+ light . lockMode = ItemLockMode . inventory ;
334+ light . keepOnDeath = true ;
335+
336+ world . getAllPlayers ( ) . forEach ( player => changeState ( player , States . NORMAL ) )
337+ world . beforeEvents . entityHurt . subscribe ( ev => {
338+ if ( ev . damageSource . cause != EntityDamageCause . fall ) return
339+
340+ const player = ev . hurtEntity as Player
341+ if ( ! player . isValid || player . typeId != "minecraft:player" ) return
342+ if ( ! player . ignoreFall ) return
343+
344+ ev . cancel = true
345+ } )
346+ world . afterEvents . playerButtonInput . subscribe ( ( { button, newButtonState, player} ) => {
347+ const pressed = newButtonState == ButtonState . Pressed
348+ if ( ! entityHasSlotTag ( player , EquipmentSlot . Mainhand , "whynot:light" ) ) return ;
349+
350+ if ( button == InputButton . Sneak && newButtonState == ButtonState . Pressed &&
351+ player . state == States . NORMAL && player . dashCooldown <= 0 ) {
352+ changeState ( player , States . DASH )
353+ }
354+ if ( button != InputButton . Jump ) return
355+ if ( player . airTime >= airborneAirtime && pressed && player . state == States . NORMAL ) {
356+ // Activate fly
357+ if ( player . fCooldown <= 0 && player . isSneaking ) {
358+ changeState ( player , States . FLYING )
359+ }
360+ // Moon jump
361+ else if ( player . airJumps > 0 ) {
362+ changeState ( player , States . MOON_JUMP )
363+ }
364+ }
365+ // Deactivate fly
366+ if ( ! pressed && player . state == States . FLYING ) {
367+ changeState ( player , States . NORMAL )
368+ }
369+ } )
370+ world . afterEvents . playerHotbarSelectedSlotChange . subscribe ( ( { itemStack, player} ) => {
371+ if ( itemStack ?. hasTag ( "whynot:light" ) ) return
372+ changeState ( player , States . NORMAL )
373+ } )
374+
375+ system . runInterval ( mainTick )
376+ }
377+
378+
379+ function mainTick ( ) {
380+ world . getAllPlayers ( ) . forEach ( player => {
381+ // Set Airtime
382+ if ( player . isOnGround ) {
383+ if ( player . state != States . FLYING ) {
384+ player . airJumps = maxAirJumps
385+ player . ignoreFall = false
386+ }
387+ player . airTime = 0
357388 }
389+ else player . airTime ++
358390
391+
359392 // Reduce all cooldowns
360393 if ( player . zCooldown > 0 ) player . zCooldown -- ;
361394 if ( player . xCooldown > 0 ) player . xCooldown -- ;
@@ -364,6 +397,8 @@ function mainTick() {
364397 if ( player . fCooldown > 0 ) player . fCooldown -- ;
365398 if ( player . dashCooldown > 0 ) player . dashCooldown -- ;
366399
400+ processState ( player )
401+
367402 // If player is holding light display cooldowns
368403 if ( ! entityHasSlotTag ( player , EquipmentSlot . Mainhand , "whynot:light" ) ) {
369404 player . camera . clear ( )
0 commit comments