mojira.dev
MC-216251

Shulkers will shoot a bullet with their shell closed after teleporting

Just as the title says. Found that shulkers were able to shoot bullets despite being closed. This seems to happen consistently after a shulker teleports, and remains that way for ~30 seconds before they open their shells again. 

I have not tested this in other versions, but I don't remember seeing any issues in the past

 

Linked issues

Attachments

Comments 6

Please include a video of this happening if you can

Done, I should also add this only seems to happen when the shulker teleports on its own. They seem to work fine if you force them to teleport by breaking the block below it.

Thanks!

I took a look through decompiled code to try to see what's going on here.

When a shulker acquires a target, the ShulkerAttackGoal AI routine begins running. It's start() calls setRawPeekAmount(100) to open the shell, and the routine periodically shoots bullets. When the target is lost for whatever reason, its stop() calls setRawPeekAmount(0) to close the shell.

There's also the ShulkerPeekGoal AI routine, which runs randomly while the shulker has no target. It's start() calls setRawPeekAmount(30) to slightly open the shell, and when it ends (either 1–3 seconds later or when a target is acquired) it calls setRawPeekAmount(0) to close the shell again except when a target was acquired, presumably so as to not interfere with ShulkerAttackGoal having just started.

So far so good.

But in the shulker's setPos() and teleportSomewhere() methods also set the DATA_PEEK_ID value directly to 0, which causes the shell to close.

If setPos() is called for whatever reason while the ShulkerAttackGoal routine is active (e.g. push the shulker with a piston, or move it with a minecart), we get the result that the shell is closed but the shulker still shoots bullets. This state continues until the shulker manages to lose its target and ShulkerAttackGoal ends.

teleportSomewhere() is slightly better, as it also clears the target which should cause ShulkerAttackGoal to end. But it seems there's still a race condition here, if a target is reacquired before ShulkerAttackGoal is evaluated then it won't end and we get the same result as above.

I can think of a few ways this might be fixed:

  1. Stop setting DATA_PEEK_ID in setPos() and teleportSomewhere(). Although I suspect that the reason they do is because it looks odd for an open shulker to teleport, so this may not be the best idea.

  2. Have ShulkerAttackGoal's canContinueToUse() return false if the DATA_PEEK_ID value is no longer 100. This would make it stop, restoring a consistent state, and then restart right away. OTOH, that might break shulkers in moving minecarts from ever attacking, which may also be an undesirable behavior change.

  3. Have ShulkerAttackGoal's tick() method re-call setRawPeekAmount(100) periodically, perhaps whenever it's about to shoot or perhaps whenever it finds the value has changed away from 100.

Not sure if this is quite as useful, but I've found that this actually has some interesting buggy effects on NoAI Shulkers too. When teleported by the /tp command, the shulkers appear to close, yet they keep the Peek NBT. This might not be related, but it also seems to cause shulkers that are riding a teleported entity to do the same. What is problematic is that this also causes MC-254449, where the shulkers retract due to being teleported with their vehicle on the client but remain open on server (which can cause sort-of softlocks where the ghost-block like effect makes you unable to move).

Saw this happen today in 1.20.6

Landon

(Unassigned)

Confirmed

Gameplay

Normal

Mob behaviour

Minecraft 15w31c, Minecraft 15w32a, Minecraft 15w32b, Minecraft 15w32c, 1.16.5, 21w07a, 1.17.1, 1.18.2, 1.21

Retrieved