1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-19 14:59:27 +00:00

Implement nautilus inventory translation.

This commit is contained in:
oryxel1
2025-12-11 22:51:55 +07:00
parent 238573536b
commit 5b16f26fc0
7 changed files with 57 additions and 41 deletions

View File

@@ -30,6 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.TrigMath; import org.cloudburstmc.math.TrigMath;
import org.cloudburstmc.math.vector.Vector2f; import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.living.animal.tameable.TameableEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.TameableEntity;
@@ -62,6 +63,8 @@ public abstract class AbstractNautilusEntity extends TameableEntity implements C
public AbstractNautilusEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, float defSpeed) { public AbstractNautilusEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, float defSpeed) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
this.vehicleComponent = new NautilusVehicleComponent(this, 0.0f, defSpeed); this.vehicleComponent = new NautilusVehicleComponent(this, 0.0f, defSpeed);
dirtyMetadata.put(EntityDataTypes.CONTAINER_SIZE, 2);
} }
@Override @Override

View File

@@ -34,8 +34,8 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import java.util.Arrays; import java.util.Arrays;
public class HorseInventoryUpdater extends InventoryUpdater { public class MountInventoryUpdater extends InventoryUpdater {
public static final HorseInventoryUpdater INSTANCE = new HorseInventoryUpdater(); public static final MountInventoryUpdater INSTANCE = new MountInventoryUpdater();
@Override @Override
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) { public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
@@ -58,10 +58,11 @@ public class HorseInventoryUpdater extends InventoryUpdater {
return true; return true;
InventorySlotPacket slotPacket = new InventorySlotPacket(); InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(4); // Horse GUI? slotPacket.setContainerId(inventory.getBedrockId());
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
return true; return true;
} }
} }

View File

@@ -26,17 +26,17 @@
package org.geysermc.geyser.translator.inventory.horse; package org.geysermc.geyser.translator.inventory.horse;
import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.updater.HorseInventoryUpdater; import org.geysermc.geyser.inventory.updater.MountInventoryUpdater;
import org.geysermc.geyser.inventory.updater.InventoryUpdater; import org.geysermc.geyser.inventory.updater.InventoryUpdater;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.BaseInventoryTranslator; import org.geysermc.geyser.translator.inventory.BaseInventoryTranslator;
public abstract class AbstractHorseInventoryTranslator extends BaseInventoryTranslator<Container> { public abstract class AbstractMountInventoryTranslator extends BaseInventoryTranslator<Container> {
private final InventoryUpdater updater; private final InventoryUpdater updater;
public AbstractHorseInventoryTranslator(int size) { public AbstractMountInventoryTranslator(int size) {
super(size); super(size);
this.updater = HorseInventoryUpdater.INSTANCE; this.updater = MountInventoryUpdater.INSTANCE;
} }
@Override @Override

View File

@@ -36,7 +36,7 @@ import org.geysermc.geyser.session.GeyserSession;
import java.util.Arrays; import java.util.Arrays;
public abstract class ChestedHorseInventoryTranslator extends AbstractHorseInventoryTranslator { public abstract class ChestedHorseInventoryTranslator extends AbstractMountInventoryTranslator {
private final int chestSize; private final int chestSize;
private final int equipSlot; private final int equipSlot;

View File

@@ -30,8 +30,8 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Container;
public class HorseInventoryTranslator extends AbstractHorseInventoryTranslator { public class MountInventoryTranslator extends AbstractMountInventoryTranslator {
public HorseInventoryTranslator(int size) { public MountInventoryTranslator(int size) {
super(size); super(size);
} }

View File

@@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
import org.geysermc.geyser.entity.type.ChestBoatEntity; import org.geysermc.geyser.entity.type.ChestBoatEntity;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity; import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.nautilus.AbstractNautilusEntity;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
@@ -122,7 +123,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
case OPEN_INVENTORY: case OPEN_INVENTORY:
if (session.getInventoryHolder() == null) { if (session.getInventoryHolder() == null) {
Entity ridingEntity = session.getPlayerEntity().getVehicle(); Entity ridingEntity = session.getPlayerEntity().getVehicle();
if (ridingEntity instanceof AbstractHorseEntity || ridingEntity instanceof ChestBoatEntity) { if (ridingEntity instanceof AbstractHorseEntity || ridingEntity instanceof AbstractNautilusEntity || ridingEntity instanceof ChestBoatEntity) {
// This mob has an inventory of its own that we should open instead. // This mob has an inventory of its own that we should open instead.
ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY); ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY);
session.sendDownstreamGamePacket(openVehicleWindowPacket); session.sendDownstreamGamePacket(openVehicleWindowPacket);

View File

@@ -37,12 +37,13 @@ import org.geysermc.geyser.entity.type.living.animal.horse.ChestedHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.LlamaEntity; import org.geysermc.geyser.entity.type.living.animal.horse.LlamaEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.SkeletonHorseEntity; import org.geysermc.geyser.entity.type.living.animal.horse.SkeletonHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.ZombieHorseEntity; import org.geysermc.geyser.entity.type.living.animal.horse.ZombieHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.nautilus.NautilusEntity;
import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.InventoryHolder; import org.geysermc.geyser.inventory.InventoryHolder;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.inventory.horse.DonkeyInventoryTranslator; import org.geysermc.geyser.translator.inventory.horse.DonkeyInventoryTranslator;
import org.geysermc.geyser.translator.inventory.horse.HorseInventoryTranslator; import org.geysermc.geyser.translator.inventory.horse.MountInventoryTranslator;
import org.geysermc.geyser.translator.inventory.horse.LlamaInventoryTranslator; import org.geysermc.geyser.translator.inventory.horse.LlamaInventoryTranslator;
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;
@@ -54,36 +55,24 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@Translator(packet = ClientboundMountScreenOpenPacket.class) @Translator(packet = ClientboundMountScreenOpenPacket.class)
public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundMountScreenOpenPacket> { public class JavaMountScreenOpenTranslator extends PacketTranslator<ClientboundMountScreenOpenPacket> {
private static final String[] ACCEPTED_HORSE_ARMORS = new String[] {"minecraft:horsearmorleather", "minecraft:horsearmoriron",
"minecraft:horsearmorgold", "minecraft:horsearmordiamond", "minecraft:copper_horse_armor", "minecraft:netherite_horse_armor"};
private static final String[] ACCEPTED_NAUTILUS_ARMORS = new String[] {"minecraft:copper_nautilus_armor", "minecraft:iron_nautilus_armor",
"minecraft:golden_nautilus_armor", "minecraft:diamond_nautilus_armor", "minecraft:netherite_nautilus_armor"};
private static final NbtMap ARMOR_SLOT;
private static final NbtMap CARPET_SLOT; private static final NbtMap SADDLE_SLOT, CARPET_SLOT;
private static final NbtMap SADDLE_SLOT; private static final NbtMap HORSE_ARMOR_SLOT, NAUTILUS_ARMOR_SLOT;
static { static {
// Build the NBT mappings that Bedrock wants to lay out the GUI HORSE_ARMOR_SLOT = buildAcceptedArmorSlot(ACCEPTED_HORSE_ARMORS, "minecraft:horsearmoriron");
String[] acceptedHorseArmorIdentifiers = new String[] {"minecraft:horsearmorleather", "minecraft:horsearmoriron", NAUTILUS_ARMOR_SLOT = buildAcceptedArmorSlot(ACCEPTED_NAUTILUS_ARMORS, "minecraft:nautilusarmor");
"minecraft:horsearmorgold", "minecraft:horsearmordiamond"};
NbtMapBuilder armorBuilder = NbtMap.builder();
List<NbtMap> acceptedArmors = new ArrayList<>(4);
for (String identifier : acceptedHorseArmorIdentifiers) {
NbtMapBuilder acceptedItemBuilder = NbtMap.builder()
.putShort("Aux", Short.MAX_VALUE)
.putString("Name", identifier);
acceptedArmors.add(NbtMap.builder().putCompound("slotItem", acceptedItemBuilder.build()).build());
}
armorBuilder.putList("acceptedItems", NbtType.COMPOUND, acceptedArmors);
NbtMapBuilder armorItem = NbtMap.builder()
.putShort("Aux", Short.MAX_VALUE)
.putString("Name", "minecraft:horsearmoriron");
armorBuilder.putCompound("item", armorItem.build());
armorBuilder.putInt("slotNumber", 1);
ARMOR_SLOT = armorBuilder.build();
NbtMapBuilder carpetBuilder = NbtMap.builder(); NbtMapBuilder carpetBuilder = NbtMap.builder();
NbtMapBuilder carpetItem = NbtMap.builder() NbtMapBuilder carpetItem = NbtMap.builder()
.putShort("Aux", Short.MAX_VALUE) .putShort("Aux", Short.MAX_VALUE)
.putString("Name", "minecraft:carpet"); .putString("Name", "minecraft:carpet");
List<NbtMap> acceptedCarpet = Collections.singletonList(NbtMap.builder().putCompound("slotItem", carpetItem.build()).build()); List<NbtMap> acceptedCarpet = Collections.singletonList(NbtMap.builder().putCompound("slotItem", carpetItem.build()).build());
carpetBuilder.putList("acceptedItems", NbtType.COMPOUND, acceptedCarpet); carpetBuilder.putList("acceptedItems", NbtType.COMPOUND, acceptedCarpet);
carpetBuilder.putCompound("item", carpetItem.build()); carpetBuilder.putCompound("item", carpetItem.build());
@@ -92,8 +81,8 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundM
NbtMapBuilder saddleBuilder = NbtMap.builder(); NbtMapBuilder saddleBuilder = NbtMap.builder();
NbtMapBuilder acceptedSaddle = NbtMap.builder() NbtMapBuilder acceptedSaddle = NbtMap.builder()
.putShort("Aux", Short.MAX_VALUE) .putShort("Aux", Short.MAX_VALUE)
.putString("Name", "minecraft:saddle"); .putString("Name", "minecraft:saddle");
List<NbtMap> acceptedItem = Collections.singletonList(NbtMap.builder().putCompound("slotItem", acceptedSaddle.build()).build()); List<NbtMap> acceptedItem = Collections.singletonList(NbtMap.builder().putCompound("slotItem", acceptedSaddle.build()).build());
saddleBuilder.putList("acceptedItems", NbtType.COMPOUND, acceptedItem); saddleBuilder.putList("acceptedItems", NbtType.COMPOUND, acceptedItem);
saddleBuilder.putCompound("item", acceptedSaddle.build()); saddleBuilder.putCompound("item", acceptedSaddle.build());
@@ -101,6 +90,26 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundM
SADDLE_SLOT = saddleBuilder.build(); SADDLE_SLOT = saddleBuilder.build();
} }
private static NbtMap buildAcceptedArmorSlot(String[] accepted, String name) {
NbtMapBuilder armorBuilder = NbtMap.builder();
List<NbtMap> acceptedArmors = new ArrayList<>(4);
for (String identifier : accepted) {
NbtMapBuilder acceptedItemBuilder = NbtMap.builder()
.putShort("Aux", Short.MAX_VALUE)
.putString("Name", identifier);
acceptedArmors.add(NbtMap.builder().putCompound("slotItem", acceptedItemBuilder.build()).build());
}
armorBuilder.putList("acceptedItems", NbtType.COMPOUND, acceptedArmors);
NbtMapBuilder armorItem = NbtMap.builder()
.putShort("Aux", Short.MAX_VALUE)
.putString("Name", name);
armorBuilder.putCompound("item", armorItem.build());
armorBuilder.putInt("slotNumber", 1);
return armorBuilder.build();
}
@Override @Override
public void translate(GeyserSession session, ClientboundMountScreenOpenPacket packet) { public void translate(GeyserSession session, ClientboundMountScreenOpenPacket packet) {
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
@@ -141,10 +150,12 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundM
inventoryTranslator = new DonkeyInventoryTranslator(slotCount); inventoryTranslator = new DonkeyInventoryTranslator(slotCount);
slots.add(SADDLE_SLOT); slots.add(SADDLE_SLOT);
} else { } else {
inventoryTranslator = new HorseInventoryTranslator(slotCount); inventoryTranslator = new MountInventoryTranslator(slotCount);
slots.add(SADDLE_SLOT); slots.add(SADDLE_SLOT);
if (!(entity instanceof SkeletonHorseEntity || entity instanceof ZombieHorseEntity)) { if (entity instanceof NautilusEntity) {
slots.add(ARMOR_SLOT); slots.add(NAUTILUS_ARMOR_SLOT);
} else if (!(entity instanceof SkeletonHorseEntity || entity instanceof ZombieHorseEntity)) {
slots.add(HORSE_ARMOR_SLOT);
} }
} }