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
is duplicated by 4
relates to 1
Attachments
Comments 6
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.
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:
Stop setting
DATA_PEEK_ID
insetPos()
andteleportSomewhere()
. 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.Have
ShulkerAttackGoal
'scanContinueToUse()
return false if theDATA_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.Have
ShulkerAttackGoal
'stick()
method re-callsetRawPeekAmount(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).
Please include a video of this happening if you can