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:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user