mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 22:45:04 +01:00
Boat changes applied
This commit is contained in:
parent
e2f40569f8
commit
93d96ef5a4
14 changed files with 178 additions and 99 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -89,6 +89,7 @@ public class BedrockLevelSoundEventTranslator extends PacketTranslator<LevelSoun
|
|||
Hand.MAIN_HAND,
|
||||
0, 0, 0,
|
||||
false,
|
||||
false,
|
||||
session.getWorldCache().nextPredictionSequence());
|
||||
session.sendDownstreamGamePacket(blockPacket);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue