Fix spawn egg triggering twice in water

This commit is contained in:
Camotoy 2021-06-19 20:33:07 -04:00
parent 35450f7b78
commit 683ac1c763
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
2 changed files with 48 additions and 27 deletions

View file

@ -183,6 +183,17 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
Block place checks end - client is good to go
*/
if (packet.getItemInHand() != null && ItemRegistry.SPAWN_EGGS.contains(packet.getItemInHand().getId())) {
int blockState = session.getConnector().getWorldManager().getBlockAt(session, packet.getBlockPosition());
if (blockState == BlockTranslator.JAVA_WATER_ID) {
// Otherwise causes multiple mobs to spawn - just send a use item packet
// TODO when we fix mobile bucket rotation, use it for this, too
ClientPlayerUseItemPacket itemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
session.sendDownstreamPacket(itemPacket);
break;
}
}
ClientPlayerPlaceBlockPacket blockPacket = new ClientPlayerPlaceBlockPacket(
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
BlockFace.values()[packet.getBlockFace()],
@ -191,25 +202,27 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
false);
session.sendDownstreamPacket(blockPacket);
// Otherwise boats will not be able to be placed in survival and buckets won't work on mobile
if (packet.getItemInHand() != null && ItemRegistry.BOATS.contains(packet.getItemInHand().getId())) {
ClientPlayerUseItemPacket itemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
session.sendDownstreamPacket(itemPacket);
}
// Check actions, otherwise buckets may be activated when block inventories are accessed
else if (packet.getItemInHand() != null && ItemRegistry.BUCKETS.contains(packet.getItemInHand().getId())) {
// Let the server decide if the bucket item should change, not the client, and revert the changes the client made
InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(ContainerId.INVENTORY);
slotPacket.setSlot(packet.getHotbarSlot());
slotPacket.setItem(packet.getItemInHand());
session.sendUpstreamPacket(slotPacket);
// Delay the interaction in case the client doesn't intend to actually use the bucket
// See BedrockActionTranslator.java
session.setBucketScheduledFuture(session.getConnector().getGeneralThreadPool().schedule(() -> {
if (packet.getItemInHand() != null) {
// Otherwise boats will not be able to be placed in survival and buckets won't work on mobile
if (ItemRegistry.BOATS.contains(packet.getItemInHand().getId())) {
ClientPlayerUseItemPacket itemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
session.sendDownstreamPacket(itemPacket);
}, 5, TimeUnit.MILLISECONDS));
}
// Check actions, otherwise buckets may be activated when block inventories are accessed
else if (ItemRegistry.BUCKETS.contains(packet.getItemInHand().getId())) {
// Let the server decide if the bucket item should change, not the client, and revert the changes the client made
InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(ContainerId.INVENTORY);
slotPacket.setSlot(packet.getHotbarSlot());
slotPacket.setItem(packet.getItemInHand());
session.sendUpstreamPacket(slotPacket);
// Delay the interaction in case the client doesn't intend to actually use the bucket
// See BedrockActionTranslator.java
session.setBucketScheduledFuture(session.getConnector().getGeneralThreadPool().schedule(() -> {
ClientPlayerUseItemPacket itemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
session.sendDownstreamPacket(itemPacket);
}, 5, TimeUnit.MILLISECONDS));
}
}
if (packet.getActions().isEmpty()) {
@ -253,10 +266,15 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
break;
}
// Handled in ITEM_USE if the item is not milk
if (packet.getItemInHand() != null && ItemRegistry.BUCKETS.contains(packet.getItemInHand().getId()) &&
packet.getItemInHand().getId() != ItemRegistry.MILK_BUCKET.getBedrockId()) {
break;
if (packet.getItemInHand() != null) {
if (ItemRegistry.BUCKETS.contains(packet.getItemInHand().getId()) &&
packet.getItemInHand().getId() != ItemRegistry.MILK_BUCKET.getBedrockId()) {
// Handled in case 0 if the item is not milk
break;
} else if (ItemRegistry.SPAWN_EGGS.contains(packet.getItemInHand().getId())) {
// Handled in case 0
break;
}
}
ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);

View file

@ -37,10 +37,7 @@ import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
@ -113,6 +110,10 @@ public class ItemRegistry {
* Shield item entry, used in Entity.java and LivingEntity.java
*/
public static ItemEntry SHIELD;
/**
* A list of all spawn eggs by their Bedrock IDs. Used in BedrockInventoryTransactionTranslator.java
*/
public static final IntSet SPAWN_EGGS = new IntArraySet();
/**
* Wheat item entry, used in AbstractHorseEntity.java
*/
@ -457,9 +458,9 @@ public class ItemRegistry {
}
if (entry.getKey().contains("boat")) {
BOATS.add(entry.getValue().get("bedrock_id").intValue());
BOATS.add(itemEntry.getBedrockId());
} else if (entry.getKey().contains("bucket") && !entry.getKey().contains("milk")) {
BUCKETS.add(entry.getValue().get("bedrock_id").intValue());
BUCKETS.add(itemEntry.getBedrockId());
} else if (entry.getKey().contains("_carpet") && !entry.getKey().contains("moss")) {
// This should be the numerical order Java sends as an integer value for llamas
CARPETS.add(ItemData.builder()
@ -471,6 +472,8 @@ public class ItemRegistry {
// The Java record level event uses the item ID as the "key" to play the record
EffectRegistry.RECORDS.put(itemIndex, SoundEvent.valueOf("RECORD_" +
entry.getKey().replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH)));
} else if (entry.getKey().endsWith("_spawn_egg")) {
SPAWN_EGGS.add(itemEntry.getBedrockId());
}
itemNames.add(entry.getKey());