9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-30 04:19:27 +00:00

Seat Type

This commit is contained in:
iqtester
2025-05-12 11:27:52 -04:00
parent c069be10ae
commit 4c6a073a96
24 changed files with 678 additions and 50 deletions

View File

@@ -0,0 +1,15 @@
package net.momirealms.craftengine.bukkit.entity.data;
import net.momirealms.craftengine.bukkit.util.Reflections;
public class PlayerData<T> extends LivingEntityData<T> {
public static final PlayerData<Object> Pose = new PlayerData<>(6, EntityDataValue.Serializers$POSE, Reflections.instance$Pose$STANDING);
public static final PlayerData<Byte> Skin = new PlayerData<>(17, EntityDataValue.Serializers$BYTE, (byte) 0);
public static final PlayerData<Byte> Hand = new PlayerData<>(18, EntityDataValue.Serializers$BYTE, (byte) 0);
public static final PlayerData<Object> LShoulder = new PlayerData<>(19, EntityDataValue.Serializers$COMPOUND_TAG, Reflections.instance$CompoundTag$Empty);
public static final PlayerData<Object> RShoulder = new PlayerData<>(20, EntityDataValue.Serializers$COMPOUND_TAG, Reflections.instance$CompoundTag$Empty);
public PlayerData(int id, Object serializer, T defaultValue) {
super(id, serializer, defaultValue);
}
}

View File

@@ -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<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
private final Vector<WeakReference<Entity>> seats = new Vector<>();
private final Map<Integer, BukkitSeatEntity> 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<Entity> 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> 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);
}
}

View File

@@ -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");

View File

@@ -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);
}
}

View File

@@ -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> 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();
}
}

View File

@@ -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);
}
}

View File

@@ -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<Object> 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<Object> 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<String> 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);
}
}
}

View File

@@ -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<String, Object> properties = (Multimap<String, Object>) Reflections.method$GameProfile$getProperties.invoke(npcProfile);
properties.putAll((Multimap<String, Object>) 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<Object> 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<String> arguments) {
return null;
}
}
}

View File

@@ -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<String> 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);
}
}
}

View File

@@ -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);

View File

@@ -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<Command
}
}))
.handler(context -> {
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());
});
}

View File

@@ -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));
}

View File

@@ -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);
}
});
}

View File

@@ -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<Integer, EntityPacketHandler> 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;
}
}