mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Fix: Totem animation when playing totem effects manually (#4860)
* Fix: Totem animation for manually played totem effects * Ensure we always reset the offhand correctly
This commit is contained in:
parent
9cdda707a3
commit
06890504a2
4 changed files with 39 additions and 1 deletions
|
@ -29,6 +29,7 @@ import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.item.type.Item;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||||
import org.jetbrains.annotations.Range;
|
import org.jetbrains.annotations.Range;
|
||||||
|
@ -73,6 +74,10 @@ public class PlayerInventory extends Inventory {
|
||||||
return items[36 + heldItemSlot];
|
return items[36 + heldItemSlot];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean eitherHandMatchesItem(@NonNull Item item) {
|
||||||
|
return getItemInHand().asItem() == item || getItemInHand(Hand.OFF_HAND).asItem() == item;
|
||||||
|
}
|
||||||
|
|
||||||
public void setItemInHand(@NonNull GeyserItemStack item) {
|
public void setItemInHand(@NonNull GeyserItemStack item) {
|
||||||
if (36 + heldItemSlot > this.size) {
|
if (36 + heldItemSlot > this.size) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Held item slot was larger than expected!");
|
GeyserImpl.getInstance().getLogger().debug("Held item slot was larger than expected!");
|
||||||
|
|
|
@ -50,6 +50,7 @@ public class StoredItemMappings {
|
||||||
private final ItemMapping milkBucket;
|
private final ItemMapping milkBucket;
|
||||||
private final ItemMapping powderSnowBucket;
|
private final ItemMapping powderSnowBucket;
|
||||||
private final ItemMapping shield;
|
private final ItemMapping shield;
|
||||||
|
private final ItemMapping totem;
|
||||||
private final ItemMapping upgradeTemplate;
|
private final ItemMapping upgradeTemplate;
|
||||||
private final ItemMapping wheat;
|
private final ItemMapping wheat;
|
||||||
private final ItemMapping writableBook;
|
private final ItemMapping writableBook;
|
||||||
|
@ -66,6 +67,7 @@ public class StoredItemMappings {
|
||||||
this.milkBucket = load(itemMappings, Items.MILK_BUCKET);
|
this.milkBucket = load(itemMappings, Items.MILK_BUCKET);
|
||||||
this.powderSnowBucket = load(itemMappings, Items.POWDER_SNOW_BUCKET);
|
this.powderSnowBucket = load(itemMappings, Items.POWDER_SNOW_BUCKET);
|
||||||
this.shield = load(itemMappings, Items.SHIELD);
|
this.shield = load(itemMappings, Items.SHIELD);
|
||||||
|
this.totem = load(itemMappings, Items.TOTEM_OF_UNDYING);
|
||||||
this.upgradeTemplate = load(itemMappings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE);
|
this.upgradeTemplate = load(itemMappings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE);
|
||||||
this.wheat = load(itemMappings, Items.WHEAT);
|
this.wheat = load(itemMappings, Items.WHEAT);
|
||||||
this.writableBook = load(itemMappings, Items.WRITABLE_BOOK);
|
this.writableBook = load(itemMappings, Items.WRITABLE_BOOK);
|
||||||
|
|
|
@ -29,7 +29,9 @@ import org.cloudburstmc.protocol.bedrock.data.ParticleType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
|
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket;
|
||||||
|
@ -42,11 +44,15 @@ import org.geysermc.geyser.entity.type.FishingHookEntity;
|
||||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||||
import org.geysermc.geyser.entity.type.living.animal.ArmadilloEntity;
|
import org.geysermc.geyser.entity.type.living.animal.ArmadilloEntity;
|
||||||
import org.geysermc.geyser.entity.type.living.monster.WardenEntity;
|
import org.geysermc.geyser.entity.type.living.monster.WardenEntity;
|
||||||
|
import org.geysermc.geyser.item.Items;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
|
import org.geysermc.geyser.util.InventoryUtils;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@Translator(packet = ClientboundEntityEventPacket.class)
|
@Translator(packet = ClientboundEntityEventPacket.class)
|
||||||
|
@ -154,6 +160,16 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
||||||
entityEventPacket.setType(EntityEventType.WITCH_HAT_MAGIC); //TODO: CHECK
|
entityEventPacket.setType(EntityEventType.WITCH_HAT_MAGIC); //TODO: CHECK
|
||||||
break;
|
break;
|
||||||
case TOTEM_OF_UNDYING_MAKE_SOUND:
|
case TOTEM_OF_UNDYING_MAKE_SOUND:
|
||||||
|
// Bedrock will not play the spinning animation without the item in the hand o.o
|
||||||
|
// Fixes https://github.com/GeyserMC/Geyser/issues/2446
|
||||||
|
boolean totemItemWorkaround = !session.getPlayerInventory().eitherHandMatchesItem(Items.TOTEM_OF_UNDYING);
|
||||||
|
if (totemItemWorkaround) {
|
||||||
|
InventoryContentPacket offhandPacket = new InventoryContentPacket();
|
||||||
|
offhandPacket.setContainerId(ContainerId.OFFHAND);
|
||||||
|
offhandPacket.setContents(Collections.singletonList(InventoryUtils.getTotemOfUndying().apply(session.getUpstream().getProtocolVersion())));
|
||||||
|
session.sendUpstreamPacket(offhandPacket);
|
||||||
|
}
|
||||||
|
|
||||||
entityEventPacket.setType(EntityEventType.CONSUME_TOTEM);
|
entityEventPacket.setType(EntityEventType.CONSUME_TOTEM);
|
||||||
|
|
||||||
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
||||||
|
@ -162,7 +178,16 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
||||||
playSoundPacket.setVolume(1.0F);
|
playSoundPacket.setVolume(1.0F);
|
||||||
playSoundPacket.setPitch(1.0F + (ThreadLocalRandom.current().nextFloat() * 0.1F) - 0.05F);
|
playSoundPacket.setPitch(1.0F + (ThreadLocalRandom.current().nextFloat() * 0.1F) - 0.05F);
|
||||||
session.sendUpstreamPacket(playSoundPacket);
|
session.sendUpstreamPacket(playSoundPacket);
|
||||||
break;
|
|
||||||
|
// Sent here early to ensure we have the totem in our hand
|
||||||
|
session.sendUpstreamPacket(entityEventPacket);
|
||||||
|
|
||||||
|
if (totemItemWorkaround) {
|
||||||
|
// Reset the item again
|
||||||
|
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), 45);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
case SHEEP_GRAZE_OR_TNT_CART_EXPLODE:
|
case SHEEP_GRAZE_OR_TNT_CART_EXPLODE:
|
||||||
if (entity.getDefinition() == EntityDefinitions.SHEEP) {
|
if (entity.getDefinition() == EntityDefinitions.SHEEP) {
|
||||||
entityEventPacket.setType(EntityEventType.EAT_GRASS);
|
entityEventPacket.setType(EntityEventType.EAT_GRASS);
|
||||||
|
|
|
@ -253,6 +253,12 @@ public class InventoryUtils {
|
||||||
.count(1).build();
|
.count(1).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IntFunction<ItemData> getTotemOfUndying() {
|
||||||
|
return protocolVersion -> ItemData.builder()
|
||||||
|
.definition(Registries.ITEMS.forVersion(protocolVersion).getStoredItems().totem().getBedrockDefinition())
|
||||||
|
.count(1).build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link #findOrCreateItem(GeyserSession, String)}. This is for finding a specified {@link ItemStack}.
|
* See {@link #findOrCreateItem(GeyserSession, String)}. This is for finding a specified {@link ItemStack}.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue