From 4c6a073a9680f76d8615791364ad40ad8963c751 Mon Sep 17 00:00:00 2001 From: iqtester Date: Mon, 12 May 2025 11:27:52 -0400 Subject: [PATCH] Seat Type --- .../bukkit/entity/data/PlayerData.java | 15 ++ .../entity/furniture/BukkitFurniture.java | 43 +++-- .../furniture/BukkitFurnitureManager.java | 12 +- .../furniture/hitbox/BukkitHitBoxTypes.java | 11 +- .../furniture/seat/BukkitSeatEntity.java | 74 ++++++++ .../furniture/seat/BukkitSeatTypes.java | 12 ++ .../entity/furniture/seat/CrawlSeat.java | 168 ++++++++++++++++++ .../bukkit/entity/furniture/seat/LaySeat.java | 102 +++++++++++ .../bukkit/entity/furniture/seat/SitSeat.java | 110 ++++++++++++ .../bukkit/plugin/BukkitCraftEngine.java | 2 + .../DebugGetBlockInternalIdCommand.java | 11 +- .../plugin/network/BukkitNetworkManager.java | 4 + .../plugin/network/PacketConsumers.java | 8 +- .../plugin/user/BukkitServerPlayer.java | 13 ++ .../default/configuration/furniture.yml | 2 +- .../core/entity/furniture/AbstractSeat.java | 39 ++++ .../core/entity/furniture/HitBoxFactory.java | 6 +- .../core/entity/furniture/Seat.java | 21 +-- .../core/entity/furniture/SeatFactory.java | 8 + .../core/entity/furniture/SeatType.java | 42 +++++ .../core/entity/player/Player.java | 5 + .../core/entity/seat/SeatEntity.java | 14 ++ .../core/registry/BuiltInRegistries.java | 4 + .../craftengine/core/registry/Registries.java | 2 + 24 files changed, 678 insertions(+), 50 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/PlayerData.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatEntity.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatTypes.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/CrawlSeat.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/LaySeat.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/SitSeat.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractSeat.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatFactory.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatType.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/seat/SeatEntity.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/PlayerData.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/PlayerData.java new file mode 100644 index 000000000..23f822ae3 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/PlayerData.java @@ -0,0 +1,15 @@ +package net.momirealms.craftengine.bukkit.entity.data; + +import net.momirealms.craftengine.bukkit.util.Reflections; + +public class PlayerData extends LivingEntityData { + public static final PlayerData Pose = new PlayerData<>(6, EntityDataValue.Serializers$POSE, Reflections.instance$Pose$STANDING); + public static final PlayerData Skin = new PlayerData<>(17, EntityDataValue.Serializers$BYTE, (byte) 0); + public static final PlayerData Hand = new PlayerData<>(18, EntityDataValue.Serializers$BYTE, (byte) 0); + public static final PlayerData LShoulder = new PlayerData<>(19, EntityDataValue.Serializers$COMPOUND_TAG, Reflections.instance$CompoundTag$Empty); + public static final PlayerData RShoulder = new PlayerData<>(20, EntityDataValue.Serializers$COMPOUND_TAG, Reflections.instance$CompoundTag$Empty); + + public PlayerData(int id, Object serializer, T defaultValue) { + super(id, serializer, defaultValue); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index 6c8c3d4d3..5b1458d9f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -3,22 +3,27 @@ package net.momirealms.craftengine.bukkit.entity.furniture; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import net.momirealms.craftengine.bukkit.entity.BukkitEntity; +import net.momirealms.craftengine.bukkit.entity.furniture.seat.BukkitSeatEntity; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.entity.furniture.*; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.ArrayUtils; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuaternionUtils; import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.collision.AABB; import org.bukkit.Location; -import org.bukkit.attribute.Attribute; -import org.bukkit.entity.*; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,7 +55,7 @@ public class BukkitFurniture implements Furniture { private final boolean hasExternalModel; // seats private final Set occupiedSeats = Collections.synchronizedSet(new HashSet<>()); - private final Vector> seats = new Vector<>(); + private final Map seats = Collections.synchronizedMap(new HashMap<>()); // cached spawn packet private Object cachedSpawnPacket; private Object cachedMinimizedSpawnPacket; @@ -190,24 +195,13 @@ public class BukkitFurniture implements Furniture { if (entity != null) entity.destroy(); } - for (WeakReference r : this.seats) { - Entity entity = r.get(); - if (entity == null) continue; - for (Entity passenger : entity.getPassengers()) { - entity.removePassenger(passenger); - } - entity.remove(); - } - this.seats.clear(); + destroySeats(); } @Override public void destroySeats() { - for (WeakReference entity : this.seats) { - Entity e = entity.get(); - if (e != null) { - e.remove(); - } + for (BukkitSeatEntity seat : this.seats.values()) { + seat.remove(); } this.seats.clear(); } @@ -295,7 +289,10 @@ public class BukkitFurniture implements Furniture { @Override public void spawnSeatEntityForPlayer(net.momirealms.craftengine.core.entity.player.Player player, Seat seat) { - spawnSeatEntityForPlayer((Player) player.platformPlayer(), seat); + net.momirealms.craftengine.core.entity.Entity e = seat.spawn(player, this); + BukkitSeatEntity seatEntity = (BukkitSeatEntity) e; + this.seats.put(e.entityID(), seatEntity); + player.setSeat(seatEntity); } @Override @@ -353,7 +350,7 @@ public class BukkitFurniture implements Furniture { } } - private Location calculateSeatLocation(Seat seat) { + public Location calculateSeatLocation(Seat seat) { Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate().transform(new Vector3f(seat.offset())); double yaw = seat.yaw() + this.location.getYaw(); if (yaw < -180) yaw += 360; @@ -362,4 +359,12 @@ public class BukkitFurniture implements Furniture { newLocation.add(offset.x, offset.y + 0.6, -offset.z); return newLocation; } + + public BukkitSeatEntity seatByEntityId(int id) { + return this.seats.get(id); + } + + public void removeSeatEntity(int id) { + this.seats.remove(id); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index e154d1e17..1bb8fed98 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.bukkit.entity.furniture; +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBox; +import net.momirealms.craftengine.bukkit.entity.furniture.seat.BukkitSeatEntity; import net.momirealms.craftengine.bukkit.nms.CollisionEntity; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; @@ -321,11 +323,19 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { protected void tryLeavingSeat(@NotNull Player player, @NotNull Entity vehicle) { Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER); if (baseFurniture == null) return; - vehicle.remove(); BukkitFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture); if (furniture == null) { + vehicle.remove(); return; } + BukkitSeatEntity seatEntity = furniture.seatByEntityId(vehicle.getEntityId()); + if (seatEntity == null) vehicle.remove(); + else { + seatEntity.dismount(BukkitAdaptors.adapt(player)); + seatEntity.remove(); + furniture.removeSeatEntity(vehicle.getEntityId()); + } + String vector3f = vehicle.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING); if (vector3f == null) { plugin.logger().warn("Failed to get vector3f for player " + player.getName() + "'s seat"); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java index dda752638..05b0ea0cf 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java @@ -4,12 +4,17 @@ import net.momirealms.craftengine.core.entity.furniture.HitBoxTypes; public class BukkitHitBoxTypes extends HitBoxTypes { - public static void init() {} - - static { + public static void init() { register(INTERACTION, InteractionHitBox.FACTORY); register(SHULKER, ShulkerHitBox.FACTORY); register(HAPPY_GHAST, HappyGhastHitBox.FACTORY); register(CUSTOM, CustomHitBox.FACTORY); } + + static { + //register(INTERACTION, InteractionHitBox.FACTORY); + //register(SHULKER, ShulkerHitBox.FACTORY); + //register(HAPPY_GHAST, HappyGhastHitBox.FACTORY); + //register(CUSTOM, CustomHitBox.FACTORY); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatEntity.java new file mode 100644 index 000000000..f11dd3469 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatEntity.java @@ -0,0 +1,74 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.seat; + +import net.momirealms.craftengine.bukkit.world.BukkitWorld; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.entity.seat.SeatEntity; +import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.world.World; +import org.bukkit.entity.Entity; + +import java.lang.ref.WeakReference; + +public abstract class BukkitSeatEntity extends SeatEntity { + + private final WeakReference entity; + + public BukkitSeatEntity(Entity entity) { + this.entity = new WeakReference<>(entity); + } + + @Override + public void dismount(Player from) { + from.setSeat(null); + } + + @Override + public double x() { + return literalObject().getLocation().getX(); + } + + @Override + public double y() { + return literalObject().getLocation().getY(); + } + + @Override + public double z() { + return literalObject().getLocation().getZ(); + } + + @Override + public void tick() { + } + + @Override + public int entityID() { + return literalObject().getEntityId(); + } + + @Override + public float getXRot() { + return literalObject().getLocation().getYaw(); + } + + @Override + public float getYRot() { + return literalObject().getLocation().getPitch(); + } + + @Override + public World world() { + return new BukkitWorld(literalObject().getWorld()); + } + + @Override + public Direction getDirection() { + return Direction.NORTH; + } + + @Override + public org.bukkit.entity.Entity literalObject() { + return this.entity.get(); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatTypes.java new file mode 100644 index 000000000..31ccc875c --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/BukkitSeatTypes.java @@ -0,0 +1,12 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.seat; + +import net.momirealms.craftengine.core.entity.furniture.SeatType; + +public class BukkitSeatTypes extends SeatType { + + public static void init() { + register(SIT, SitSeat.FACTORY); + register(LAY, LaySeat.FACTORY); + register(CRAWL, CrawlSeat.FACTORY); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/CrawlSeat.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/CrawlSeat.java new file mode 100644 index 000000000..99f74c7fd --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/CrawlSeat.java @@ -0,0 +1,168 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.seat; + +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; +import net.momirealms.craftengine.bukkit.entity.data.ShulkerData; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; +import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; +import net.momirealms.craftengine.bukkit.util.EntityUtils; +import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.entity.Entity; +import net.momirealms.craftengine.core.entity.furniture.AbstractSeat; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.Seat; +import net.momirealms.craftengine.core.entity.furniture.SeatFactory; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.bukkit.Location; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.Pose; +import org.bukkit.persistence.PersistentDataType; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +public class CrawlSeat extends AbstractSeat { + public static final SeatFactory FACTORY = new Factory(); + private static final List visualData = new ArrayList<>(); + private final boolean limitPlayerRotation; + + static { + ShulkerData.NoGravity.addEntityDataIfNotDefaultValue(true, visualData); + ShulkerData.Silent.addEntityDataIfNotDefaultValue(true, visualData); + ShulkerData.MobFlags.addEntityDataIfNotDefaultValue((byte) 0x01, visualData); + ShulkerData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, visualData); + } + + public CrawlSeat(Vector3f offset, float yaw, boolean limitPlayerRotation) { + super(offset, yaw); + this.limitPlayerRotation = limitPlayerRotation; + } + + @Override + public Entity spawn(Player player, Furniture furniture) { + return spawn((org.bukkit.entity.Player) player.platformPlayer(), furniture); + } + + public Entity spawn(org.bukkit.entity.Player player, Furniture furniture) { + Location location = ((LoadedFurniture)furniture).calculateSeatLocation(this); + + int visualId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + List packets = new ArrayList<>(); + packets.add(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(visualId, UUID.randomUUID(), location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw(), + Reflections.instance$EntityType$SHULKER, 0, Reflections.instance$Vec3$Zero, 0)); + packets.add(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(visualId, List.copyOf(visualData))); + Object bundle = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets); + BukkitAdaptors.adapt(player).sendPacket(bundle, true); + + org.bukkit.entity.Entity seatEntity = this.limitPlayerRotation ? + EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location.subtract(0,0.9875,0) : location.subtract(0,0.990625,0), EntityType.ARMOR_STAND, entity -> { + ArmorStand armorStand = (ArmorStand) entity; + if (VersionHelper.isOrAbove1_21_3()) { + Objects.requireNonNull(armorStand.getAttribute(Attribute.MAX_HEALTH)).setBaseValue(0.01); + } else { + LegacyAttributeUtils.setMaxHealth(armorStand); + } + armorStand.setSmall(true); + armorStand.setInvisible(true); + armorStand.setSilent(true); + armorStand.setInvulnerable(true); + armorStand.setArms(false); + armorStand.setCanTick(false); + armorStand.setAI(false); + armorStand.setGravity(false); + armorStand.setPersistent(false); + armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, furniture.baseEntityId()); + armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, this.offset().x + ", " + this.offset().y + ", " + this.offset().z); + }) : + EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location : location.subtract(0,0.25,0), EntityType.ITEM_DISPLAY, entity -> { + ItemDisplay itemDisplay = (ItemDisplay) entity; + itemDisplay.setPersistent(false); + itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, furniture.baseEntityId()); + itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, this.offset().x + ", " + this.offset().y + ", " + this.offset().z); + }); + seatEntity.addPassenger(player); + // Todo 调查一下,位置y的变化是为了什么,可能是为了让玩家做下去之后的位置是seatlocation的位置 + BukkitCraftEngine.instance().scheduler().sync().runLater(() -> player.setPose(Pose.SWIMMING, true), + 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); + + return new CrawlEntity(seatEntity, visualId); + // Todo 检测版本实现潜影贝缩小 + 找到合适的位置保持玩家的姿势 + 潜影贝骑乘展示实体 + } + + private static class CrawlEntity extends BukkitSeatEntity { + private final int visual; + + public CrawlEntity(org.bukkit.entity.Entity entity, int visual) { + super(entity); + this.visual = visual; + } + + @Override + public void sync(Player to) { + org.bukkit.entity.Entity entity = this.literalObject(); + for (org.bukkit.entity.Entity passenger : entity.getPassengers()) { + if (passenger instanceof org.bukkit.entity.Player) { + try { + Object serverPlayer = FastNMS.INSTANCE.method$CraftEntity$getHandle(passenger); + Reflections.method$Entity$refreshEntityData.invoke(serverPlayer, to.serverPlayer()); + } catch (Exception e) { + BukkitCraftEngine.instance().logger().warn("Failed to sync player pose", e); + } + } + } + } + + @Override + public void dismount(Player from) { + super.dismount(from); + ((org.bukkit.entity.Player) from.platformPlayer()).setPose(Pose.STANDING, false); + try { + @SuppressWarnings("Confusing primitive array argument to var-arg method PrimitiveArrayArgumentToVariableArgMethod") + Object packet = Reflections.constructor$ClientboundRemoveEntitiesPacket.newInstance(new int[]{visual}); + from.sendPacket(packet, true); + } catch (Exception e) { + BukkitCraftEngine.instance().logger().warn("Failed to send remove entity packet", e); + } + } + + @Override + public void remove() { + org.bukkit.entity.Entity entity = this.literalObject(); + if (entity == null) return; + + for (org.bukkit.entity.Entity passenger : entity.getPassengers()) { + entity.removePassenger(passenger); + if (passenger instanceof org.bukkit.entity.Player p) { + dismount(BukkitAdaptors.adapt(p)); + } + } + entity.remove(); + } + + @Override + public Key type() { + return Key.of("craftengine", "crawl"); + } + } + + public static class Factory implements SeatFactory { + + @Override + public Seat create(List args) { + if (args.size() == 1) return new CrawlSeat(MiscUtils.getAsVector3f(args.get(0), "seats"), 0, false); + return new CrawlSeat(MiscUtils.getAsVector3f(args.get(0), "seats"), Float.parseFloat(args.get(1)), true); + } + } +} \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/LaySeat.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/LaySeat.java new file mode 100644 index 000000000..f606a46dc --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/LaySeat.java @@ -0,0 +1,102 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.seat; + +import com.google.common.collect.ForwardingMultimap; +import com.google.common.collect.Multimap; +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; +import net.momirealms.craftengine.bukkit.entity.BukkitEntity; +import net.momirealms.craftengine.bukkit.entity.data.ShulkerData; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; +import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.util.EntityUtils; +import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.entity.Entity; +import net.momirealms.craftengine.core.entity.furniture.AbstractSeat; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.Seat; +import net.momirealms.craftengine.core.entity.furniture.SeatFactory; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.Pose; +import org.bukkit.persistence.PersistentDataType; +import org.joml.Vector3f; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +public class LaySeat extends AbstractSeat { + public static final SeatFactory FACTORY = new Factory(); + + public LaySeat(Vector3f offset, float yaw) { + super(offset, yaw); + } + + @Override + @SuppressWarnings("unchecked") + public Entity spawn(Player serverPlayer, Furniture furniture) { + Location location = ((LoadedFurniture)furniture).calculateSeatLocation(this); + org.bukkit.entity.Player player = (org.bukkit.entity.Player) serverPlayer.platformPlayer(); + + Object npc; + try { + Object server = Reflections.method$MinecraftServer$getServer.invoke(null); + Object level = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld()); + Object npcProfile = Reflections.constructor$GameProfile.newInstance(UUID.randomUUID(), player.getName()); + Object pProfile = Reflections.method$ServerPlayer$getGameProfile.invoke(serverPlayer.serverPlayer()); + Multimap properties = (Multimap) Reflections.method$GameProfile$getProperties.invoke(npcProfile); + properties.putAll((Multimap) Reflections.method$GameProfile$getProperties.invoke(pProfile)); + Object information = Reflections.method$ServerPlayer$clientInformation.invoke(serverPlayer.serverPlayer()); + npc = Reflections.constructor$ServerPlayer.newInstance(server, level, npcProfile, information); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to create NPC", e); + } + + return null; + } + + private static class LayEntity extends BukkitSeatEntity { + private final WeakReference npc; + + public LayEntity(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity npc) { + super(entity); + this.npc = new WeakReference<>(npc); + } + + @Override + public void sync(Player to) { + + } + + @Override + public void remove() { + + } + + @Override + public Key type() { + return Key.of("craftengine", "lay"); + } + } + + public static class Factory implements SeatFactory { + + @Override + public Seat create(List arguments) { + return null; + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/SitSeat.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/SitSeat.java new file mode 100644 index 000000000..0e1ef4994 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/seat/SitSeat.java @@ -0,0 +1,110 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.seat; + +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; +import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; +import net.momirealms.craftengine.bukkit.util.EntityUtils; +import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; +import net.momirealms.craftengine.core.entity.Entity; +import net.momirealms.craftengine.core.entity.furniture.AbstractSeat; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.Seat; +import net.momirealms.craftengine.core.entity.furniture.SeatFactory; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.bukkit.Location; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.persistence.PersistentDataType; +import org.joml.Vector3f; + +import java.util.List; +import java.util.Objects; + +public class SitSeat extends AbstractSeat { + public static final SeatFactory FACTORY = new Factory(); + private final boolean limitPlayerRotation; + + public SitSeat(Vector3f offset, float yaw, boolean limitPlayerRotation) { + super(offset, yaw); + this.limitPlayerRotation = limitPlayerRotation; + } + + @Override + public Entity spawn(Player player, Furniture furniture) { + return spawn((org.bukkit.entity.Player) player.platformPlayer(), furniture); + } + + public Entity spawn(org.bukkit.entity.Player player, Furniture furniture) { + Location location = ((LoadedFurniture)furniture).calculateSeatLocation(this); + org.bukkit.entity.Entity seatEntity = this.limitPlayerRotation ? + EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location.subtract(0,0.9875,0) : location.subtract(0,0.990625,0), EntityType.ARMOR_STAND, entity -> { + ArmorStand armorStand = (ArmorStand) entity; + if (VersionHelper.isOrAbove1_21_3()) { + Objects.requireNonNull(armorStand.getAttribute(Attribute.MAX_HEALTH)).setBaseValue(0.01); + } else { + LegacyAttributeUtils.setMaxHealth(armorStand); + } + armorStand.setSmall(true); + armorStand.setInvisible(true); + armorStand.setSilent(true); + armorStand.setInvulnerable(true); + armorStand.setArms(false); + armorStand.setCanTick(false); + armorStand.setAI(false); + armorStand.setGravity(false); + armorStand.setPersistent(false); + armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, furniture.baseEntityId()); + armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, this.offset().x + ", " + this.offset().y + ", " + this.offset().z); + }) : + EntityUtils.spawnEntity(player.getWorld(), VersionHelper.isOrAbove1_20_2() ? location : location.subtract(0,0.25,0), EntityType.ITEM_DISPLAY, entity -> { + ItemDisplay itemDisplay = (ItemDisplay) entity; + itemDisplay.setPersistent(false); + itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, furniture.baseEntityId()); + itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, this.offset().x + ", " + this.offset().y + ", " + this.offset().z); + }); + seatEntity.addPassenger(player); + return new SitEntity(seatEntity); + } + + private static class SitEntity extends BukkitSeatEntity { + + public SitEntity(org.bukkit.entity.Entity entity) { + super(entity); + } + + @Override + public void sync(Player to) {} + + @Override + public void remove() { + org.bukkit.entity.Entity entity = this.literalObject(); + if (entity == null) return; + for (org.bukkit.entity.Entity passenger : entity.getPassengers()) { + entity.removePassenger(passenger); + if (passenger instanceof org.bukkit.entity.Player p) { + BukkitAdaptors.adapt(p).setSeat(null); + } + } + entity.remove(); + } + + @Override + public Key type() { + return Key.of("craftengine", "sit") ; + } + } + + public static class Factory implements SeatFactory { + + @Override + public Seat create(List args) { + if (args.size() == 1) return new SitSeat(MiscUtils.getAsVector3f(args.get(0), "seats"), 0, false); + return new SitSeat(MiscUtils.getAsVector3f(args.get(0), "seats"), Float.parseFloat(args.get(1)), true); + } + } +} \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index d00647089..90203365a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -8,6 +8,7 @@ import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes; import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager; +import net.momirealms.craftengine.bukkit.entity.furniture.seat.BukkitSeatTypes; import net.momirealms.craftengine.bukkit.font.BukkitFontManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors; @@ -179,6 +180,7 @@ public class BukkitCraftEngine extends CraftEngine { BukkitItemBehaviors.init(); BukkitHitBoxTypes.init(); PacketConsumers.initEntities(RegistryUtils.currentEntityTypeRegistrySize()); + BukkitSeatTypes.init(); super.packManager = new BukkitPackManager(this); super.senderFactory = new BukkitSenderFactory(this); super.itemManager = new BukkitItemManager(this); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugGetBlockInternalIdCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugGetBlockInternalIdCommand.java index ac1e9ae7b..7e1a63eea 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugGetBlockInternalIdCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugGetBlockInternalIdCommand.java @@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; import net.momirealms.craftengine.core.plugin.command.FlagKeys; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.entity.Pose; import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.cloud.Command; import org.incendo.cloud.context.CommandContext; @@ -35,10 +37,13 @@ public class DebugGetBlockInternalIdCommand extends BukkitCommandFeature { + Player player = (Player) context.sender(); + if (player.hasFixedPose()) player.setPose(Pose.STANDING, false); + else player.setPose(Pose.SWIMMING, true); String data = context.get("id"); - ImmutableBlockState state = BlockStateParser.deserialize(data); - if (state == null) return; - context.sender().sendMessage(BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState().handle()).toString()); + //ImmutableBlockState state = BlockStateParser.deserialize(data); + //if (state == null) return; + //context.sender().sendMessage(BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState().handle()).toString()); }); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 21a2b347d..98a7df2ac 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -301,6 +301,10 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes return this.onlineUsers.get(player.getUniqueId()); } + public NetWorkUser getOnlineUser(UUID uuid) { + return onlineUsers.get(uuid); + } + public Channel getChannel(Player player) { return (Channel) FastNMS.INSTANCE.field$Player$connection$connection$channel(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index ea715b3b9..cf6ef4dbc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntList; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslationArgument; +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptBreakEvent; import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent; @@ -35,6 +36,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.entity.seat.SeatEntity; import net.momirealms.craftengine.core.font.FontManager; import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult; import net.momirealms.craftengine.core.item.CustomItem; @@ -1642,9 +1644,9 @@ public class PacketConsumers { LocationUtils.toBlockPos(hitResult.blockPos()) ); } else { - furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> { - if (furniture.tryOccupySeat(seatPos)) { - furniture.spawnSeatEntityForPlayer(serverPlayer, seatPos); + furniture.findFirstAvailableSeat(entityId).ifPresent(seat -> { + if (furniture.tryOccupySeat(seat)) { + furniture.spawnSeatEntityForPlayer(serverPlayer, seat); } }); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 3a25e446c..88cda7af2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -23,6 +23,7 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.player.GameMode; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.entity.seat.SeatEntity; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; @@ -108,6 +109,8 @@ public class BukkitServerPlayer extends Player { private double cachedInteractionRange; // cooldown data private CooldownData cooldownData; + // cache seat + private SeatEntity seatEntity; private final Map entityTypeView = new ConcurrentHashMap<>(); @@ -964,4 +967,14 @@ public class BukkitServerPlayer extends Player { public CooldownData cooldown() { return this.cooldownData; } + + @Override + public void setSeat(SeatEntity seatEntity) { + this.seatEntity = seatEntity; + } + + @Override + public SeatEntity seat() { + return this.seatEntity; + } } diff --git a/common-files/src/main/resources/resources/default/configuration/furniture.yml b/common-files/src/main/resources/resources/default/configuration/furniture.yml index 35b568623..5e3018767 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture.yml @@ -36,7 +36,7 @@ items: interactive: true interaction-entity: true seats: - - 0,0,-0.1 0 + - 0,0,-0.1 0 crawl - 1,0,-0.1 0 loot: template: default:loot_table/furniture diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractSeat.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractSeat.java new file mode 100644 index 000000000..f05a6ae4d --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractSeat.java @@ -0,0 +1,39 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import org.joml.Vector3f; + +import java.util.Objects; + +public abstract class AbstractSeat implements Seat{ + protected final Vector3f offset; + protected final float yaw; + + public AbstractSeat(Vector3f offset, float yaw) { + this.offset = offset; + this.yaw = yaw; + } + + @Override + public Vector3f offset() { + return offset; + } + + @Override + public float yaw() { + return yaw; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AbstractSeat seat)) return false; + return Float.compare(yaw, seat.yaw()) == 0 && offset.equals(seat.offset()); + } + + @Override + public int hashCode() { + int result = Objects.hash(offset); + result = 31 * result + Float.hashCode(yaw); + return result; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxFactory.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxFactory.java index 3720eb9bd..2779a5d6c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxFactory.java @@ -13,11 +13,7 @@ public interface HitBoxFactory { static Seat[] getSeats(Map arguments) { List seats = (List) arguments.getOrDefault("seats", List.of()); return seats.stream() - .map(arg -> { - String[] split = arg.split(" "); - if (split.length == 1) return new Seat(MiscUtils.getAsVector3f(split[0], "seats"), 0, false); - return new Seat(MiscUtils.getAsVector3f(split[0], "seats"), Float.parseFloat(split[1]), true); - }) + .map(SeatType::fromString) .toArray(Seat[]::new); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Seat.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Seat.java index 885333703..d0f3eadd3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Seat.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Seat.java @@ -1,23 +1,14 @@ package net.momirealms.craftengine.core.entity.furniture; +import net.momirealms.craftengine.core.entity.Entity; +import net.momirealms.craftengine.core.entity.player.Player; import org.joml.Vector3f; -import java.util.Objects; +public interface Seat { -public record Seat(Vector3f offset, float yaw, boolean limitPlayerRotation) { + Entity spawn(Player player, Furniture furniture); - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Seat seat)) return false; - return Float.compare(yaw, seat.yaw) == 0 && Objects.equals(offset, seat.offset) && limitPlayerRotation == seat.limitPlayerRotation; - } + Vector3f offset(); - @Override - public int hashCode() { - int result = Objects.hashCode(offset); - result = 31 * result + Float.hashCode(yaw); - result = 31 * result + Boolean.hashCode(limitPlayerRotation); - return result; - } + float yaw(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatFactory.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatFactory.java new file mode 100644 index 000000000..34b41577d --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatFactory.java @@ -0,0 +1,8 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import java.util.List; + +public interface SeatFactory { + + Seat create(List args); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatType.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatType.java new file mode 100644 index 000000000..a049595d7 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/SeatType.java @@ -0,0 +1,42 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import com.google.common.collect.Lists; +import net.momirealms.craftengine.core.plugin.locale.LocalizedException; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceKey; + +import java.util.List; + +public class SeatType { + public static final Key SIT = Key.of("craftengine:sit"); + public static final Key LAY = Key.of("craftengine:lay"); + public static final Key CRAWL = Key.of("craftengine:crawl"); + + public static void register(Key key, SeatFactory factory) { + Holder.Reference holder =((WritableRegistry) BuiltInRegistries.SEAT_FACTORY) + .registerForHolder(new ResourceKey<>(Registries.SEAT_FACTORY.location(), key)); + holder.bindValue(factory); + } + + public static Seat fromString(String s) { + List split = Lists.newArrayList(s.split(" ")); + int last = split.size() - 1; + Key type = SIT; + SeatFactory factory; + try { + Float.parseFloat(split.get(last)); + } catch (NullPointerException | NumberFormatException e) { + type = Key.withDefaultNamespace(split.get(last), "craftengine"); + split.remove(last); + } + factory = BuiltInRegistries.SEAT_FACTORY.getValue(type); + if (factory == null) { + throw new LocalizedException("warning.config.furniture.hitbox.invalid_type"); + } + return factory.create(split); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index e0b2d0394..51c141612 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.entity.player; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.entity.AbstractEntity; +import net.momirealms.craftengine.core.entity.seat.SeatEntity; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.context.CooldownData; import net.momirealms.craftengine.core.plugin.network.NetWorkUser; @@ -140,4 +141,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract void clearPotionEffects(); public abstract CooldownData cooldown(); + + public abstract void setSeat(SeatEntity seatEntity); + + public abstract SeatEntity seat(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/seat/SeatEntity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/seat/SeatEntity.java new file mode 100644 index 000000000..ccb0f1694 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/seat/SeatEntity.java @@ -0,0 +1,14 @@ +package net.momirealms.craftengine.core.entity.seat; + +import net.momirealms.craftengine.core.entity.AbstractEntity; +import net.momirealms.craftengine.core.entity.Entity; +import net.momirealms.craftengine.core.entity.player.Player; + +public abstract class SeatEntity extends AbstractEntity { + + public abstract void sync(Player to); + + public abstract void dismount(Player from); + + public abstract void remove(); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java index a28c42fe9..e09b61f34 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.PropertyFactory; import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory; +import net.momirealms.craftengine.core.entity.furniture.SeatFactory; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe; import net.momirealms.craftengine.core.item.recipe.RecipeFactory; @@ -56,6 +57,9 @@ public class BuiltInRegistries { public static final Registry> EVENT_FUNCTION_FACTORY = createRegistry(Registries.EVENT_FUNCTION_FACTORY); public static final Registry> EVENT_CONDITION_FACTORY = createRegistry(Registries.EVENT_CONDITION_FACTORY); public static final Registry> PLAYER_SELECTOR_FACTORY = createRegistry(Registries.PLAYER_SELECTOR_FACTORY); + public static final Registry>> PLAYER_BLOCK_FUNCTION_FACTORY = createRegistry(Registries.PLAYER_BLOCK_FUNCTION_FACTORY); + public static final Registry>> PLAYER_BLOCK_CONDITION_FACTORY = createRegistry(Registries.PLAYER_BLOCK_CONDITION_FACTORY); + public static final Registry SEAT_FACTORY = createRegistry(Registries.SEAT_FACTORY); private static Registry createRegistry(ResourceKey> key) { return new MappedRegistry<>(key); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java index 5d8ed2868..305556136 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.PropertyFactory; import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory; +import net.momirealms.craftengine.core.entity.furniture.SeatFactory; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe; import net.momirealms.craftengine.core.item.recipe.RecipeFactory; @@ -57,4 +58,5 @@ public class Registries { public static final ResourceKey>> EVENT_FUNCTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_function_factory")); public static final ResourceKey>> EVENT_CONDITION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_condition_factory")); public static final ResourceKey>> PLAYER_SELECTOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_selector")); + public static final ResourceKey> SEAT_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("seat_factory")); }