mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-27 18:59:17 +00:00
Actually fix item frame/painting entities
This commit is contained in:
@@ -37,6 +37,7 @@ import org.geysermc.geyser.entity.type.BoatEntity;
|
||||
import org.geysermc.geyser.entity.type.ChestBoatEntity;
|
||||
import org.geysermc.geyser.entity.type.CommandBlockMinecartEntity;
|
||||
import org.geysermc.geyser.entity.type.DisplayBaseEntity;
|
||||
import org.geysermc.geyser.entity.type.HangingEntity;
|
||||
import org.geysermc.geyser.entity.type.ThrowableEggEntity;
|
||||
import org.geysermc.geyser.entity.type.EnderCrystalEntity;
|
||||
import org.geysermc.geyser.entity.type.EnderEyeEntity;
|
||||
@@ -523,17 +524,17 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataTypes.BOOLEAN, (tridentEntity, entityMetadata) -> tridentEntity.setFlag(EntityFlag.ENCHANTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
|
||||
EntityDefinition<Entity> hangingEntityBase = EntityDefinition.inherited(null, entityBase)
|
||||
.addTranslator(null) // Direction
|
||||
EntityDefinition<HangingEntity> hangingEntityBase = EntityDefinition.<HangingEntity>inherited(null, entityBase)
|
||||
.addTranslator(MetadataTypes.DIRECTION, HangingEntity::setDirectionMetadata)
|
||||
.build();
|
||||
|
||||
PAINTING = EntityDefinition.<PaintingEntity>inherited(null, hangingEntityBase)
|
||||
PAINTING = EntityDefinition.inherited(PaintingEntity::new, hangingEntityBase)
|
||||
.type(EntityType.PAINTING)
|
||||
.addTranslator(MetadataTypes.PAINTING_VARIANT, PaintingEntity::setPaintingType)
|
||||
.build();
|
||||
|
||||
// Item frames are handled differently as they are blocks, not items, in Bedrock
|
||||
ITEM_FRAME = EntityDefinition.<ItemFrameEntity>inherited(null, hangingEntityBase)
|
||||
ITEM_FRAME = EntityDefinition.inherited(ItemFrameEntity::new, hangingEntityBase)
|
||||
.type(EntityType.ITEM_FRAME)
|
||||
.addTranslator(MetadataTypes.ITEM_STACK, ItemFrameEntity::setItemInFrame)
|
||||
.addTranslator(MetadataTypes.INT, ItemFrameEntity::setItemRotation)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.entity.type;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class HangingEntity extends Entity {
|
||||
|
||||
public HangingEntity(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 void setDirectionMetadata(EntityMetadata<Direction, ?> direction) {
|
||||
setDirection(direction.getValue());
|
||||
}
|
||||
|
||||
public abstract void setDirection(Direction direction);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ import java.util.UUID;
|
||||
/**
|
||||
* Item frames are an entity in Java but a block entity in Bedrock.
|
||||
*/
|
||||
public class ItemFrameEntity extends Entity {
|
||||
public class ItemFrameEntity extends HangingEntity {
|
||||
/**
|
||||
* Used for getting the Bedrock block position.
|
||||
* Blocks deal with integers whereas entities deal with floats.
|
||||
@@ -60,7 +60,7 @@ public class ItemFrameEntity extends Entity {
|
||||
/**
|
||||
* Specific block 'state' we are emulating in Bedrock.
|
||||
*/
|
||||
private final BlockDefinition blockDefinition;
|
||||
private BlockDefinition blockDefinition;
|
||||
/**
|
||||
* Rotation of item in frame.
|
||||
*/
|
||||
@@ -75,22 +75,14 @@ public class ItemFrameEntity extends Entity {
|
||||
@Getter
|
||||
private ItemStack heldItem = null;
|
||||
/**
|
||||
* Determines if this entity needs updated on the client end/
|
||||
* Determines if this entity needs to be updated on the client end.
|
||||
*/
|
||||
private boolean changed = true;
|
||||
|
||||
public ItemFrameEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, Direction direction) {
|
||||
public ItemFrameEntity(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);
|
||||
|
||||
NbtMapBuilder blockBuilder = NbtMap.builder()
|
||||
.putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame");
|
||||
NbtMapBuilder statesBuilder = NbtMap.builder()
|
||||
.putInt("facing_direction", direction.ordinal())
|
||||
.putByte("item_frame_map_bit", (byte) 0)
|
||||
.putByte("item_frame_photo_bit", (byte) 0);
|
||||
blockBuilder.put("states", statesBuilder.build());
|
||||
|
||||
blockDefinition = session.getBlockMappings().getItemFrame(blockBuilder.build());
|
||||
blockDefinition = buildBlockDefinition(Direction.SOUTH); // Default to SOUTH direction, like on Java - entity metadata should correct this when necessary
|
||||
bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ());
|
||||
|
||||
session.getItemFrameCache().put(bedrockPosition, this);
|
||||
@@ -109,6 +101,12 @@ public class ItemFrameEntity extends Entity {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirection(Direction direction) {
|
||||
blockDefinition = buildBlockDefinition(direction);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
public void setItemInFrame(EntityMetadata<ItemStack, ?> entityMetadata) {
|
||||
if (entityMetadata.getValue() != null) {
|
||||
this.heldItem = entityMetadata.getValue();
|
||||
@@ -222,6 +220,18 @@ public class ItemFrameEntity extends Entity {
|
||||
return InventoryUtils.isEmpty(heldItem) && session.getPlayerInventory().getItemInHand(hand).isEmpty() ? InteractionResult.PASS : InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
private BlockDefinition buildBlockDefinition(Direction direction) {
|
||||
NbtMapBuilder blockBuilder = NbtMap.builder()
|
||||
.putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame");
|
||||
NbtMapBuilder statesBuilder = NbtMap.builder()
|
||||
.putInt("facing_direction", direction.ordinal())
|
||||
.putByte("item_frame_map_bit", (byte) 0)
|
||||
.putByte("item_frame_photo_bit", (byte) 0);
|
||||
blockBuilder.put("states", statesBuilder.build());
|
||||
|
||||
return session.getBlockMappings().getItemFrame(blockBuilder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the Java entity ID of an item frame from its Bedrock position.
|
||||
* @param position position of item frame in Bedrock.
|
||||
|
||||
@@ -38,13 +38,13 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PaintingEntity extends Entity {
|
||||
public class PaintingEntity extends HangingEntity {
|
||||
private static final double OFFSET = -0.46875;
|
||||
private final Direction direction;
|
||||
private int paintingId = -1; // Ideally this would be the default painting Java uses in their metadata, but seems to depend on the current paintings loaded in the registry
|
||||
private Direction direction = Direction.SOUTH; // Default to SOUTH direction, like on Java - entity metadata should correct this when necessary
|
||||
|
||||
public PaintingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, Direction direction) {
|
||||
public PaintingEntity(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);
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,11 +52,31 @@ public class PaintingEntity extends Entity {
|
||||
// Wait until we get the metadata needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
updatePainting();
|
||||
}
|
||||
|
||||
public void setPaintingType(ObjectEntityMetadata<Holder<PaintingVariant>> entityMetadata) {
|
||||
if (!entityMetadata.getValue().isId()) {
|
||||
return;
|
||||
}
|
||||
PaintingType type = session.getRegistryCache().registry(JavaRegistries.PAINTING_VARIANT).byId(entityMetadata.getValue().id());
|
||||
paintingId = entityMetadata.getValue().id();
|
||||
updatePainting();
|
||||
}
|
||||
|
||||
private void updatePainting() {
|
||||
if (paintingId == -1) {
|
||||
return;
|
||||
} else if (valid) {
|
||||
despawnEntity();
|
||||
}
|
||||
|
||||
PaintingType type = session.getRegistryCache().registry(JavaRegistries.PAINTING_VARIANT).byId(paintingId);
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
AddPaintingPacket addPaintingPacket = new AddPaintingPacket();
|
||||
addPaintingPacket.setUniqueEntityId(geyserId);
|
||||
addPaintingPacket.setRuntimeEntityId(geyserId);
|
||||
|
||||
@@ -31,8 +31,6 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.FallingBlockEntity;
|
||||
import org.geysermc.geyser.entity.type.FishingHookEntity;
|
||||
import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||
import org.geysermc.geyser.entity.type.PaintingEntity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@@ -42,7 +40,6 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.EnvironmentUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.ProjectileData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.WardenData;
|
||||
@@ -102,13 +99,6 @@ public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEnti
|
||||
if (packet.getType() == EntityType.FALLING_BLOCK) {
|
||||
entity = new FallingBlockEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(),
|
||||
position, motion, yaw, pitch, headYaw, ((FallingBlockData) packet.getData()).getId());
|
||||
} else if (packet.getType() == EntityType.ITEM_FRAME || packet.getType() == EntityType.GLOW_ITEM_FRAME) {
|
||||
// Item frames need the hanging direction
|
||||
entity = new ItemFrameEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(),
|
||||
definition, position, motion, yaw, pitch, headYaw, (Direction) packet.getData());
|
||||
} else if (packet.getType() == EntityType.PAINTING) {
|
||||
entity = new PaintingEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(),
|
||||
definition, position, motion, yaw, pitch, headYaw, (Direction) packet.getData());
|
||||
} else if (packet.getType() == EntityType.FISHING_BOBBER) {
|
||||
// Fishing bobbers need the owner for the line
|
||||
int ownerEntityId = ((ProjectileData) packet.getData()).getOwnerId();
|
||||
|
||||
Reference in New Issue
Block a user