Constant damage results in crash if taking damage fast-forwards the game.
James103 opened this issue ยท 2 comments
To reproduce:
- Place a repeating command block with the command
summon minecraft:falling_block ~ ~10 ~ {BlockState:{Name:"minecraft:anvil"},Time:1}
. - Place a stone pressure plate on the command block.
- Run the following command:
/script run __on_player_takes_damage(player, amount, source, source_entity) -> (modify(player, 'effect', 'hunger', floor(2*amount), 199); modify(player, 'effect', 'resistance', floor(20*amount)); loop(floor(20*amount),game_tick());)
- Step on the pressure plate.
- Crash.
Also reproducible with lava and to a lesser extent cactus and some mobs.
Last four crashes:
crash-2020-05-22_19.25.26-server.txt
crash-2020-05-22_19.42.10-server.txt
crash-2020-05-22_19.43.11-server.txt
crash-2020-05-22_19.43.44-server.txt
Most likely cause:
- Taking damage calls the
__on_player_takes_damage
handler. - The
__on_player_takes_damage
handler is set to call thegame_tick()
function a bunch of times. - During one of the subsequent
game_tick()
calls, the player gets damaged again. - Repeat steps 1 through 3 until a
java.lang.StackOverflowError
is triggered. - This then results in a bunch of
... HERE>> game_tick() ...
andCallback failed
messages and eventually a crash.
In that case, isn't it semi-intended, if it's a StackOverflowError
, as it's an intended error?
And btw (out of curiosity) , what sort of crazy testing do you do to discover these bugs man?
well, you are promising to handle player taking damage event and while handling it, you are causing the game to tick potentially catching the same event while still handling the previous event. Its a typical stack overflow causer. Make sure to release handling of the event before ticking the world, of if you are not sure it won't be handling itself, continue execution with schedule
or task
, like
__handle_damage(args) ->
(
do_somethings();
game_tick(50);
do_something_else();
)
__handle_safer(args) ->
(
do_something();
schedule(0, 'do_something_else', args);
)
With your setup of receiving constant damage, you may still run over your system infinitely, but at least it wouldn't keep adding layers to the stack.