Boat changes applied

This commit is contained in:
Camotoy 2024-10-20 14:54:27 -04:00
parent e2f40569f8
commit 93d96ef5a4
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
14 changed files with 178 additions and 99 deletions

View file

@ -152,29 +152,37 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatE
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
public final class EntityDefinitions {
public static final EntityDefinition<BoatEntity> ACACIA_BOAT;
public static final EntityDefinition<ChestBoatEntity> ACACIA_CHEST_BOAT;
public static final EntityDefinition<AllayEntity> ALLAY;
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
public static final EntityDefinition<ArmadilloEntity> ARMADILLO;
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
public static final EntityDefinition<ArrowEntity> ARROW;
public static final EntityDefinition<AxolotlEntity> AXOLOTL;
public static final EntityDefinition<BoatEntity> BAMBOO_RAFT;
public static final EntityDefinition<ChestBoatEntity> BAMBOO_CHEST_RAFT;
public static final EntityDefinition<BatEntity> BAT;
public static final EntityDefinition<BeeEntity> BEE;
public static final EntityDefinition<BoatEntity> BIRCH_BOAT;
public static final EntityDefinition<ChestBoatEntity> BIRCH_CHEST_BOAT;
public static final EntityDefinition<BlazeEntity> BLAZE;
public static final EntityDefinition<BoatEntity> BOAT;
public static final EntityDefinition<BoggedEntity> BOGGED;
public static final EntityDefinition<BreezeEntity> BREEZE;
public static final EntityDefinition<AbstractWindChargeEntity> BREEZE_WIND_CHARGE;
public static final EntityDefinition<CamelEntity> CAMEL;
public static final EntityDefinition<CatEntity> CAT;
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
public static final EntityDefinition<BoatEntity> CHERRY_BOAT;
public static final EntityDefinition<ChestBoatEntity> CHERRY_CHEST_BOAT;
public static final EntityDefinition<MinecartEntity> CHEST_MINECART;
public static final EntityDefinition<ChickenEntity> CHICKEN;
public static final EntityDefinition<ChestBoatEntity> CHEST_BOAT;
public static final EntityDefinition<AbstractFishEntity> COD;
public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART;
public static final EntityDefinition<CowEntity> COW;
public static final EntityDefinition<CreeperEntity> CREEPER;
public static final EntityDefinition<BoatEntity> DARK_OAK_BOAT;
public static final EntityDefinition<ChestBoatEntity> DARK_OAK_CHEST_BOAT;
public static final EntityDefinition<DolphinEntity> DOLPHIN;
public static final EntityDefinition<ChestedHorseEntity> DONKEY;
public static final EntityDefinition<FireballEntity> DRAGON_FIREBALL;
@ -213,14 +221,20 @@ public final class EntityDefinitions {
public static final EntityDefinition<IronGolemEntity> IRON_GOLEM;
public static final EntityDefinition<ItemEntity> ITEM;
public static final EntityDefinition<ItemFrameEntity> ITEM_FRAME;
public static final EntityDefinition<BoatEntity> JUNGLE_BOAT;
public static final EntityDefinition<ChestBoatEntity> JUNGLE_CHEST_BOAT;
public static final EntityDefinition<LeashKnotEntity> LEASH_KNOT;
public static final EntityDefinition<LightningEntity> LIGHTNING_BOLT;
public static final EntityDefinition<LlamaEntity> LLAMA;
public static final EntityDefinition<ThrowableEntity> LLAMA_SPIT;
public static final EntityDefinition<MagmaCubeEntity> MAGMA_CUBE;
public static final EntityDefinition<BoatEntity> MANGROVE_BOAT;
public static final EntityDefinition<ChestBoatEntity> MANGROVE_CHEST_BOAT;
public static final EntityDefinition<MinecartEntity> MINECART;
public static final EntityDefinition<MooshroomEntity> MOOSHROOM;
public static final EntityDefinition<ChestedHorseEntity> MULE;
public static final EntityDefinition<BoatEntity> OAK_BOAT;
public static final EntityDefinition<ChestBoatEntity> OAK_CHEST_BOAT;
public static final EntityDefinition<OcelotEntity> OCELOT;
public static final EntityDefinition<PaintingEntity> PAINTING;
public static final EntityDefinition<PandaEntity> PANDA;
@ -251,6 +265,8 @@ public final class EntityDefinitions {
public static final EntityDefinition<SpawnerMinecartEntity> SPAWNER_MINECART; // Not present on Bedrock
public static final EntityDefinition<AbstractArrowEntity> SPECTRAL_ARROW;
public static final EntityDefinition<SpiderEntity> SPIDER;
public static final EntityDefinition<BoatEntity> SPRUCE_BOAT;
public static final EntityDefinition<ChestBoatEntity> SPRUCE_CHEST_BOAT;
public static final EntityDefinition<SquidEntity> SQUID;
public static final EntityDefinition<AbstractSkeletonEntity> STRAY;
public static final EntityDefinition<StriderEntity> STRIDER;
@ -309,23 +325,6 @@ public final class EntityDefinitions {
.addTranslator(null) // Waiting
.addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle)
.build();
BOAT = EntityDefinition.inherited(BoatEntity::new, entityBase)
.type(EntityType.BOAT)
.height(0.6f).width(1.6f)
.offset(0.35f)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction
.addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) ->
// 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock
boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue())))
.addTranslator(MetadataType.INT, BoatEntity::setVariant)
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft)
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
.build();
CHEST_BOAT = EntityDefinition.inherited(ChestBoatEntity::new, BOAT)
.type(EntityType.CHEST_BOAT)
.build();
DRAGON_FIREBALL = EntityDefinition.inherited(FireballEntity::new, entityBase)
.type(EntityType.DRAGON_FIREBALL)
.heightAndWidth(1.0f)
@ -568,6 +567,45 @@ public final class EntityDefinitions {
.build(false);
}
// Boats
{
EntityDefinition<BoatEntity> boatBase = EntityDefinition.<BoatEntity>inherited(null, entityBase)
.height(0.6f).width(1.6f)
.offset(0.35f)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction
.addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) ->
// 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock
boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue())))
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft)
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
.build();
ACACIA_BOAT = buildBoat(boatBase, EntityType.ACACIA_BOAT, BoatEntity.BoatVariant.ACACIA);
BAMBOO_RAFT = buildBoat(boatBase, EntityType.BAMBOO_RAFT, BoatEntity.BoatVariant.BAMBOO);
BIRCH_BOAT = buildBoat(boatBase, EntityType.BIRCH_BOAT, BoatEntity.BoatVariant.BIRCH);
CHERRY_BOAT = buildBoat(boatBase, EntityType.CHERRY_BOAT, BoatEntity.BoatVariant.CHERRY);
DARK_OAK_BOAT = buildBoat(boatBase, EntityType.DARK_OAK_BOAT, BoatEntity.BoatVariant.DARK_OAK);
JUNGLE_BOAT = buildBoat(boatBase, EntityType.JUNGLE_BOAT, BoatEntity.BoatVariant.JUNGLE);
MANGROVE_BOAT = buildBoat(boatBase, EntityType.MANGROVE_BOAT, BoatEntity.BoatVariant.MANGROVE);
OAK_BOAT = buildBoat(boatBase, EntityType.OAK_BOAT, BoatEntity.BoatVariant.OAK);
SPRUCE_BOAT = buildBoat(boatBase, EntityType.SPRUCE_BOAT, BoatEntity.BoatVariant.SPRUCE);
EntityDefinition<ChestBoatEntity> chestBoatBase = EntityDefinition.<ChestBoatEntity>inherited(null, boatBase)
.build();
ACACIA_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.ACACIA_CHEST_BOAT, BoatEntity.BoatVariant.ACACIA);
BAMBOO_CHEST_RAFT = buildChestBoat(chestBoatBase, EntityType.BAMBOO_CHEST_RAFT, BoatEntity.BoatVariant.BAMBOO);
BIRCH_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.BIRCH_CHEST_BOAT, BoatEntity.BoatVariant.BIRCH);
CHERRY_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.CHERRY_CHEST_BOAT, BoatEntity.BoatVariant.CHERRY);
DARK_OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.DARK_OAK_CHEST_BOAT, BoatEntity.BoatVariant.DARK_OAK);
JUNGLE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.JUNGLE_CHEST_BOAT, BoatEntity.BoatVariant.JUNGLE);
MANGROVE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.MANGROVE_CHEST_BOAT, BoatEntity.BoatVariant.MANGROVE);
OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.OAK_CHEST_BOAT, BoatEntity.BoatVariant.OAK);
SPRUCE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.SPRUCE_CHEST_BOAT, BoatEntity.BoatVariant.SPRUCE);
}
EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase)
.addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags)
.addTranslator(MetadataType.FLOAT, LivingEntity::setHealth)
@ -1128,6 +1166,22 @@ public final class EntityDefinitions {
}
}
private static EntityDefinition<BoatEntity> buildBoat(EntityDefinition<BoatEntity> base, EntityType entityType, BoatEntity.BoatVariant variant) {
return EntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) ->
new BoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base)
.type(entityType)
.identifier("minecraft:boat")
.build();
}
private static EntityDefinition<ChestBoatEntity> buildChestBoat(EntityDefinition<ChestBoatEntity> base, EntityType entityType, BoatEntity.BoatVariant variant) {
return EntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) ->
new ChestBoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base)
.type(entityType)
.identifier("minecraft:chest_boat")
.build();
}
public static void init() {
// no-op
}

View file

@ -32,11 +32,12 @@ import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID;
@ -63,16 +64,19 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
* Saved for using the "pick" functionality on a boat.
*/
@Getter
private int variant;
protected final BoatVariant variant;
private long leashHolderBedrockId = -1;
// Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it
private final float ROWING_SPEED = 0.1f;
public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) {
// Initial rotation is incorrect
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
this.variant = variant;
dirtyMetadata.put(EntityDataTypes.VARIANT, variant.ordinal());
// Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+
dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, true);
@ -124,15 +128,6 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
moveRelative(0, 0, 0, yaw + 90, 0, 0, isOnGround);
}
public void setVariant(IntEntityMetadata entityMetadata) {
variant = entityMetadata.getPrimitiveValue();
dirtyMetadata.put(EntityDataTypes.VARIANT, switch (variant) {
case 6, 7, 8 -> variant - 1; // dark_oak, mangrove, bamboo
case 5 -> 8; // cherry
default -> variant;
});
}
public void setPaddlingLeft(BooleanEntityMetadata entityMetadata) {
isPaddlingLeft = entityMetadata.getPrimitiveValue();
if (!isPaddlingLeft) {
@ -212,6 +207,10 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
return leashHolderBedrockId;
}
public Item getPickItem() {
return variant.pickItem;
}
private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) {
AnimatePacket packet = new AnimatePacket();
packet.setRuntimeEntityId(rower.getGeyserId());
@ -219,4 +218,27 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
packet.setRowingTime(rowTime);
session.sendUpstreamPacket(packet);
}
/**
* Ordered by Bedrock ordinal
*/
public enum BoatVariant {
OAK(Items.OAK_BOAT, Items.OAK_CHEST_BOAT),
SPRUCE(Items.SPRUCE_BOAT, Items.SPRUCE_CHEST_BOAT),
BIRCH(Items.BIRCH_BOAT, Items.BIRCH_CHEST_BOAT),
JUNGLE(Items.JUNGLE_BOAT, Items.JUNGLE_CHEST_BOAT),
ACACIA(Items.ACACIA_BOAT, Items.ACACIA_CHEST_BOAT),
DARK_OAK(Items.DARK_OAK_BOAT, Items.DARK_OAK_CHEST_BOAT),
MANGROVE(Items.MANGROVE_BOAT, Items.MANGROVE_CHEST_BOAT),
BAMBOO(Items.BAMBOO_RAFT, Items.BAMBOO_CHEST_RAFT),
CHERRY(Items.CHERRY_BOAT, Items.CHERRY_CHEST_BOAT);
private final Item pickItem;
final Item chestPickItem;
BoatVariant(Item pickItem, Item chestPickItem) {
this.pickItem = pickItem;
this.chestPickItem = chestPickItem;
}
}
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -35,8 +36,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID;
public class ChestBoatEntity extends BoatEntity {
public ChestBoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
public ChestBoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, variant);
}
@Override
@ -48,4 +49,9 @@ public class ChestBoatEntity extends BoatEntity {
public InteractionResult interact(Hand hand) {
return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS;
}
@Override
public Item getPickItem() {
return this.variant.chestPickItem;
}
}

View file

@ -51,29 +51,14 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator<EntityP
Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
if (entity == null) return;
if (entity instanceof BoatEntity boat) {
InventoryUtils.findOrCreateItem(session, boat.getPickItem());
return;
}
// Get the corresponding item
String itemName;
switch (entity.getDefinition().entityType()) {
case BOAT, CHEST_BOAT -> {
// Include type of boat in the name
int variant = ((BoatEntity) entity).getVariant();
String typeOfBoat = switch (variant) {
case 1 -> "spruce";
case 2 -> "birch";
case 3 -> "jungle";
case 4 -> "acacia";
case 5 -> "cherry";
case 6 -> "dark_oak";
case 7 -> "mangrove";
case 8 -> "bamboo";
default -> "oak";
};
itemName = typeOfBoat + "_" + entity.getDefinition().entityType().name().toLowerCase(Locale.ROOT);
// Bamboo boat is a raft
if (variant == 8) {
itemName = itemName.replace("boat", "raft");
}
}
case LEASH_KNOT -> itemName = "lead";
case CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART, HOPPER_MINECART, TNT_MINECART ->
// The Bedrock identifier matches the item name which moves MINECART to the end of the name

View file

@ -296,6 +296,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
Hand.MAIN_HAND,
packet.getClickPosition().getX(), packet.getClickPosition().getY(), packet.getClickPosition().getZ(),
false,
false,
sequence);
session.sendDownstreamGamePacket(blockPacket);
@ -698,9 +699,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
float pitch = (float) -Math.toDegrees(Math.atan2(yDiff, xzHypot));
SessionPlayerEntity entity = session.getPlayerEntity();
ServerboundMovePlayerPosRotPacket returnPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), entity.getYaw(), entity.getPitch());
ServerboundMovePlayerPosRotPacket returnPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), false, playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), entity.getYaw(), entity.getPitch());
// This matches Java edition behavior
ServerboundMovePlayerPosRotPacket movementPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), yaw, pitch);
ServerboundMovePlayerPosRotPacket movementPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), false, playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), yaw, pitch);
session.sendDownstreamGamePacket(movementPacket);
if (session.getLookBackScheduledFuture() != null) {

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.session.GeyserSession;
@ -66,7 +65,7 @@ public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator<MoveEn
float y = packet.getPosition().getY();
if (ridingEntity instanceof BoatEntity && !ridingEntity.isOnGround()) {
// Remove the offset to prevents boats from looking like they're floating in water
y -= EntityDefinitions.BOAT.offset();
y -= ridingEntity.getDefinition().offset();
}
ServerboundMoveVehiclePacket ServerboundMoveVehiclePacket = new ServerboundMoveVehiclePacket(
packet.getPosition().getX(), y, packet.getPosition().getZ(),

View file

@ -25,11 +25,8 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPlayerInputPacket;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.packet.PlayerInputPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
@ -37,6 +34,7 @@ import org.geysermc.geyser.entity.type.living.animal.horse.LlamaEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket;
/**
* Sent by the client for minecarts and boats.
@ -46,11 +44,11 @@ public class BedrockPlayerInputTranslator extends PacketTranslator<PlayerInputPa
@Override
public void translate(GeyserSession session, PlayerInputPacket packet) {
ServerboundPlayerInputPacket playerInputPacket = new ServerboundPlayerInputPacket(
packet.getInputMotion().getX(), packet.getInputMotion().getY(), packet.isJumping(), packet.isSneaking()
);
session.sendDownstreamGamePacket(playerInputPacket);
// ServerboundPlayerInputPacket playerInputPacket = new ServerboundPlayerInputPacket(
// packet.getInputMotion().getX(), packet.getInputMotion().getY(), packet.isJumping(), packet.isSneaking()
// );
//
// session.sendDownstreamGamePacket(playerInputPacket);
session.getPlayerEntity().setVehicleInput(packet.getInputMotion());
@ -78,7 +76,7 @@ public class BedrockPlayerInputTranslator extends PacketTranslator<PlayerInputPa
if (vehicle instanceof BoatEntity && !vehicle.isOnGround()) {
// Remove some Y position to prevents boats flying up
vehiclePosition = vehiclePosition.down(EntityDefinitions.BOAT.offset());
vehiclePosition = vehiclePosition.down(vehicle.getDefinition().offset());
}
ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(

View file

@ -350,6 +350,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
Hand.MAIN_HAND,
0, 0, 0,
false,
false,
session.getWorldCache().nextPredictionSequence());
session.sendDownstreamGamePacket(blockPacket);
break;

View file

@ -25,16 +25,11 @@
package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerState;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
import org.cloudburstmc.protocol.bedrock.packet.InteractPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
import org.geysermc.geyser.entity.type.ChestBoatEntity;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
import org.geysermc.geyser.item.Items;
@ -42,6 +37,11 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerState;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket;
import java.util.concurrent.TimeUnit;
@ -119,7 +119,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
case OPEN_INVENTORY:
if (session.getOpenInventory() == null) {
Entity ridingEntity = session.getPlayerEntity().getVehicle();
if (ridingEntity instanceof AbstractHorseEntity || (ridingEntity != null && ridingEntity.getDefinition().entityType() == EntityType.CHEST_BOAT)) {
if (ridingEntity instanceof AbstractHorseEntity || ridingEntity instanceof ChestBoatEntity) {
// This mob has an inventory of its own that we should open instead.
ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY);
session.sendDownstreamGamePacket(openVehicleWindowPacket);

View file

@ -84,7 +84,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
// This isn't needed, but it makes the packets closer to vanilla
// It also means you can't "lag back" while only looking, in theory
if (!positionChanged && rotationChanged) {
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(packet.isOnGround(), yaw, pitch);
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(packet.isOnGround(), false, yaw, pitch);
entity.setYaw(yaw);
entity.setPitch(pitch);
@ -138,6 +138,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
// Send rotation updates as well
movePacket = new ServerboundMovePlayerPosRotPacket(
onGround,
false,
position.getX(), yPosition, position.getZ(),
yaw, pitch
);
@ -146,7 +147,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
entity.setHeadYaw(headYaw);
} else {
// Rotation did not change; don't send an update with rotation
movePacket = new ServerboundMovePlayerPosPacket(onGround, position.getX(), yPosition, position.getZ());
movePacket = new ServerboundMovePlayerPosPacket(onGround, false, position.getX(), yPosition, position.getZ());
}
entity.setPositionManual(packet.getPosition());

View file

@ -89,6 +89,7 @@ public class BedrockLevelSoundEventTranslator extends PacketTranslator<LevelSoun
Hand.MAIN_HAND,
0, 0, 0,
false,
false,
session.getWorldCache().nextPredictionSequence());
session.sendDownstreamGamePacket(blockPacket);
}

View file

@ -39,7 +39,7 @@ public class JavaCooldownTranslator extends PacketTranslator<ClientboundCooldown
@Override
public void translate(GeyserSession session, ClientboundCooldownPacket packet) {
Item item = Registries.JAVA_ITEMS.get().get(packet.getItemId());
Item item = Registries.JAVA_ITEMS.get().get(0); // FIXME
// Not every item, as of 1.19, appears to be server-driven. Just these two.
// Use a map here if it gets too big.
String cooldownCategory;

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.util;
import java.util.Locale;
import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -35,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.ChestBoatEntity;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.TextDisplayEntity;
import org.geysermc.geyser.entity.type.living.ArmorStandEntity;
@ -49,6 +49,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import java.util.Locale;
public final class EntityUtils {
/**
* A constant array of the two hands that a player can interact with an entity.
@ -93,6 +95,10 @@ public final class EntityUtils {
}
private static float getMountedHeightOffset(Entity mount) {
if (mount instanceof BoatEntity boat && boat.getVariant() != BoatEntity.BoatVariant.BAMBOO) {
return -0.1f;
}
float height = mount.getBoundingBoxHeight();
float mountedHeightOffset = height * 0.75f;
switch (mount.getDefinition().entityType()) {
@ -105,10 +111,7 @@ public final class EntityUtils {
case TRADER_LLAMA, LLAMA -> mountedHeightOffset = height * 0.6f;
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
COMMAND_BLOCK_MINECART -> mountedHeightOffset = 0;
case BOAT, CHEST_BOAT -> {
boolean isBamboo = ((BoatEntity) mount).getVariant() == 8;
mountedHeightOffset = isBamboo ? 0.25f : -0.1f;
}
case BAMBOO_RAFT, BAMBOO_CHEST_RAFT -> mountedHeightOffset = 0.25f;
case HOGLIN, ZOGLIN -> {
boolean isBaby = mount.getFlag(EntityFlag.BABY);
mountedHeightOffset = height - (isBaby ? 0.2f : 0.15f);
@ -174,15 +177,6 @@ public final class EntityUtils {
float yOffset = mountedHeightOffset + heightOffset;
float zOffset = 0;
switch (mount.getDefinition().entityType()) {
case BOAT -> {
// Without the X offset, more than one entity on a boat is stacked on top of each other
if (moreThanOneEntity) {
xOffset = rider ? 0.2f : -0.6f;
if (passenger instanceof AnimalEntity) {
xOffset += 0.2f;
}
}
}
case CAMEL -> {
zOffset = 0.5f;
if (moreThanOneEntity) {
@ -201,7 +195,6 @@ public final class EntityUtils {
}
}
}
case CHEST_BOAT -> xOffset = 0.15F;
case CHICKEN -> zOffset = -0.1f;
case TRADER_LLAMA, LLAMA -> zOffset = -0.3f;
case TEXT_DISPLAY -> {
@ -217,6 +210,17 @@ public final class EntityUtils {
}
}
}
if (mount instanceof ChestBoatEntity) {
xOffset = 0.15F;
} else if (mount instanceof BoatEntity) {
// Without the X offset, more than one entity on a boat is stacked on top of each other
if (moreThanOneEntity) {
xOffset = rider ? 0.2f : -0.6f;
if (passenger instanceof AnimalEntity) {
xOffset += 0.2f;
}
}
}
/*
* Bedrock Differences
* Zoglin & Hoglin seem to be taller in Bedrock edition
@ -231,13 +235,19 @@ public final class EntityUtils {
}
switch (mount.getDefinition().entityType()) {
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
COMMAND_BLOCK_MINECART, BOAT, CHEST_BOAT -> yOffset -= mount.getDefinition().height() * 0.5f;
COMMAND_BLOCK_MINECART -> yOffset -= mount.getDefinition().height() * 0.5f;
}
switch (passenger.getDefinition().entityType()) {
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
COMMAND_BLOCK_MINECART, BOAT, CHEST_BOAT -> yOffset += passenger.getDefinition().height() * 0.5f;
COMMAND_BLOCK_MINECART -> yOffset += passenger.getDefinition().height() * 0.5f;
case FALLING_BLOCK -> yOffset += 0.5f;
}
if (mount instanceof BoatEntity) {
yOffset -= mount.getDefinition().height() * 0.5f;
}
if (passenger instanceof BoatEntity) {
yOffset += passenger.getDefinition().height() * 0.5f;
}
if (mount instanceof ArmorStandEntity armorStand) {
yOffset -= armorStand.getYOffset();
}

View file

@ -485,7 +485,7 @@ public class InventoryUtils {
}
for (int i = 0; i < data.ingredients().length; i++) {
Ingredient ingredient = data.ingredients()[i];
for (ItemStack itemStack : ingredient.getOptions()) {
for (int item : ingredient.getValues().getHolders()) { // FIXME
boolean inventoryHasItem = false;
// Iterate only over the crafting table to find this item
crafting:
@ -493,11 +493,11 @@ public class InventoryUtils {
for (int col = firstCol; col < width + firstCol; col++) {
GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1);
if (geyserItemStack.isEmpty()) {
inventoryHasItem = itemStack == null || itemStack.getId() == 0;
inventoryHasItem = item == 0;
if (inventoryHasItem) {
break crafting;
}
} else if (itemStack.equals(geyserItemStack.getItemStack(1))) {
} else if (item == geyserItemStack.getJavaId()) {
inventoryHasItem = true;
break crafting;
}
@ -522,14 +522,15 @@ public class InventoryUtils {
for (int col = firstCol; col < width + firstCol; col++) {
GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1);
Ingredient ingredient = ingredients[ingredientIndex++];
if (ingredient.getOptions().length == 0) {
int[] items = ingredient.getValues().getHolders(); // FIXME
if (items.length == 0) {
if (!geyserItemStack.isEmpty()) {
return false;
}
} else {
boolean inventoryHasItem = false;
for (ItemStack item : ingredient.getOptions()) {
if (Objects.equals(geyserItemStack.getItemStack(1), item)) {
for (int item : items) {
if (geyserItemStack.getJavaId() == item) {
inventoryHasItem = true;
break;
}