mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
优化座椅机制
This commit is contained in:
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.api;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||||
|
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeatManager;
|
||||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
@@ -18,6 +19,7 @@ import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextPar
|
|||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.world.World;
|
import net.momirealms.craftengine.core.world.World;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -159,8 +161,7 @@ public final class CraftEngineFurniture {
|
|||||||
* @return is seat or not
|
* @return is seat or not
|
||||||
*/
|
*/
|
||||||
public static boolean isSeat(@NotNull Entity entity) {
|
public static boolean isSeat(@NotNull Entity entity) {
|
||||||
Integer baseEntityId = entity.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
return entity.getPersistentDataContainer().has(BukkitSeatManager.SEAT_KEY);
|
||||||
return baseEntityId != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,9 +183,12 @@ public final class CraftEngineFurniture {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static BukkitFurniture getLoadedFurnitureBySeat(@NotNull Entity seat) {
|
public static BukkitFurniture getLoadedFurnitureBySeat(@NotNull Entity seat) {
|
||||||
Integer baseEntityId = seat.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
if (isSeat(seat)) {
|
||||||
if (baseEntityId == null) return null;
|
CompoundTag seatExtraData = BukkitSeatManager.instance().getSeatExtraData(seat);
|
||||||
return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntityId);
|
int entityId = seatExtraData.getInt("entity_id");
|
||||||
|
BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.momirealms.craftengine.bukkit.api.event;
|
package net.momirealms.craftengine.bukkit.api.event;
|
||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
||||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -15,15 +16,23 @@ public final class FurnitureInteractEvent extends PlayerEvent implements Cancell
|
|||||||
private final BukkitFurniture furniture;
|
private final BukkitFurniture furniture;
|
||||||
private final InteractionHand hand;
|
private final InteractionHand hand;
|
||||||
private final Location interactionPoint;
|
private final Location interactionPoint;
|
||||||
|
private final HitBox hitBox;
|
||||||
|
|
||||||
public FurnitureInteractEvent(@NotNull Player player,
|
public FurnitureInteractEvent(@NotNull Player player,
|
||||||
@NotNull BukkitFurniture furniture,
|
@NotNull BukkitFurniture furniture,
|
||||||
@NotNull InteractionHand hand,
|
@NotNull InteractionHand hand,
|
||||||
@NotNull Location interactionPoint) {
|
@NotNull Location interactionPoint,
|
||||||
|
@NotNull HitBox hitBox) {
|
||||||
super(player);
|
super(player);
|
||||||
this.furniture = furniture;
|
this.furniture = furniture;
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
this.interactionPoint = interactionPoint;
|
this.interactionPoint = interactionPoint;
|
||||||
|
this.hitBox = hitBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public HitBox hitBox() {
|
||||||
|
return hitBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
|||||||
public static final Key ATTACHED_STEM_BLOCK = Key.from("craftengine:attached_stem_block");
|
public static final Key ATTACHED_STEM_BLOCK = Key.from("craftengine:attached_stem_block");
|
||||||
public static final Key CHIME_BLOCK = Key.from("craftengine:chime_block");
|
public static final Key CHIME_BLOCK = Key.from("craftengine:chime_block");
|
||||||
public static final Key BUDDING_BLOCK = Key.from("craftengine:budding_block");
|
public static final Key BUDDING_BLOCK = Key.from("craftengine:budding_block");
|
||||||
|
public static final Key SEAT_BLOCK = Key.from("craftengine:seat_block");
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||||
@@ -84,5 +85,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
|||||||
register(ATTACHED_STEM_BLOCK, AttachedStemBlockBehavior.FACTORY);
|
register(ATTACHED_STEM_BLOCK, AttachedStemBlockBehavior.FACTORY);
|
||||||
register(CHIME_BLOCK, ChimeBlockBehavior.FACTORY);
|
register(CHIME_BLOCK, ChimeBlockBehavior.FACTORY);
|
||||||
register(BUDDING_BLOCK, BuddingBlockBehavior.FACTORY);
|
register(BUDDING_BLOCK, BuddingBlockBehavior.FACTORY);
|
||||||
|
register(SEAT_BLOCK, SeatBlockBehavior.FACTORY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes;
|
||||||
|
import net.momirealms.craftengine.bukkit.block.entity.SeatBlockEntity;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||||
|
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||||
|
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||||
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
|
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||||
|
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||||
|
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||||
|
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||||
|
import net.momirealms.craftengine.core.block.properties.Property;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
|
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||||
|
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||||
|
import net.momirealms.craftengine.core.world.BlockPos;
|
||||||
|
import net.momirealms.craftengine.core.world.CEWorld;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior {
|
||||||
|
public static final Factory FACTORY = new Factory();
|
||||||
|
private final Property<HorizontalDirection> directionProperty;
|
||||||
|
private final SeatConfig[] seats;
|
||||||
|
|
||||||
|
public SeatBlockBehavior(CustomBlock customBlock, Property<HorizontalDirection> directionProperty, SeatConfig[] seats) {
|
||||||
|
super(customBlock);
|
||||||
|
this.seats = seats;
|
||||||
|
this.directionProperty = directionProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
||||||
|
return new SeatBlockEntity(pos, state, this.seats);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends BlockEntity> BlockEntityType<T> blockEntityType(ImmutableBlockState state) {
|
||||||
|
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property<HorizontalDirection> directionProperty() {
|
||||||
|
return this.directionProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) {
|
||||||
|
BukkitServerPlayer player = (BukkitServerPlayer) context.getPlayer();
|
||||||
|
if (player == null || player.isSecondaryUseActive()) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
player.swingHand(context.getHand());
|
||||||
|
CEWorld world = context.getLevel().storageWorld();
|
||||||
|
BlockEntity blockEntity = world.getBlockEntityAtIfLoaded(context.getClickedPos());
|
||||||
|
if (!(blockEntity instanceof SeatBlockEntity seatBlockEntity)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
if (seatBlockEntity.spawnSeat(player)) {
|
||||||
|
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||||
|
} else {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory implements BlockBehaviorFactory {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||||
|
Property<HorizontalDirection> directionProperty = null;
|
||||||
|
Property<?> facing = block.getProperty("facing");
|
||||||
|
if (facing != null && facing.valueClass() == HorizontalDirection.class) {
|
||||||
|
directionProperty = (Property<HorizontalDirection>) facing;
|
||||||
|
}
|
||||||
|
return new SeatBlockBehavior(block, directionProperty, SeatConfig.fromObj(arguments.get("seats")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ public class SimpleParticleBlockBehavior extends BukkitBlockBehavior implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
public <T extends BlockEntity> BlockEntityType<T> blockEntityType(ImmutableBlockState state) {
|
||||||
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SIMPLE_PARTICLE);
|
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SIMPLE_PARTICLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class SimpleStorageBlockBehavior extends BukkitBlockBehavior implements E
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
public <T extends BlockEntity> BlockEntityType<T> blockEntityType(ImmutableBlockState state) {
|
||||||
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SIMPLE_STORAGE);
|
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SIMPLE_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
|
||||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||||
@@ -47,7 +46,7 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T extends BlockBehavior> Optional<T> getAs(Class<T> tClass) {
|
public <T> Optional<T> getAs(Class<T> tClass) {
|
||||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||||
if (tClass.isInstance(behavior)) {
|
if (tClass.isInstance(behavior)) {
|
||||||
return Optional.of((T) behavior);
|
return Optional.of((T) behavior);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class WallTorchParticleBlockBehavior extends BukkitBlockBehavior implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
public <T extends BlockEntity> BlockEntityType<T> blockEntityType(ImmutableBlockState state) {
|
||||||
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.WALL_TORCH_PARTICLE);
|
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.WALL_TORCH_PARTICLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityTypeKeys;
|
|||||||
import net.momirealms.craftengine.core.block.entity.BlockEntityTypes;
|
import net.momirealms.craftengine.core.block.entity.BlockEntityTypes;
|
||||||
|
|
||||||
public class BukkitBlockEntityTypes extends BlockEntityTypes {
|
public class BukkitBlockEntityTypes extends BlockEntityTypes {
|
||||||
public static final BlockEntityType<SimpleStorageBlockEntity> SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new);
|
public static final BlockEntityType<SimpleStorageBlockEntity> SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE);
|
||||||
public static final BlockEntityType<SimpleParticleBlockEntity> SIMPLE_PARTICLE = register(BlockEntityTypeKeys.SIMPLE_PARTICLE, SimpleParticleBlockEntity::new);
|
public static final BlockEntityType<SimpleParticleBlockEntity> SIMPLE_PARTICLE = register(BlockEntityTypeKeys.SIMPLE_PARTICLE);
|
||||||
public static final BlockEntityType<WallTorchParticleBlockEntity> WALL_TORCH_PARTICLE = register(BlockEntityTypeKeys.WALL_TORCH_PARTICLE, WallTorchParticleBlockEntity::new);
|
public static final BlockEntityType<WallTorchParticleBlockEntity> WALL_TORCH_PARTICLE = register(BlockEntityTypeKeys.WALL_TORCH_PARTICLE);
|
||||||
|
public static final BlockEntityType<SeatBlockEntity> SEAT = register(BlockEntityTypeKeys.SEAT);
|
||||||
|
|
||||||
private BukkitBlockEntityTypes() {}
|
private BukkitBlockEntityTypes() {}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.block.entity;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.block.behavior.SeatBlockBehavior;
|
||||||
|
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat;
|
||||||
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
|
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||||
|
import net.momirealms.craftengine.core.block.properties.Property;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatOwner;
|
||||||
|
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||||
|
import net.momirealms.craftengine.core.world.BlockPos;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class SeatBlockEntity extends BlockEntity implements SeatOwner {
|
||||||
|
private final Seat<SeatBlockEntity>[] seats;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState, SeatConfig[] seats) {
|
||||||
|
super(BukkitBlockEntityTypes.SEAT, pos, blockState);
|
||||||
|
this.seats = new Seat[seats.length];
|
||||||
|
for (int i = 0; i < seats.length; i++) {
|
||||||
|
this.seats[i] = new BukkitSeat<>(this, seats[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveCustomData(CompoundTag data) {
|
||||||
|
data.putString("type", "seat_block_entity");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preRemove() {
|
||||||
|
for (Seat<SeatBlockEntity> seat : this.seats) {
|
||||||
|
seat.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean spawnSeat(Player player) {
|
||||||
|
Optional<SeatBlockBehavior> seatBehavior = super.blockState.behavior().getAs(SeatBlockBehavior.class);
|
||||||
|
if (seatBehavior.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float yRot = 0;
|
||||||
|
Property<HorizontalDirection> directionProperty = seatBehavior.get().directionProperty();
|
||||||
|
if (directionProperty != null) {
|
||||||
|
HorizontalDirection direction = super.blockState.get(directionProperty);
|
||||||
|
if (direction == HorizontalDirection.NORTH) {
|
||||||
|
yRot = 180;
|
||||||
|
} else if (direction == HorizontalDirection.EAST) {
|
||||||
|
yRot = -90;
|
||||||
|
} else if (direction == HorizontalDirection.WEST) {
|
||||||
|
yRot = 90;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Seat<SeatBlockEntity> seat : this.seats) {
|
||||||
|
if (!seat.isOccupied()) {
|
||||||
|
if (seat.spawnSeat(player, new WorldPosition(super.world.world(), super.pos.x() + 0.5, super.pos.y(), super.pos.z() + 0.5, 0, 180 - yRot))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class BukkitEntity extends AbstractEntity {
|
public class BukkitEntity extends AbstractEntity {
|
||||||
private final WeakReference<org.bukkit.entity.Entity> entity;
|
protected final WeakReference<org.bukkit.entity.Entity> entity;
|
||||||
|
|
||||||
public BukkitEntity(org.bukkit.entity.Entity entity) {
|
public BukkitEntity(org.bukkit.entity.Entity entity) {
|
||||||
this.entity = new WeakReference<>(entity);
|
this.entity = new WeakReference<>(entity);
|
||||||
|
|||||||
@@ -5,20 +5,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList;
|
|||||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
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.LocationUtils;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
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.Key;
|
||||||
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -30,7 +26,6 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class BukkitFurniture implements Furniture {
|
public class BukkitFurniture implements Furniture {
|
||||||
private final Key id;
|
|
||||||
private final CustomFurniture furniture;
|
private final CustomFurniture furniture;
|
||||||
private final CustomFurniture.Placement placement;
|
private final CustomFurniture.Placement placement;
|
||||||
private FurnitureExtraData extraData;
|
private FurnitureExtraData extraData;
|
||||||
@@ -44,13 +39,10 @@ public class BukkitFurniture implements Furniture {
|
|||||||
// cache
|
// cache
|
||||||
private final List<Integer> fakeEntityIds;
|
private final List<Integer> fakeEntityIds;
|
||||||
private final List<Integer> entityIds;
|
private final List<Integer> entityIds;
|
||||||
private final Map<Integer, HitBox> hitBoxes = new Int2ObjectArrayMap<>();
|
private final Map<Integer, BukkitHitBox> hitBoxes = new Int2ObjectArrayMap<>();
|
||||||
private final Map<Integer, AABB> aabb = new Int2ObjectArrayMap<>();
|
private final Map<Integer, HitBoxPart> hitBoxParts = new Int2ObjectArrayMap<>();
|
||||||
private final boolean minimized;
|
private final boolean minimized;
|
||||||
private final boolean hasExternalModel;
|
private final boolean hasExternalModel;
|
||||||
// seats
|
|
||||||
private final Set<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
|
|
||||||
private final Vector<WeakReference<Entity>> seats = new Vector<>();
|
|
||||||
// cached spawn packet
|
// cached spawn packet
|
||||||
private Object cachedSpawnPacket;
|
private Object cachedSpawnPacket;
|
||||||
private Object cachedMinimizedSpawnPacket;
|
private Object cachedMinimizedSpawnPacket;
|
||||||
@@ -58,37 +50,40 @@ public class BukkitFurniture implements Furniture {
|
|||||||
public BukkitFurniture(Entity baseEntity,
|
public BukkitFurniture(Entity baseEntity,
|
||||||
CustomFurniture furniture,
|
CustomFurniture furniture,
|
||||||
FurnitureExtraData extraData) {
|
FurnitureExtraData extraData) {
|
||||||
this.id = furniture.id();
|
|
||||||
this.extraData = extraData;
|
this.extraData = extraData;
|
||||||
this.baseEntityId = baseEntity.getEntityId();
|
this.baseEntityId = baseEntity.getEntityId();
|
||||||
|
|
||||||
this.location = baseEntity.getLocation();
|
this.location = baseEntity.getLocation();
|
||||||
this.baseEntity = new WeakReference<>(baseEntity);
|
this.baseEntity = new WeakReference<>(baseEntity);
|
||||||
this.furniture = furniture;
|
this.furniture = furniture;
|
||||||
this.minimized = furniture.settings().minimized();
|
this.minimized = furniture.settings().minimized();
|
||||||
|
this.placement = furniture.getValidPlacement(extraData.anchorType().orElseGet(furniture::getAnyAnchorType));
|
||||||
|
|
||||||
List<Integer> fakeEntityIds = new IntArrayList();
|
List<Integer> fakeEntityIds = new IntArrayList();
|
||||||
List<Integer> mainEntityIds = new IntArrayList();
|
List<Integer> mainEntityIds = new IntArrayList();
|
||||||
mainEntityIds.add(this.baseEntityId);
|
mainEntityIds.add(this.baseEntityId);
|
||||||
|
|
||||||
this.placement = furniture.getValidPlacement(extraData.anchorType().orElseGet(furniture::getAnyAnchorType));
|
// 绑定外部模型
|
||||||
// bind external furniture
|
|
||||||
Optional<ExternalModel> optionalExternal = placement.externalModel();
|
Optional<ExternalModel> optionalExternal = placement.externalModel();
|
||||||
if (optionalExternal.isPresent()) {
|
if (optionalExternal.isPresent()) {
|
||||||
try {
|
try {
|
||||||
optionalExternal.get().bindModel(new BukkitEntity(baseEntity));
|
optionalExternal.get().bindModel(new BukkitEntity(baseEntity));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id, e);
|
CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id(), e);
|
||||||
}
|
}
|
||||||
this.hasExternalModel = true;
|
this.hasExternalModel = true;
|
||||||
} else {
|
} else {
|
||||||
this.hasExternalModel = false;
|
this.hasExternalModel = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate();
|
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate();
|
||||||
List<Object> packets = new ArrayList<>();
|
List<Object> packets = new ArrayList<>();
|
||||||
List<Object> minimizedPackets = new ArrayList<>();
|
List<Object> minimizedPackets = new ArrayList<>();
|
||||||
List<Collider> colliders = new ArrayList<>();
|
List<Collider> colliders = new ArrayList<>(4);
|
||||||
WorldPosition position = position();
|
WorldPosition position = position();
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化家具的元素
|
||||||
for (FurnitureElement element : placement.elements()) {
|
for (FurnitureElement element : placement.elements()) {
|
||||||
int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||||
fakeEntityIds.add(entityId);
|
fakeEntityIds.add(entityId);
|
||||||
@@ -97,28 +92,41 @@ public class BukkitFurniture implements Furniture {
|
|||||||
if (this.minimized) minimizedPackets.add(packet);
|
if (this.minimized) minimizedPackets.add(packet);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (HitBox hitBox : placement.hitBoxes()) {
|
|
||||||
int[] ids = hitBox.acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet);
|
// 初始化碰撞箱
|
||||||
|
for (HitBoxConfig hitBoxConfig : this.placement.hitBoxConfigs()) {
|
||||||
|
int[] ids = hitBoxConfig.acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet);
|
||||||
|
List<HitBoxPart> aabbs = new ArrayList<>();
|
||||||
|
|
||||||
|
hitBoxConfig.initPacketsAndColliders(ids, position, conjugated, (packet, canBeMinimized) -> {
|
||||||
|
packets.add(packet);
|
||||||
|
if (this.minimized && !canBeMinimized) {
|
||||||
|
minimizedPackets.add(packet);
|
||||||
|
}
|
||||||
|
}, colliders::add, part -> {
|
||||||
|
this.hitBoxParts.put(part.entityId(), part);
|
||||||
|
aabbs.add(part);
|
||||||
|
});
|
||||||
|
|
||||||
|
BukkitHitBox hitBox = new BukkitHitBox(this, hitBoxConfig, aabbs.toArray(new HitBoxPart[0]));
|
||||||
for (int entityId : ids) {
|
for (int entityId : ids) {
|
||||||
fakeEntityIds.add(entityId);
|
fakeEntityIds.add(entityId);
|
||||||
mainEntityIds.add(entityId);
|
mainEntityIds.add(entityId);
|
||||||
this.hitBoxes.put(entityId, hitBox);
|
this.hitBoxes.put(entityId, hitBox);
|
||||||
}
|
}
|
||||||
hitBox.initPacketsAndColliders(ids, position, conjugated, (packet, canBeMinimized) -> {
|
|
||||||
packets.add(packet);
|
|
||||||
if (this.minimized && !canBeMinimized) {
|
|
||||||
minimizedPackets.add(packet);
|
|
||||||
}
|
|
||||||
}, colliders::add, this.aabb::put);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化缓存的家具包
|
||||||
try {
|
try {
|
||||||
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||||
if (this.minimized) {
|
if (this.minimized) {
|
||||||
this.cachedMinimizedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(minimizedPackets);
|
this.cachedMinimizedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(minimizedPackets);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e);
|
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.fakeEntityIds = fakeEntityIds;
|
this.fakeEntityIds = fakeEntityIds;
|
||||||
this.entityIds = mainEntityIds;
|
this.entityIds = mainEntityIds;
|
||||||
this.colliderEntities = colliders.toArray(new Collider[0]);
|
this.colliderEntities = colliders.toArray(new Collider[0]);
|
||||||
@@ -186,57 +194,25 @@ public class BukkitFurniture implements Furniture {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.baseEntity().remove();
|
this.baseEntity().remove();
|
||||||
|
this.destroyColliders();
|
||||||
|
this.destroySeats();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyColliders() {
|
||||||
for (Collider entity : this.colliderEntities) {
|
for (Collider entity : this.colliderEntities) {
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
entity.destroy();
|
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroySeats() {
|
public void destroySeats() {
|
||||||
for (WeakReference<Entity> entity : this.seats) {
|
for (HitBox hitBox : this.hitBoxes.values()) {
|
||||||
Entity e = entity.get();
|
for (Seat<HitBox> seat : hitBox.seats()) {
|
||||||
if (e != null) {
|
seat.destroy();
|
||||||
e.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.seats.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Seat> findFirstAvailableSeat(int targetEntityId) {
|
|
||||||
HitBox hitbox = hitBoxes.get(targetEntityId);
|
|
||||||
if (hitbox == null) return Optional.empty();
|
|
||||||
|
|
||||||
Seat[] seats = hitbox.seats();
|
|
||||||
if (ArrayUtils.isEmpty(seats)) return Optional.empty();
|
|
||||||
|
|
||||||
return Arrays.stream(seats)
|
|
||||||
.filter(s -> !occupiedSeats.contains(s.offset()))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeOccupiedSeat(Vector3f seat) {
|
|
||||||
return this.occupiedSeats.remove(seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryOccupySeat(Seat seat) {
|
|
||||||
if (this.occupiedSeats.contains(seat.offset())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.occupiedSeats.add(seat.offset());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -263,14 +239,14 @@ public class BukkitFurniture implements Furniture {
|
|||||||
return this.colliderEntities;
|
return this.colliderEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Override
|
||||||
public HitBox hitBoxByEntityId(int id) {
|
public @Nullable HitBox hitBoxByEntityId(int id) {
|
||||||
return this.hitBoxes.get(id);
|
return this.hitBoxes.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Override
|
||||||
public AABB aabbByEntityId(int id) {
|
public @Nullable HitBoxPart hitBoxPartByEntityId(int id) {
|
||||||
return this.aabb.get(id);
|
return this.hitBoxParts.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -280,7 +256,7 @@ public class BukkitFurniture implements Furniture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Key id() {
|
public @NotNull Key id() {
|
||||||
return this.id;
|
return this.furniture.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -293,11 +269,6 @@ public class BukkitFurniture implements Furniture {
|
|||||||
return hasExternalModel;
|
return hasExternalModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void spawnSeatEntityForPlayer(net.momirealms.craftengine.core.entity.player.Player player, Seat seat) {
|
|
||||||
spawnSeatEntityForPlayer((Player) player.platformPlayer(), seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FurnitureExtraData extraData() {
|
public FurnitureExtraData extraData() {
|
||||||
return this.extraData;
|
return this.extraData;
|
||||||
@@ -317,49 +288,4 @@ public class BukkitFurniture implements Furniture {
|
|||||||
CraftEngine.instance().logger().warn("Failed to save furniture data.", e);
|
CraftEngine.instance().logger().warn("Failed to save furniture data.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void spawnSeatEntityForPlayer(org.bukkit.entity.Player player, Seat seat) {
|
|
||||||
Location location = this.calculateSeatLocation(seat);
|
|
||||||
Entity seatEntity = seat.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, this.baseEntityId());
|
|
||||||
armorStand.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.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, this.baseEntityId());
|
|
||||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
|
||||||
});
|
|
||||||
this.seats.add(new WeakReference<>(seatEntity));
|
|
||||||
if (!seatEntity.addPassenger(player)) {
|
|
||||||
seatEntity.remove();
|
|
||||||
this.removeOccupiedSeat(seat.offset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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;
|
|
||||||
Location newLocation = this.location.clone();
|
|
||||||
newLocation.setYaw((float) yaw);
|
|
||||||
newLocation.add(offset.x, offset.y + 0.6, -offset.z);
|
|
||||||
return newLocation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBox;
|
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBoxConfig;
|
||||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
@@ -15,17 +15,13 @@ import net.momirealms.craftengine.core.entity.furniture.*;
|
|||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.sound.SoundData;
|
import net.momirealms.craftengine.core.sound.SoundData;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -37,8 +33,6 @@ import java.util.function.BiConsumer;
|
|||||||
public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||||
public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY);
|
public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY);
|
||||||
public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_EXTRA_DATA_KEY);
|
public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_EXTRA_DATA_KEY);
|
||||||
public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY);
|
|
||||||
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY);
|
|
||||||
public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION);
|
public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION);
|
||||||
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
|
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
|
||||||
public static Object NMS_COLLISION_ENTITY_TYPE = MEntityTypes.INTERACTION;
|
public static Object NMS_COLLISION_ENTITY_TYPE = MEntityTypes.INTERACTION;
|
||||||
@@ -48,7 +42,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
private final Map<Integer, BukkitFurniture> furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f);
|
private final Map<Integer, BukkitFurniture> furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f);
|
||||||
private final Map<Integer, BukkitFurniture> furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f);
|
private final Map<Integer, BukkitFurniture> furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f);
|
||||||
// Event listeners
|
// Event listeners
|
||||||
private final Listener dismountListener;
|
|
||||||
private final FurnitureEventListener furnitureEventListener;
|
private final FurnitureEventListener furnitureEventListener;
|
||||||
|
|
||||||
public static BukkitFurnitureManager instance() {
|
public static BukkitFurnitureManager instance() {
|
||||||
@@ -60,7 +53,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
instance = this;
|
instance = this;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.furnitureEventListener = new FurnitureEventListener(this);
|
this.furnitureEventListener = new FurnitureEventListener(this);
|
||||||
this.dismountListener = VersionHelper.isOrAbove1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,7 +87,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
||||||
NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? MEntityTypes.INTERACTION : MEntityTypes.OAK_BOAT;
|
NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? MEntityTypes.INTERACTION : MEntityTypes.OAK_BOAT;
|
||||||
COLLISION_ENTITY_TYPE = Config.colliderType();
|
COLLISION_ENTITY_TYPE = Config.colliderType();
|
||||||
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.javaPlugin());
|
|
||||||
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin());
|
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin());
|
||||||
if (VersionHelper.isFolia()) {
|
if (VersionHelper.isFolia()) {
|
||||||
BiConsumer<Entity, Runnable> taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {});
|
BiConsumer<Entity, Runnable> taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {});
|
||||||
@@ -129,15 +120,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
HandlerList.unregisterAll(this.dismountListener);
|
|
||||||
HandlerList.unregisterAll(this.furnitureEventListener);
|
HandlerList.unregisterAll(this.furnitureEventListener);
|
||||||
unload();
|
unload();
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
||||||
Entity vehicle = player.getVehicle();
|
|
||||||
if (vehicle != null) {
|
|
||||||
tryLeavingSeat(player, vehicle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -327,84 +311,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HitBox defaultHitBox() {
|
protected HitBoxConfig defaultHitBox() {
|
||||||
return InteractionHitBox.DEFAULT;
|
return InteractionHitBoxConfig.DEFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
protected void handleDismount(Player player, Entity entity) {
|
|
||||||
if (!isSeatCarrierType(entity)) return;
|
|
||||||
Location location = entity.getLocation();
|
|
||||||
plugin.scheduler().sync().runDelayed(() -> tryLeavingSeat(player, entity), player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("DuplicatedCode")
|
|
||||||
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) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Vector3f seatPos = ResourceConfigUtils.getAsVector3f(vector3f, "seat");
|
|
||||||
furniture.removeOccupiedSeat(seatPos);
|
|
||||||
|
|
||||||
if (player.getVehicle() != null) return;
|
|
||||||
Location vehicleLocation = vehicle.getLocation();
|
|
||||||
Location originalLocation = vehicleLocation.clone();
|
|
||||||
originalLocation.setY(furniture.location().getY());
|
|
||||||
Location targetLocation = originalLocation.clone().add(vehicleLocation.getDirection().multiply(1.1));
|
|
||||||
if (!isSafeLocation(targetLocation)) {
|
|
||||||
targetLocation = findSafeLocationNearby(originalLocation);
|
|
||||||
if (targetLocation == null) return;
|
|
||||||
}
|
|
||||||
targetLocation.setYaw(player.getLocation().getYaw());
|
|
||||||
targetLocation.setPitch(player.getLocation().getPitch());
|
|
||||||
if (VersionHelper.isFolia()) {
|
|
||||||
player.teleportAsync(targetLocation);
|
|
||||||
} else {
|
|
||||||
player.teleport(targetLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isSeatCarrierType(Entity entity) {
|
|
||||||
return (entity instanceof ArmorStand || entity instanceof ItemDisplay);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("DuplicatedCode")
|
|
||||||
private boolean isSafeLocation(Location location) {
|
|
||||||
World world = location.getWorld();
|
|
||||||
if (world == null) return false;
|
|
||||||
int x = location.getBlockX();
|
|
||||||
int y = location.getBlockY();
|
|
||||||
int z = location.getBlockZ();
|
|
||||||
if (!world.getBlockAt(x, y - 1, z).getType().isSolid()) return false;
|
|
||||||
if (!world.getBlockAt(x, y, z).isPassable()) return false;
|
|
||||||
return world.getBlockAt(x, y + 1, z).isPassable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("DuplicatedCode")
|
|
||||||
@Nullable
|
|
||||||
private Location findSafeLocationNearby(Location center) {
|
|
||||||
World world = center.getWorld();
|
|
||||||
if (world == null) return null;
|
|
||||||
int centerX = center.getBlockX();
|
|
||||||
int centerY = center.getBlockY();
|
|
||||||
int centerZ = center.getBlockZ();
|
|
||||||
for (int dx = -1; dx <= 1; dx++) {
|
|
||||||
for (int dz = -1; dz <= 1; dz++) {
|
|
||||||
if (dx == 0 && dz == 0) continue;
|
|
||||||
int x = centerX + dx;
|
|
||||||
int z = centerZ + dz;
|
|
||||||
Location nearbyLocation = new Location(world, x + 0.5, centerY, z + 0.5);
|
|
||||||
if (isSafeLocation(nearbyLocation)) return nearbyLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfig;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.HitBoxPart;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
|
import net.momirealms.craftengine.core.world.EntityHitResult;
|
||||||
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class BukkitHitBox implements HitBox {
|
||||||
|
private final Furniture furniture;
|
||||||
|
private final HitBoxConfig config;
|
||||||
|
private final HitBoxPart[] parts;
|
||||||
|
private final Seat<HitBox>[] seats;
|
||||||
|
|
||||||
|
public BukkitHitBox(Furniture furniture, HitBoxConfig config, HitBoxPart[] parts) {
|
||||||
|
this.parts = parts;
|
||||||
|
this.config = config;
|
||||||
|
this.furniture = furniture;
|
||||||
|
this.seats = createSeats(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Seat<HitBox>[] createSeats(HitBoxConfig config) {
|
||||||
|
SeatConfig[] seatConfigs = config.seats();
|
||||||
|
Seat<HitBox>[] seats = new Seat[seatConfigs.length];
|
||||||
|
for (int i = 0; i < seatConfigs.length; i++) {
|
||||||
|
seats[i] = new BukkitSeat<>(this, seatConfigs[i]);
|
||||||
|
}
|
||||||
|
return seats;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HitBoxPart[] parts() {
|
||||||
|
return this.parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HitBoxConfig config() {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Seat<HitBox>[] seats() {
|
||||||
|
return this.seats;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<EntityHitResult> clip(Vec3d min, Vec3d max) {
|
||||||
|
for (HitBoxPart hbe : this.parts) {
|
||||||
|
Optional<EntityHitResult> result = hbe.aabb().clip(min, max);
|
||||||
|
if (result.isPresent()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveCustomData(CompoundTag data) {
|
||||||
|
data.putString("type", "furniture");
|
||||||
|
data.putInt("entity_id", this.furniture.baseEntityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,24 @@
|
|||||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityDismountEvent;
|
import org.bukkit.event.entity.EntityDismountEvent;
|
||||||
|
|
||||||
public class DismountListener1_20_3 implements Listener {
|
import java.util.function.BiConsumer;
|
||||||
private final BukkitFurnitureManager manager;
|
|
||||||
|
|
||||||
public DismountListener1_20_3(final BukkitFurnitureManager manager) {
|
public class DismountListener1_20_3 implements Listener {
|
||||||
this.manager = manager;
|
private final BiConsumer<Player, Entity> consumer;
|
||||||
|
|
||||||
|
public DismountListener1_20_3(final BiConsumer<Player, Entity> consumer) {
|
||||||
|
this.consumer = consumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onDismount(EntityDismountEvent event) {
|
public void onDismount(EntityDismountEvent event) {
|
||||||
if (event.getEntity() instanceof Player player) {
|
if (event.getEntity() instanceof Player player) {
|
||||||
this.manager.handleDismount(player, event.getDismounted());
|
this.consumer.accept(player, event.getDismounted());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,15 @@ package net.momirealms.craftengine.bukkit.entity.furniture;
|
|||||||
|
|
||||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||||
import org.bukkit.entity.ArmorStand;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.ItemDisplay;
|
import org.bukkit.entity.ItemDisplay;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
|
||||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -100,35 +94,4 @@ public class FurnitureEventListener implements Listener {
|
|||||||
this.manager.handleCollisionEntityUnload(entity);
|
this.manager.handleCollisionEntityUnload(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
Entity entity = player.getVehicle();
|
|
||||||
if (entity == null) return;
|
|
||||||
if (this.manager.isSeatCarrierType(entity)) {
|
|
||||||
this.manager.tryLeavingSeat(player, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
|
||||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
Entity entity = player.getVehicle();
|
|
||||||
if (entity == null) return;
|
|
||||||
if (this.manager.isSeatCarrierType(entity)) {
|
|
||||||
this.manager.tryLeavingSeat(player, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not allow players to put item on seats
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
|
||||||
public void onInteractArmorStand(PlayerInteractAtEntityEvent event) {
|
|
||||||
Entity clicked = event.getRightClicked();
|
|
||||||
if (clicked instanceof ArmorStand armorStand) {
|
|
||||||
Integer baseFurniture = armorStand.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
|
||||||
if (baseFurniture == null) return;
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ public class BukkitHitBoxTypes extends HitBoxTypes {
|
|||||||
public static void init() {}
|
public static void init() {}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
register(INTERACTION, InteractionHitBox.FACTORY);
|
register(INTERACTION, InteractionHitBoxConfig.FACTORY);
|
||||||
register(SHULKER, ShulkerHitBox.FACTORY);
|
register(SHULKER, ShulkerHitBoxConfig.FACTORY);
|
||||||
register(HAPPY_GHAST, HappyGhastHitBox.FACTORY);
|
register(HAPPY_GHAST, HappyGhastHitBoxConfig.FACTORY);
|
||||||
register(CUSTOM, CustomHitBox.FACTORY);
|
register(CUSTOM, CustomHitBoxConfig.FACTORY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
@@ -23,13 +24,13 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class CustomHitBox extends AbstractHitBox {
|
public class CustomHitBoxConfig extends AbstractHitBoxConfig {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
private final float scale;
|
private final float scale;
|
||||||
private final EntityType entityType;
|
private final EntityType entityType;
|
||||||
private final List<Object> cachedValues = new ArrayList<>();
|
private final List<Object> cachedValues = new ArrayList<>();
|
||||||
|
|
||||||
public CustomHitBox(Seat[] seats, Vector3f position, EntityType type, float scale, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
public CustomHitBoxConfig(SeatConfig[] seats, Vector3f position, EntityType type, float scale, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
||||||
super(seats, position, false, blocksBuilding, canBeHitByProjectile);
|
super(seats, position, false, blocksBuilding, canBeHitByProjectile);
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.entityType = type;
|
this.entityType = type;
|
||||||
@@ -39,11 +40,11 @@ public class CustomHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public EntityType entityType() {
|
public EntityType entityType() {
|
||||||
return entityType;
|
return this.entityType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float scale() {
|
public float scale() {
|
||||||
return scale;
|
return this.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,7 +53,7 @@ public class CustomHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
public void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, Consumer<HitBoxPart> aabb) {
|
||||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||||
try {
|
try {
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
@@ -79,10 +80,10 @@ public class CustomHitBox extends AbstractHitBox {
|
|||||||
return new int[] {entityIdSupplier.get()};
|
return new int[] {entityIdSupplier.get()};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Factory implements HitBoxFactory {
|
public static class Factory implements HitBoxConfigFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HitBox create(Map<String, Object> arguments) {
|
public HitBoxConfig create(Map<String, Object> arguments) {
|
||||||
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
||||||
float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1), "scale");
|
float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1), "scale");
|
||||||
String type = (String) arguments.getOrDefault("entity-type", "slime");
|
String type = (String) arguments.getOrDefault("entity-type", "slime");
|
||||||
@@ -92,7 +93,7 @@ public class CustomHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", false), "can-be-hit-by-projectile");
|
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", false), "can-be-hit-by-projectile");
|
||||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||||
return new CustomHitBox(HitBoxFactory.getSeats(arguments), position, entityType, scale, blocksBuilding, canBeHitByProjectile);
|
return new CustomHitBoxConfig(SeatConfig.fromObj(arguments.get("seats")), position, entityType, scale, blocksBuilding, canBeHitByProjectile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,9 +8,11 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeH
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
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.World;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
@@ -22,13 +24,13 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class HappyGhastHitBox extends AbstractHitBox {
|
public class HappyGhastHitBoxConfig extends AbstractHitBoxConfig {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
private final double scale;
|
private final double scale;
|
||||||
private final boolean hardCollision;
|
private final boolean hardCollision;
|
||||||
private final List<Object> cachedValues = new ArrayList<>();
|
private final List<Object> cachedValues = new ArrayList<>();
|
||||||
|
|
||||||
public HappyGhastHitBox(Seat[] seats, Vector3f position, double scale, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile, boolean hardCollision) {
|
public HappyGhastHitBoxConfig(SeatConfig[] seats, Vector3f position, double scale, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile, boolean hardCollision) {
|
||||||
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.hardCollision = hardCollision;
|
this.hardCollision = hardCollision;
|
||||||
@@ -43,15 +45,20 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public double scale() {
|
public double scale() {
|
||||||
return scale;
|
return this.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hardCollision() {
|
public boolean hardCollision() {
|
||||||
return hardCollision;
|
return this.hardCollision;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initPacketsAndColliders(int[] entityIds, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
public void initPacketsAndColliders(int[] entityIds,
|
||||||
|
WorldPosition position,
|
||||||
|
Quaternionf conjugated,
|
||||||
|
BiConsumer<Object, Boolean> packets,
|
||||||
|
Consumer<Collider> collider,
|
||||||
|
Consumer<HitBoxPart> aabb) {
|
||||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||||
try {
|
try {
|
||||||
double x = position.x();
|
double x = position.x();
|
||||||
@@ -76,11 +83,11 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collider createCollider(World world, Vector3f offset, double x, double y, double z, int entityId, BiConsumer<Integer, AABB> aabb) {
|
public Collider createCollider(World world, Vector3f offset, double x, double y, double z, int entityId, Consumer<HitBoxPart> aabb) {
|
||||||
AABB ceAABB = createAABB(offset, x, y, z);
|
AABB ceAABB = createAABB(offset, x, y, z);
|
||||||
Object level = world.serverWorld();
|
Object level = world.serverWorld();
|
||||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
||||||
aabb.accept(entityId, ceAABB);
|
aabb.accept(new HitBoxPart(entityId, ceAABB, new Vec3d(x, y, z)));
|
||||||
return new BukkitCollider(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding());
|
return new BukkitCollider(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,10 +116,10 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
|||||||
return new int[] {entityIdSupplier.get()};
|
return new int[] {entityIdSupplier.get()};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Factory implements HitBoxFactory {
|
public static class Factory implements HitBoxConfigFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HitBox create(Map<String, Object> arguments) {
|
public HitBoxConfig create(Map<String, Object> arguments) {
|
||||||
if (!VersionHelper.isOrAbove1_21_6()) {
|
if (!VersionHelper.isOrAbove1_21_6()) {
|
||||||
throw new UnsupportedOperationException("HappyGhastHitBox is only supported on 1.21.6+");
|
throw new UnsupportedOperationException("HappyGhastHitBox is only supported on 1.21.6+");
|
||||||
}
|
}
|
||||||
@@ -121,8 +128,8 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
|||||||
boolean canUseOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
boolean canUseOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
||||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
||||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||||
return new HappyGhastHitBox(
|
return new HappyGhastHitBoxConfig(
|
||||||
HitBoxFactory.getSeats(arguments),
|
SeatConfig.fromObj(arguments.get("seats")),
|
||||||
ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position"),
|
ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position"),
|
||||||
scale, canUseOn, blocksBuilding, canBeHitByProjectile, hardCollision
|
scale, canUseOn, blocksBuilding, canBeHitByProjectile, hardCollision
|
||||||
);
|
);
|
||||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
import net.momirealms.craftengine.core.world.Vec3d;
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
@@ -22,15 +23,15 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class InteractionHitBox extends AbstractHitBox {
|
public class InteractionHitBoxConfig extends AbstractHitBoxConfig {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
public static final InteractionHitBox DEFAULT = new InteractionHitBox(new Seat[0], new Vector3f(), new Vector3f(1,1,1), true, false, false, false);
|
public static final InteractionHitBoxConfig DEFAULT = new InteractionHitBoxConfig(new SeatConfig[0], new Vector3f(), new Vector3f(1,1,1), true, false, false, false);
|
||||||
|
|
||||||
private final Vector3f size;
|
private final Vector3f size;
|
||||||
private final boolean responsive;
|
private final boolean responsive;
|
||||||
private final List<Object> cachedValues = new ArrayList<>();
|
private final List<Object> cachedValues = new ArrayList<>();
|
||||||
|
|
||||||
public InteractionHitBox(Seat[] seats, Vector3f position, Vector3f size, boolean responsive, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
public InteractionHitBoxConfig(SeatConfig[] seats, Vector3f position, Vector3f size, boolean responsive, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
||||||
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.responsive = responsive;
|
this.responsive = responsive;
|
||||||
@@ -40,11 +41,11 @@ public class InteractionHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean responsive() {
|
public boolean responsive() {
|
||||||
return responsive;
|
return this.responsive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3f size() {
|
public Vector3f size() {
|
||||||
return size;
|
return this.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -53,22 +54,26 @@ public class InteractionHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
public void initPacketsAndColliders(int[] entityId,
|
||||||
|
WorldPosition position,
|
||||||
|
Quaternionf conjugated,
|
||||||
|
BiConsumer<Object, Boolean> packets,
|
||||||
|
Consumer<Collider> collider,
|
||||||
|
Consumer<HitBoxPart> aabb) {
|
||||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||||
double x = position.x();
|
double x = position.x();
|
||||||
double y = position.y();
|
double y = position.y();
|
||||||
double z = position.z();
|
double z = position.z();
|
||||||
float yaw = position.xRot();
|
float yaw = position.xRot();
|
||||||
|
Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y, z - offset.z);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
entityId[0], UUID.randomUUID(), vec3d.x, vec3d.y, vec3d.z, 0, yaw,
|
||||||
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
||||||
if (canUseItemOn()) {
|
aabb.accept(new HitBoxPart(entityId[0], AABB.fromInteraction(vec3d, this.size.x, this.size.y), vec3d));
|
||||||
aabb.accept(entityId[0], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), this.size.x, this.size.y));
|
|
||||||
}
|
|
||||||
if (blocksBuilding() || this.canBeHitByProjectile()) {
|
if (blocksBuilding() || this.canBeHitByProjectile()) {
|
||||||
AABB ceAABB = AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), this.size.x, this.size.y);
|
AABB ceAABB = AABB.fromInteraction(vec3d, this.size.x, this.size.y);
|
||||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
||||||
collider.accept(new BukkitCollider(position.world().serverWorld(), nmsAABB, x, y, z, this.canBeHitByProjectile(), false, this.blocksBuilding()));
|
collider.accept(new BukkitCollider(position.world().serverWorld(), nmsAABB, x, y, z, this.canBeHitByProjectile(), false, this.blocksBuilding()));
|
||||||
}
|
}
|
||||||
@@ -88,10 +93,10 @@ public class InteractionHitBox extends AbstractHitBox {
|
|||||||
return new int[] {entityIdSupplier.get()};
|
return new int[] {entityIdSupplier.get()};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Factory implements HitBoxFactory {
|
public static class Factory implements HitBoxConfigFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HitBox create(Map<String, Object> arguments) {
|
public HitBoxConfig create(Map<String, Object> arguments) {
|
||||||
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
@@ -100,15 +105,15 @@ public class InteractionHitBox extends AbstractHitBox {
|
|||||||
width = Float.parseFloat(split[0]);
|
width = Float.parseFloat(split[0]);
|
||||||
height = Float.parseFloat(split[1]);
|
height = Float.parseFloat(split[1]);
|
||||||
} else {
|
} else {
|
||||||
width = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("width", "1"), "width");
|
width = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("width", 1), "width");
|
||||||
height = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("height", "1"), "height");
|
height = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("height", 1), "height");
|
||||||
}
|
}
|
||||||
boolean canUseOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", false), "can-use-item-on");
|
boolean canUseOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", false), "can-use-item-on");
|
||||||
boolean interactive = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("interactive", true), "interactive");
|
boolean interactive = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("interactive", true), "interactive");
|
||||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", false), "can-be-hit-by-projectile");
|
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", false), "can-be-hit-by-projectile");
|
||||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||||
return new InteractionHitBox(
|
return new InteractionHitBoxConfig(
|
||||||
HitBoxFactory.getSeats(arguments),
|
SeatConfig.fromObj(arguments.get("seats")),
|
||||||
position,
|
position,
|
||||||
new Vector3f(width, height, width),
|
new Vector3f(width, height, width),
|
||||||
interactive, canUseOn, blocksBuilding, canBeHitByProjectile
|
interactive, canUseOn, blocksBuilding, canBeHitByProjectile
|
||||||
@@ -10,6 +10,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityType
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
import net.momirealms.craftengine.core.util.*;
|
import net.momirealms.craftengine.core.util.*;
|
||||||
import net.momirealms.craftengine.core.world.Vec3d;
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
import net.momirealms.craftengine.core.world.World;
|
import net.momirealms.craftengine.core.world.World;
|
||||||
@@ -23,7 +24,7 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ShulkerHitBox extends AbstractHitBox {
|
public class ShulkerHitBoxConfig extends AbstractHitBoxConfig {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
// 1.20.6+
|
// 1.20.6+
|
||||||
private final float scale;
|
private final float scale;
|
||||||
@@ -35,7 +36,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
private final DirectionalShulkerSpawner spawner;
|
private final DirectionalShulkerSpawner spawner;
|
||||||
private final AABBCreator aabbCreator;
|
private final AABBCreator aabbCreator;
|
||||||
|
|
||||||
public ShulkerHitBox(Seat[] seats, Vector3f position, Direction direction, float scale, byte peek, boolean interactionEntity, boolean interactive, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
public ShulkerHitBoxConfig(SeatConfig[] seats, Vector3f position, Direction direction, float scale, byte peek, boolean interactionEntity, boolean interactive, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
||||||
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
@@ -65,7 +66,8 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||||
if (canUseOn) {
|
if (canUseOn) {
|
||||||
aabb.accept(entityIds[2], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), scale, shulkerHeight));
|
Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y, z - offset.z);
|
||||||
|
aabb.accept(new HitBoxPart(entityIds[2], AABB.fromInteraction(vec3d, scale, shulkerHeight), vec3d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -84,7 +86,8 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||||
if (canUseOn) {
|
if (canUseOn) {
|
||||||
aabb.accept(entityIds[2], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y - shulkerHeight + scale, z - offset.z), scale, shulkerHeight));
|
Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y - shulkerHeight + scale, z - offset.z);
|
||||||
|
aabb.accept(new HitBoxPart(entityIds[2], AABB.fromInteraction(vec3d, scale, shulkerHeight), vec3d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -113,8 +116,10 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
), true);
|
), true);
|
||||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues)), true);
|
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues)), true);
|
||||||
if (canUseOn) {
|
if (canUseOn) {
|
||||||
aabb.accept(entityIds[2], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), scale, scale));
|
Vec3d vec3d1 = new Vec3d(x + offset.x, y + offset.y, z - offset.z);
|
||||||
aabb.accept(entityIds[3], AABB.fromInteraction(new Vec3d(x + offset.x + shulkerDirection.stepX() * distance, y + offset.y, z - offset.z + shulkerDirection.stepZ() * distance), scale, scale));
|
Vec3d vec3d2 = new Vec3d(x + offset.x + shulkerDirection.stepX() * distance, y + offset.y, z - offset.z + shulkerDirection.stepZ() * distance);
|
||||||
|
aabb.accept(new HitBoxPart(entityIds[2], AABB.fromInteraction(vec3d1, scale, scale), vec3d1));
|
||||||
|
aabb.accept(new HitBoxPart(entityIds[3], AABB.fromInteraction(vec3d2, scale, scale), vec3d2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -126,11 +131,11 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collider createCollider(Direction direction, World world, Vector3f offset, double x, double y, double z, int entityId, BiConsumer<Integer, AABB> aabb) {
|
public Collider createCollider(Direction direction, World world, Vector3f offset, double x, double y, double z, int entityId, Consumer<HitBoxPart> aabb) {
|
||||||
AABB ceAABB = createAABB(direction, offset, x, y, z);
|
AABB ceAABB = createAABB(direction, offset, x, y, z);
|
||||||
Object level = world.serverWorld();
|
Object level = world.serverWorld();
|
||||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
||||||
aabb.accept(entityId, ceAABB);
|
aabb.accept(new HitBoxPart(entityId, ceAABB, new Vec3d(x, y, z)));
|
||||||
return new BukkitCollider(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding());
|
return new BukkitCollider(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +205,12 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initPacketsAndColliders(int[] entityIds, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
public void initPacketsAndColliders(int[] entityIds,
|
||||||
|
WorldPosition position,
|
||||||
|
Quaternionf conjugated,
|
||||||
|
BiConsumer<Object, Boolean> packets,
|
||||||
|
Consumer<Collider> collider,
|
||||||
|
Consumer<HitBoxPart> aabb) {
|
||||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||||
try {
|
try {
|
||||||
double x = position.x();
|
double x = position.x();
|
||||||
@@ -251,7 +261,16 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface DirectionalShulkerSpawner {
|
interface DirectionalShulkerSpawner {
|
||||||
|
|
||||||
void accept(int[] entityIds, World world, double x, double y, double z, float yaw, Vector3f offset, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb);
|
void accept(int[] entityIds,
|
||||||
|
World world,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double z,
|
||||||
|
float yaw,
|
||||||
|
Vector3f offset,
|
||||||
|
BiConsumer<Object, Boolean> packets,
|
||||||
|
Consumer<Collider> collider,
|
||||||
|
Consumer<HitBoxPart> aabb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
@@ -276,10 +295,10 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Factory implements HitBoxFactory {
|
public static class Factory implements HitBoxConfigFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HitBox create(Map<String, Object> arguments) {
|
public HitBoxConfig create(Map<String, Object> arguments) {
|
||||||
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
||||||
float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", "1"), "scale");
|
float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", "1"), "scale");
|
||||||
byte peek = (byte) ResourceConfigUtils.getAsInt(arguments.getOrDefault("peek", 0), "peek");
|
byte peek = (byte) ResourceConfigUtils.getAsInt(arguments.getOrDefault("peek", 0), "peek");
|
||||||
@@ -289,8 +308,8 @@ public class ShulkerHitBox extends AbstractHitBox {
|
|||||||
boolean canUseItemOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
boolean canUseItemOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
||||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
||||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||||
return new ShulkerHitBox(
|
return new ShulkerHitBoxConfig(
|
||||||
HitBoxFactory.getSeats(arguments),
|
SeatConfig.fromObj(arguments.get("seats")),
|
||||||
position, directionEnum,
|
position, directionEnum,
|
||||||
scale, peek, interactionEntity, interactive, canUseItemOn, blocksBuilding, canBeHitByProjectile
|
scale, peek, interactionEntity, interactive, canUseItemOn, blocksBuilding, canBeHitByProjectile
|
||||||
);
|
);
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.entity.seat;
|
||||||
|
|
||||||
|
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.core.entity.seat.Seat;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatOwner;
|
||||||
|
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||||
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
import net.momirealms.sparrow.nbt.NBT;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.entity.*;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class BukkitSeat<O extends SeatOwner> implements Seat<O> {
|
||||||
|
private final O owner;
|
||||||
|
private final SeatConfig seatConfig;
|
||||||
|
private WeakReference<Entity> entity;
|
||||||
|
|
||||||
|
public BukkitSeat(O owner, SeatConfig config) {
|
||||||
|
this.owner = owner;
|
||||||
|
this.seatConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public O owner() {
|
||||||
|
return this.owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SeatConfig config() {
|
||||||
|
return this.seatConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Entity getSeatEntity() {
|
||||||
|
return this.entity == null ? null : this.entity.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOccupied() {
|
||||||
|
Entity seatEntity = getSeatEntity();
|
||||||
|
return seatEntity != null && seatEntity.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
if (this.entity != null) {
|
||||||
|
Entity entity = this.entity.get();
|
||||||
|
if (entity != null) {
|
||||||
|
if (entity.isValid()) {
|
||||||
|
entity.remove();
|
||||||
|
}
|
||||||
|
this.entity = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float yRot() {
|
||||||
|
return this.seatConfig.yRot();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3f position() {
|
||||||
|
return this.seatConfig.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean limitPlayerRotation() {
|
||||||
|
return this.seatConfig.limitPlayerRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Location calculateSeatLocation(Location sourceLocation) {
|
||||||
|
Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - sourceLocation.getYaw()), 0).conjugate().transform(new Vector3f(this.position()));
|
||||||
|
double yaw = this.yRot() + sourceLocation.getYaw();
|
||||||
|
if (yaw < -180) yaw += 360;
|
||||||
|
Location newLocation = sourceLocation.clone();
|
||||||
|
newLocation.setYaw((float) yaw);
|
||||||
|
newLocation.add(offset.x, offset.y + 0.6, -offset.z);
|
||||||
|
return newLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean spawnSeat(net.momirealms.craftengine.core.entity.player.Player player, WorldPosition source) {
|
||||||
|
return spawnSeatEntityForPlayer((Player) player.platformPlayer(), LocationUtils.toLocation(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean spawnSeatEntityForPlayer(Player player, Location sourceLocation) {
|
||||||
|
// 移除就有的座椅
|
||||||
|
this.destroy();
|
||||||
|
// 计算座椅的位置
|
||||||
|
Location location = this.calculateSeatLocation(sourceLocation);
|
||||||
|
|
||||||
|
CompoundTag extraData = new CompoundTag();
|
||||||
|
this.owner.saveCustomData(extraData);
|
||||||
|
byte[] data;
|
||||||
|
try {
|
||||||
|
data = NBT.toBytes(extraData);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成座椅实体
|
||||||
|
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(BukkitSeatManager.SEAT_KEY, PersistentDataType.BOOLEAN, true);
|
||||||
|
armorStand.getPersistentDataContainer().set(BukkitSeatManager.SEAT_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, data);
|
||||||
|
}) :
|
||||||
|
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(BukkitSeatManager.SEAT_KEY, PersistentDataType.BOOLEAN, true);
|
||||||
|
itemDisplay.getPersistentDataContainer().set(BukkitSeatManager.SEAT_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, data);
|
||||||
|
});
|
||||||
|
if (!seatEntity.addPassenger(player)) {
|
||||||
|
seatEntity.remove();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.entity = new WeakReference<>(seatEntity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package net.momirealms.craftengine.bukkit.entity.seat;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.bukkit.entity.furniture.DismountListener1_20;
|
||||||
|
import net.momirealms.craftengine.bukkit.entity.furniture.DismountListener1_20_3;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatManager;
|
||||||
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
import net.momirealms.sparrow.nbt.NBT;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.ItemDisplay;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BukkitSeatManager implements SeatManager {
|
||||||
|
private static BukkitSeatManager instance;
|
||||||
|
public static final NamespacedKey SEAT_KEY = KeyUtils.toNamespacedKey(SeatManager.SEAT_KEY);
|
||||||
|
public static final NamespacedKey SEAT_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(SeatManager.SEAT_EXTRA_DATA_KEY);
|
||||||
|
private final BukkitCraftEngine plugin;
|
||||||
|
private final Listener dismountListener;
|
||||||
|
|
||||||
|
public BukkitSeatManager(BukkitCraftEngine plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.dismountListener = VersionHelper.isOrAbove1_20_3() ? new DismountListener1_20_3(this::handleDismount) : new DismountListener1_20(this::handleDismount);
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag getSeatExtraData(Entity entity) {
|
||||||
|
if (!isSeatEntityType(entity)) {
|
||||||
|
throw new IllegalArgumentException("Entity is not a seat");
|
||||||
|
}
|
||||||
|
byte[] bytes = entity.getPersistentDataContainer().get(SEAT_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY);
|
||||||
|
try {
|
||||||
|
return NBT.fromBytes(bytes);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to read extra data from seat", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDismount(Player player, @NotNull Entity dismounted) {
|
||||||
|
if (!isSeatEntityType(dismounted)) return;
|
||||||
|
Location location = dismounted.getLocation();
|
||||||
|
this.plugin.scheduler().sync().runDelayed(() -> tryLeavingSeat(player, dismounted), player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayedInit() {
|
||||||
|
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.javaPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disable() {
|
||||||
|
HandlerList.unregisterAll(this.dismountListener);
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
Entity vehicle = player.getVehicle();
|
||||||
|
if (vehicle != null) {
|
||||||
|
tryLeavingSeat(player, vehicle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
Entity entity = player.getVehicle();
|
||||||
|
if (entity == null) return;
|
||||||
|
if (this.isSeatEntityType(entity)) {
|
||||||
|
this.tryLeavingSeat(player, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
Entity entity = player.getVehicle();
|
||||||
|
if (entity == null) return;
|
||||||
|
if (this.isSeatEntityType(entity)) {
|
||||||
|
this.tryLeavingSeat(player, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not allow players to put item on seats
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
|
public void onInteractArmorStand(PlayerInteractAtEntityEvent event) {
|
||||||
|
Entity clicked = event.getRightClicked();
|
||||||
|
if (clicked instanceof ArmorStand armorStand) {
|
||||||
|
if (!armorStand.getPersistentDataContainer().has(SEAT_KEY)) return;
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isSeatEntityType(Entity entity) {
|
||||||
|
return (entity instanceof ArmorStand || entity instanceof ItemDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tryLeavingSeat(@NotNull Player player, @NotNull Entity seat) {
|
||||||
|
boolean isSeat = seat.getPersistentDataContainer().has(SEAT_KEY);
|
||||||
|
if (!isSeat) return;
|
||||||
|
seat.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BukkitSeatManager instance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
|||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
import net.momirealms.craftengine.core.item.CustomItem;
|
import net.momirealms.craftengine.core.item.CustomItem;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
import net.momirealms.craftengine.core.item.NetworkItemBuildContext;
|
||||||
import net.momirealms.craftengine.core.item.NetworkItemHandler;
|
import net.momirealms.craftengine.core.item.NetworkItemHandler;
|
||||||
import net.momirealms.craftengine.core.item.modifier.ArgumentsModifier;
|
import net.momirealms.craftengine.core.item.modifier.ArgumentsModifier;
|
||||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||||
@@ -209,15 +209,15 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
// 创建context
|
// 创建context
|
||||||
Tag argumentTag = wrapped.getTag(ArgumentsModifier.ARGUMENTS_TAG);
|
Tag argumentTag = wrapped.getTag(ArgumentsModifier.ARGUMENTS_TAG);
|
||||||
ItemBuildContext context;
|
NetworkItemBuildContext context;
|
||||||
if (argumentTag instanceof CompoundTag arguments) {
|
if (argumentTag instanceof CompoundTag arguments) {
|
||||||
ContextHolder.Builder builder = ContextHolder.builder();
|
ContextHolder.Builder builder = ContextHolder.builder();
|
||||||
for (Map.Entry<String, Tag> entry : arguments.entrySet()) {
|
for (Map.Entry<String, Tag> entry : arguments.entrySet()) {
|
||||||
builder.withParameter(ContextKey.direct(entry.getKey()), entry.getValue().getAsString());
|
builder.withParameter(ContextKey.direct(entry.getKey()), entry.getValue().getAsString());
|
||||||
}
|
}
|
||||||
context = ItemBuildContext.of(player, builder);
|
context = NetworkItemBuildContext.of(player, builder);
|
||||||
} else {
|
} else {
|
||||||
context = ItemBuildContext.of(player);
|
context = NetworkItemBuildContext.of(player);
|
||||||
}
|
}
|
||||||
// 准备阶段
|
// 准备阶段
|
||||||
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
|
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
|
||||||
|
|||||||
@@ -185,15 +185,15 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
|||||||
.orElseGet(CompoundTag::new);
|
.orElseGet(CompoundTag::new);
|
||||||
CompoundTag arguments = customData.getCompound(ArgumentsModifier.ARGUMENTS_TAG);
|
CompoundTag arguments = customData.getCompound(ArgumentsModifier.ARGUMENTS_TAG);
|
||||||
// 创建context
|
// 创建context
|
||||||
ItemBuildContext context;
|
NetworkItemBuildContext context;
|
||||||
if (arguments == null) {
|
if (arguments == null) {
|
||||||
context = ItemBuildContext.of(player);
|
context = NetworkItemBuildContext.of(player);
|
||||||
} else {
|
} else {
|
||||||
ContextHolder.Builder builder = ContextHolder.builder();
|
ContextHolder.Builder builder = ContextHolder.builder();
|
||||||
for (Map.Entry<String, Tag> entry : arguments.entrySet()) {
|
for (Map.Entry<String, Tag> entry : arguments.entrySet()) {
|
||||||
builder.withParameter(ContextKey.direct(entry.getKey()), entry.getValue().getAsString());
|
builder.withParameter(ContextKey.direct(entry.getKey()), entry.getValue().getAsString());
|
||||||
}
|
}
|
||||||
context = ItemBuildContext.of(player, builder);
|
context = NetworkItemBuildContext.of(player, builder);
|
||||||
}
|
}
|
||||||
// 准备阶段
|
// 准备阶段
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.momirealms.craftengine.bukkit.item.behavior;
|
|||||||
import net.momirealms.craftengine.bukkit.block.behavior.StrippableBlockBehavior;
|
import net.momirealms.craftengine.bukkit.block.behavior.StrippableBlockBehavior;
|
||||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
|
||||||
import net.momirealms.craftengine.bukkit.util.*;
|
import net.momirealms.craftengine.bukkit.util.*;
|
||||||
import net.momirealms.craftengine.bukkit.world.BukkitExistingBlock;
|
import net.momirealms.craftengine.bukkit.world.BukkitExistingBlock;
|
||||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
|||||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfig;
|
||||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
@@ -109,8 +109,8 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
|||||||
Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0);
|
Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0);
|
||||||
|
|
||||||
List<AABB> aabbs = new ArrayList<>();
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
for (HitBox hitBox : placement.hitBoxes()) {
|
for (HitBoxConfig hitBoxConfig : placement.hitBoxConfigs()) {
|
||||||
hitBox.initShapeForPlacement(finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - furnitureYaw), 0).conjugate(), aabbs::add);
|
hitBoxConfig.initShapeForPlacement(finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - furnitureYaw), 0).conjugate(), aabbs::add);
|
||||||
}
|
}
|
||||||
if (!aabbs.isEmpty()) {
|
if (!aabbs.isEmpty()) {
|
||||||
if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList(), finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z())) {
|
if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList(), finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z())) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.momirealms.craftengine.bukkit.block.entity.renderer.element.BukkitBlo
|
|||||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes;
|
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes;
|
||||||
import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager;
|
import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager;
|
||||||
|
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeatManager;
|
||||||
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
||||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||||
import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors;
|
import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors;
|
||||||
@@ -209,6 +210,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
|||||||
super.advancementManager = new BukkitAdvancementManager(this);
|
super.advancementManager = new BukkitAdvancementManager(this);
|
||||||
super.projectileManager = new BukkitProjectileManager(this);
|
super.projectileManager = new BukkitProjectileManager(this);
|
||||||
super.furnitureManager = new BukkitFurnitureManager(this);
|
super.furnitureManager = new BukkitFurnitureManager(this);
|
||||||
|
super.seatManager = new BukkitSeatManager(this);
|
||||||
super.onPluginEnable();
|
super.onPluginEnable();
|
||||||
super.compatibilityManager().onEnable();
|
super.compatibilityManager().onEnable();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ import net.momirealms.craftengine.core.plugin.config.Config;
|
|||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.incendo.cloud.Command;
|
import org.incendo.cloud.Command;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class DebugRealStateUsageCommand extends BukkitCommandFeature<CommandSender> {
|
public class DebugRealStateUsageCommand extends BukkitCommandFeature<CommandSender> {
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
|||||||
import net.momirealms.craftengine.core.advancement.network.AdvancementHolder;
|
import net.momirealms.craftengine.core.advancement.network.AdvancementHolder;
|
||||||
import net.momirealms.craftengine.core.advancement.network.AdvancementProgress;
|
import net.momirealms.craftengine.core.advancement.network.AdvancementProgress;
|
||||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.HitBoxPart;
|
||||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||||
import net.momirealms.craftengine.core.font.FontManager;
|
import net.momirealms.craftengine.core.font.FontManager;
|
||||||
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
||||||
import net.momirealms.craftengine.core.item.CustomItem;
|
import net.momirealms.craftengine.core.item.CustomItem;
|
||||||
@@ -92,7 +95,6 @@ import net.momirealms.craftengine.core.world.chunk.Palette;
|
|||||||
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
||||||
import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData;
|
import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData;
|
||||||
import net.momirealms.craftengine.core.world.chunk.packet.MCSection;
|
import net.momirealms.craftengine.core.world.chunk.packet.MCSection;
|
||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
|
||||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
import net.momirealms.sparrow.nbt.ListTag;
|
import net.momirealms.sparrow.nbt.ListTag;
|
||||||
import net.momirealms.sparrow.nbt.Tag;
|
import net.momirealms.sparrow.nbt.Tag;
|
||||||
@@ -3635,8 +3637,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
float x = buf.readFloat();
|
float x = buf.readFloat();
|
||||||
float y = buf.readFloat();
|
float y = buf.readFloat();
|
||||||
float z = buf.readFloat();
|
float z = buf.readFloat();
|
||||||
// todo 这个是错误的,这是实体的相对位置而非绝对位置
|
|
||||||
Location interactionPoint = new Location(platformPlayer.getWorld(), x, y, z);
|
|
||||||
InteractionHand hand = buf.readVarInt() == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
InteractionHand hand = buf.readVarInt() == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||||
boolean usingSecondaryAction = buf.readBoolean();
|
boolean usingSecondaryAction = buf.readBoolean();
|
||||||
if (entityId != furniture.baseEntityId()) {
|
if (entityId != furniture.baseEntityId()) {
|
||||||
@@ -3655,16 +3655,40 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo 重构家具时候注意,需要准备加载好的hitbox类,以获取hitbox坐标
|
// 先检查碰撞箱部分是否存在
|
||||||
if (!serverPlayer.canInteractPoint(new Vec3d(location.getX(), location.getY(), location.getZ()), 16d)) {
|
HitBoxPart hitBoxPart = furniture.hitBoxPartByEntityId(entityId);
|
||||||
|
if (hitBoxPart == null) return;
|
||||||
|
Vec3d pos = hitBoxPart.pos();
|
||||||
|
// 检测距离
|
||||||
|
if (!serverPlayer.canInteractPoint(pos, 16d)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 检测
|
||||||
|
Location eyeLocation = platformPlayer.getEyeLocation();
|
||||||
|
Vector direction = eyeLocation.getDirection();
|
||||||
|
Location endLocation = eyeLocation.clone();
|
||||||
|
endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange()));
|
||||||
|
Optional<EntityHitResult> result = hitBoxPart.aabb().clip(LocationUtils.toVec3d(eyeLocation), LocationUtils.toVec3d(endLocation));
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EntityHitResult hitResult = result.get();
|
||||||
|
Vec3d hitLocation = hitResult.hitLocation();
|
||||||
|
// 获取正确的交互点
|
||||||
|
Location interactionPoint = new Location(platformPlayer.getWorld(), hitLocation.x, hitLocation.y, hitLocation.z);
|
||||||
|
|
||||||
|
HitBox hitbox = furniture.hitBoxByEntityId(entityId);
|
||||||
|
if (hitbox == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FurnitureInteractEvent interactEvent = new FurnitureInteractEvent(serverPlayer.platformPlayer(), furniture, hand, interactionPoint);
|
// 触发事件
|
||||||
|
FurnitureInteractEvent interactEvent = new FurnitureInteractEvent(serverPlayer.platformPlayer(), furniture, hand, interactionPoint, hitbox);
|
||||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行事件动作
|
||||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||||
Cancellable cancellable = Cancellable.of(interactEvent::isCancelled, interactEvent::setCancelled);
|
Cancellable cancellable = Cancellable.of(interactEvent::isCancelled, interactEvent::setCancelled);
|
||||||
// execute functions
|
// execute functions
|
||||||
@@ -3681,20 +3705,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
||||||
if (serverPlayer.isSecondaryUseActive() && !itemInHand.isEmpty()) {
|
if (serverPlayer.isSecondaryUseActive() && !itemInHand.isEmpty() && hitbox.config().canUseItemOn()) {
|
||||||
// try placing another furniture above it
|
|
||||||
AABB hitBox = furniture.aabbByEntityId(entityId);
|
|
||||||
if (hitBox == null) return;
|
|
||||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||||
Location eyeLocation = platformPlayer.getEyeLocation();
|
|
||||||
Vector direction = eyeLocation.getDirection();
|
|
||||||
Location endLocation = eyeLocation.clone();
|
|
||||||
endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange()));
|
|
||||||
Optional<EntityHitResult> result = hitBox.clip(LocationUtils.toVec3d(eyeLocation), LocationUtils.toVec3d(endLocation));
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EntityHitResult hitResult = result.get();
|
|
||||||
if (optionalCustomItem.isPresent() && !optionalCustomItem.get().behaviors().isEmpty()) {
|
if (optionalCustomItem.isPresent() && !optionalCustomItem.get().behaviors().isEmpty()) {
|
||||||
for (ItemBehavior behavior : optionalCustomItem.get().behaviors()) {
|
for (ItemBehavior behavior : optionalCustomItem.get().behaviors()) {
|
||||||
if (behavior instanceof FurnitureItemBehavior) {
|
if (behavior instanceof FurnitureItemBehavior) {
|
||||||
@@ -3713,11 +3725,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (!serverPlayer.isSecondaryUseActive()) {
|
if (!serverPlayer.isSecondaryUseActive()) {
|
||||||
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
for (Seat<HitBox> seat : hitbox.seats()) {
|
||||||
if (furniture.tryOccupySeat(seatPos)) {
|
if (!seat.isOccupied()) {
|
||||||
furniture.spawnSeatEntityForPlayer(serverPlayer, seatPos);
|
seat.spawnSeat(serverPlayer, furniture.position());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import net.momirealms.craftengine.bukkit.plugin.network.payload.protocol.ClientC
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.network.payload.protocol.VisualBlockStatePacket;
|
import net.momirealms.craftengine.bukkit.plugin.network.payload.protocol.VisualBlockStatePacket;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||||
import net.momirealms.craftengine.core.plugin.network.PayloadChannelKeys;
|
|
||||||
import net.momirealms.craftengine.core.plugin.network.ModPacket;
|
import net.momirealms.craftengine.core.plugin.network.ModPacket;
|
||||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||||
|
import net.momirealms.craftengine.core.plugin.network.PayloadChannelKeys;
|
||||||
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
|
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
|
||||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public final class LocationUtils {
|
|||||||
private LocationUtils() {}
|
private LocationUtils() {}
|
||||||
|
|
||||||
public static Location toLocation(WorldPosition position) {
|
public static Location toLocation(WorldPosition position) {
|
||||||
return new Location((World) position.world().platformWorld(), position.x(), position.y(), position.z(), position.xRot(), position.yRot());
|
return new Location((World) position.world().platformWorld(), position.x(), position.y(), position.z(), position.yRot(), position.xRot());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorldPosition toWorldPosition(Location location) {
|
public static WorldPosition toWorldPosition(Location location) {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ resource-pack:
|
|||||||
method-2: false # This will increase the resource pack size by 64KB
|
method-2: false # This will increase the resource pack size by 64KB
|
||||||
method-3: false # This will increase the resource pack size by 0.67MB
|
method-3: false # This will increase the resource pack size by 0.67MB
|
||||||
method-4: false
|
method-4: false
|
||||||
method-5: true # This can reduce the resource pack size, also it prevents some software from extracting it
|
method-5: true # This will reduce the resource pack size, also it prevents some software from extracting it
|
||||||
method-6: false # This will increase the resource pack size by a certain percentage
|
method-6: false # This will increase the resource pack size by a certain percentage
|
||||||
method-7: false
|
method-7: false
|
||||||
# Create incorrect crc data
|
# Create incorrect crc data
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ items:
|
|||||||
- type: bouncing_block
|
- type: bouncing_block
|
||||||
bounce-height: 0.66
|
bounce-height: 0.66
|
||||||
sync-player-position: false
|
sync-player-position: false
|
||||||
|
- type: seat_block
|
||||||
|
seats:
|
||||||
|
- 0,0,0
|
||||||
state:
|
state:
|
||||||
state: white_bed[facing=west,occupied=false,part=foot]
|
state: white_bed[facing=west,occupied=false,part=foot]
|
||||||
entity-renderer:
|
entity-renderer:
|
||||||
@@ -79,6 +82,9 @@ items:
|
|||||||
- type: sofa_block
|
- type: sofa_block
|
||||||
- type: bouncing_block
|
- type: bouncing_block
|
||||||
bounce-height: 0.66
|
bounce-height: 0.66
|
||||||
|
- type: seat_block
|
||||||
|
seats:
|
||||||
|
- 0,0,0 0
|
||||||
states:
|
states:
|
||||||
properties:
|
properties:
|
||||||
facing:
|
facing:
|
||||||
|
|||||||
@@ -646,7 +646,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
|||||||
// 绑定行为
|
// 绑定行为
|
||||||
for (ImmutableBlockState state : states) {
|
for (ImmutableBlockState state : states) {
|
||||||
if (isEntityBlock) {
|
if (isEntityBlock) {
|
||||||
state.setBlockEntityType(entityBlockBehavior.blockEntityType());
|
state.setBlockEntityType(entityBlockBehavior.blockEntityType(state));
|
||||||
}
|
}
|
||||||
state.setBehavior(blockBehavior);
|
state.setBehavior(blockBehavior);
|
||||||
int internalId = state.customBlockState().registryId();
|
int internalId = state.customBlockState().registryId();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import java.util.concurrent.Callable;
|
|||||||
public abstract class BlockBehavior {
|
public abstract class BlockBehavior {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends BlockBehavior> Optional<T> getAs(Class<T> tClass) {
|
public <T> Optional<T> getAs(Class<T> tClass) {
|
||||||
if (tClass.isInstance(this)) {
|
if (tClass.isInstance(this)) {
|
||||||
return Optional.of((T) this);
|
return Optional.of((T) this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,15 @@ import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
|
|||||||
import net.momirealms.craftengine.core.world.BlockPos;
|
import net.momirealms.craftengine.core.world.BlockPos;
|
||||||
import net.momirealms.craftengine.core.world.CEWorld;
|
import net.momirealms.craftengine.core.world.CEWorld;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
public interface EntityBlockBehavior {
|
public interface EntityBlockBehavior {
|
||||||
|
|
||||||
<T extends BlockEntity> BlockEntityType<T> blockEntityType();
|
@Nullable
|
||||||
|
<T extends BlockEntity> BlockEntityType<T> blockEntityType(ImmutableBlockState state);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state);
|
BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state);
|
||||||
|
|
||||||
default <T extends BlockEntity> BlockEntityTicker<T> createSyncBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType<T> blockEntityType) {
|
default <T extends BlockEntity> BlockEntityTicker<T> createSyncBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType<T> blockEntityType) {
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ package net.momirealms.craftengine.core.block.entity;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
public record BlockEntityType<T extends BlockEntity>(Key id, BlockEntity.Factory<T> factory) {
|
public record BlockEntityType<T extends BlockEntity>(Key id) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,5 @@ public final class BlockEntityTypeKeys {
|
|||||||
public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage");
|
public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage");
|
||||||
public static final Key SIMPLE_PARTICLE = Key.of("craftengine:simple_particle");
|
public static final Key SIMPLE_PARTICLE = Key.of("craftengine:simple_particle");
|
||||||
public static final Key WALL_TORCH_PARTICLE = Key.of("craftengine:wall_torch_particle");
|
public static final Key WALL_TORCH_PARTICLE = Key.of("craftengine:wall_torch_particle");
|
||||||
|
public static final Key SEAT = Key.of("craftengine:seat");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import net.momirealms.craftengine.core.util.ResourceKey;
|
|||||||
|
|
||||||
public abstract class BlockEntityTypes {
|
public abstract class BlockEntityTypes {
|
||||||
|
|
||||||
public static <T extends BlockEntity> BlockEntityType<T> register(Key id, BlockEntity.Factory<T> factory) {
|
public static <T extends BlockEntity> BlockEntityType<T> register(Key id) {
|
||||||
BlockEntityType<T> type = new BlockEntityType<>(id, factory);
|
BlockEntityType<T> type = new BlockEntityType<>(id);
|
||||||
((WritableRegistry<BlockEntityType<?>>) BuiltInRegistries.BLOCK_ENTITY_TYPE)
|
((WritableRegistry<BlockEntityType<?>>) BuiltInRegistries.BLOCK_ENTITY_TYPE)
|
||||||
.register(ResourceKey.create(Registries.BLOCK_ENTITY_TYPE.location(), id), type);
|
.register(ResourceKey.create(Registries.BLOCK_ENTITY_TYPE.location(), id), type);
|
||||||
return type;
|
return type;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.core.block.properties.type;
|
package net.momirealms.craftengine.core.block.properties.type;
|
||||||
|
|
||||||
public enum DoorHinge {
|
public enum DoorHinge {
|
||||||
LEFT, RIGHT
|
LEFT,
|
||||||
|
RIGHT
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.core.block.properties.type;
|
package net.momirealms.craftengine.core.block.properties.type;
|
||||||
|
|
||||||
public enum DoubleBlockHalf {
|
public enum DoubleBlockHalf {
|
||||||
UPPER, LOWER
|
LOWER,
|
||||||
|
UPPER
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.core.block.properties.type;
|
package net.momirealms.craftengine.core.block.properties.type;
|
||||||
|
|
||||||
public enum SingleBlockHalf {
|
public enum SingleBlockHalf {
|
||||||
TOP, BOTTOM
|
BOTTOM,
|
||||||
|
TOP
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
this.byId.clear();
|
this.byId.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract HitBox defaultHitBox();
|
protected abstract HitBoxConfig defaultHitBox();
|
||||||
|
|
||||||
protected abstract FurnitureElement.Builder furnitureElementBuilder();
|
protected abstract FurnitureElement.Builder furnitureElementBuilder();
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add hitboxes
|
// add hitboxes
|
||||||
List<HitBox> hitboxes = ResourceConfigUtils.parseConfigAsList(placementArguments.get("hitboxes"), HitBoxTypes::fromMap);
|
List<HitBoxConfig> hitboxes = ResourceConfigUtils.parseConfigAsList(placementArguments.get("hitboxes"), HitBoxTypes::fromMap);
|
||||||
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
|
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
|
||||||
hitboxes = List.of(defaultHitBox());
|
hitboxes = List.of(defaultHitBox());
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
placements.put(anchorType, new CustomFurniture.Placement(
|
placements.put(anchorType, new CustomFurniture.Placement(
|
||||||
anchorType,
|
anchorType,
|
||||||
elements.toArray(new FurnitureElement[0]),
|
elements.toArray(new FurnitureElement[0]),
|
||||||
hitboxes.toArray(new HitBox[0]),
|
hitboxes.toArray(new HitBoxConfig[0]),
|
||||||
ResourceConfigUtils.getOrDefault(ruleSection.get("rotation"), o -> RotationRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), RotationRule.ANY),
|
ResourceConfigUtils.getOrDefault(ruleSection.get("rotation"), o -> RotationRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), RotationRule.ANY),
|
||||||
ResourceConfigUtils.getOrDefault(ruleSection.get("alignment"), o -> AlignmentRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), AlignmentRule.CENTER),
|
ResourceConfigUtils.getOrDefault(ruleSection.get("alignment"), o -> AlignmentRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), AlignmentRule.CENTER),
|
||||||
externalModel,
|
externalModel,
|
||||||
@@ -175,7 +175,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
placements.put(anchorType, new CustomFurniture.Placement(
|
placements.put(anchorType, new CustomFurniture.Placement(
|
||||||
anchorType,
|
anchorType,
|
||||||
elements.toArray(new FurnitureElement[0]),
|
elements.toArray(new FurnitureElement[0]),
|
||||||
hitboxes.toArray(new HitBox[0]),
|
hitboxes.toArray(new HitBoxConfig[0]),
|
||||||
RotationRule.ANY,
|
RotationRule.ANY,
|
||||||
AlignmentRule.CENTER,
|
AlignmentRule.CENTER,
|
||||||
externalModel,
|
externalModel,
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
public abstract class AbstractHitBox implements HitBox {
|
public abstract class AbstractHitBoxConfig implements HitBoxConfig {
|
||||||
protected final Seat[] seats;
|
protected final SeatConfig[] seats;
|
||||||
protected final Vector3f position;
|
protected final Vector3f position;
|
||||||
protected final boolean canUseItemOn;
|
protected final boolean canUseItemOn;
|
||||||
protected final boolean blocksBuilding;
|
protected final boolean blocksBuilding;
|
||||||
protected final boolean canBeHitByProjectile;
|
protected final boolean canBeHitByProjectile;
|
||||||
|
|
||||||
public AbstractHitBox(Seat[] seats, Vector3f position, boolean canUseItemOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
public AbstractHitBoxConfig(SeatConfig[] seats, Vector3f position, boolean canUseItemOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
||||||
this.seats = seats;
|
this.seats = seats;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.canUseItemOn = canUseItemOn;
|
this.canUseItemOn = canUseItemOn;
|
||||||
@@ -18,7 +19,7 @@ public abstract class AbstractHitBox implements HitBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Seat[] seats() {
|
public SeatConfig[] seats() {
|
||||||
return this.seats;
|
return this.seats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public interface CustomFurniture {
|
|||||||
|
|
||||||
record Placement(AnchorType anchorType,
|
record Placement(AnchorType anchorType,
|
||||||
FurnitureElement[] elements,
|
FurnitureElement[] elements,
|
||||||
HitBox[] hitBoxes,
|
HitBoxConfig[] hitBoxConfigs,
|
||||||
RotationRule rotationRule,
|
RotationRule rotationRule,
|
||||||
AlignmentRule alignmentRule,
|
AlignmentRule alignmentRule,
|
||||||
Optional<ExternalModel> externalModel,
|
Optional<ExternalModel> externalModel,
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.joml.Vector3f;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface Furniture {
|
public interface Furniture {
|
||||||
@@ -18,32 +16,30 @@ public interface Furniture {
|
|||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
|
void destroyColliders();
|
||||||
|
|
||||||
void destroySeats();
|
void destroySeats();
|
||||||
|
|
||||||
Optional<Seat> findFirstAvailableSeat(int targetEntityId);
|
|
||||||
|
|
||||||
boolean removeOccupiedSeat(Vector3f seat);
|
|
||||||
|
|
||||||
default boolean removeOccupiedSeat(Seat seat) {
|
|
||||||
return this.removeOccupiedSeat(seat.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean tryOccupySeat(Seat seat);
|
|
||||||
|
|
||||||
UUID uuid();
|
UUID uuid();
|
||||||
|
|
||||||
int baseEntityId();
|
int baseEntityId();
|
||||||
|
|
||||||
@NotNull AnchorType anchorType();
|
@Nullable
|
||||||
|
HitBox hitBoxByEntityId(int id);
|
||||||
|
|
||||||
@NotNull Key id();
|
@Nullable HitBoxPart hitBoxPartByEntityId(int id);
|
||||||
|
|
||||||
@NotNull CustomFurniture config();
|
@NotNull
|
||||||
|
AnchorType anchorType();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Key id();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CustomFurniture config();
|
||||||
|
|
||||||
boolean hasExternalModel();
|
boolean hasExternalModel();
|
||||||
|
|
||||||
void spawnSeatEntityForPlayer(Player player, Seat seat);
|
|
||||||
|
|
||||||
FurnitureExtraData extraData();
|
FurnitureExtraData extraData();
|
||||||
|
|
||||||
void setExtraData(FurnitureExtraData extraData);
|
void setExtraData(FurnitureExtraData extraData);
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import java.util.Optional;
|
|||||||
public interface FurnitureManager extends Manageable {
|
public interface FurnitureManager extends Manageable {
|
||||||
Key FURNITURE_KEY = Key.of("craftengine:furniture_id");
|
Key FURNITURE_KEY = Key.of("craftengine:furniture_id");
|
||||||
Key FURNITURE_EXTRA_DATA_KEY = Key.of("craftengine:furniture_extra_data");
|
Key FURNITURE_EXTRA_DATA_KEY = Key.of("craftengine:furniture_extra_data");
|
||||||
Key FURNITURE_SEAT_BASE_ENTITY_KEY = Key.of("craftengine:seat_to_base_entity");
|
|
||||||
Key FURNITURE_SEAT_VECTOR_3F_KEY = Key.of("craftengine:seat_vector");
|
|
||||||
Key FURNITURE_COLLISION = Key.of("craftengine:collision");
|
Key FURNITURE_COLLISION = Key.of("craftengine:collision");
|
||||||
|
|
||||||
String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin";
|
String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin";
|
||||||
|
|||||||
@@ -1,33 +1,19 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.entity.seat.SeatOwner;
|
||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
import net.momirealms.craftengine.core.world.EntityHitResult;
|
||||||
import org.joml.Quaternionf;
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public interface HitBox {
|
public interface HitBox extends SeatOwner {
|
||||||
|
|
||||||
Key type();
|
Seat<HitBox>[] seats();
|
||||||
|
|
||||||
void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated,
|
Optional<EntityHitResult> clip(Vec3d min, Vec3d max);
|
||||||
BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb);
|
|
||||||
|
|
||||||
void initShapeForPlacement(double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<AABB> aabbs);
|
HitBoxPart[] parts();
|
||||||
|
|
||||||
int[] acquireEntityIds(Supplier<Integer> entityIdSupplier);
|
HitBoxConfig config();
|
||||||
|
|
||||||
Seat[] seats();
|
|
||||||
|
|
||||||
Vector3f position();
|
|
||||||
|
|
||||||
boolean blocksBuilding();
|
|
||||||
|
|
||||||
boolean canBeHitByProjectile();
|
|
||||||
|
|
||||||
boolean canUseItemOn();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public interface HitBoxConfig {
|
||||||
|
|
||||||
|
Key type();
|
||||||
|
|
||||||
|
void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated,
|
||||||
|
BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, Consumer<HitBoxPart> aabb);
|
||||||
|
|
||||||
|
void initShapeForPlacement(double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<AABB> aabbs);
|
||||||
|
|
||||||
|
int[] acquireEntityIds(Supplier<Integer> entityIdSupplier);
|
||||||
|
|
||||||
|
SeatConfig[] seats();
|
||||||
|
|
||||||
|
Vector3f position();
|
||||||
|
|
||||||
|
boolean blocksBuilding();
|
||||||
|
|
||||||
|
boolean canBeHitByProjectile();
|
||||||
|
|
||||||
|
boolean canUseItemOn();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface HitBoxConfigFactory {
|
||||||
|
|
||||||
|
HitBoxConfig create(Map<String, Object> arguments);
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface HitBoxFactory {
|
|
||||||
|
|
||||||
HitBox create(Map<String, Object> arguments);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static Seat[] getSeats(Map<String, Object> arguments) {
|
|
||||||
List<String> seats = (List<String>) arguments.getOrDefault("seats", List.of());
|
|
||||||
return seats.stream()
|
|
||||||
.map(arg -> {
|
|
||||||
String[] split = arg.split(" ");
|
|
||||||
if (split.length == 1) return new Seat(ResourceConfigUtils.getAsVector3f(split[0], "seats"), 0, false);
|
|
||||||
return new Seat(ResourceConfigUtils.getAsVector3f(split[0], "seats"), Float.parseFloat(split[1]), true);
|
|
||||||
})
|
|
||||||
.toArray(Seat[]::new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
|
|
||||||
|
public record HitBoxPart(int entityId, AABB aabb, Vec3d pos) {
|
||||||
|
}
|
||||||
@@ -16,14 +16,14 @@ public class HitBoxTypes {
|
|||||||
public static final Key HAPPY_GHAST = Key.of("minecraft:happy_ghast");
|
public static final Key HAPPY_GHAST = Key.of("minecraft:happy_ghast");
|
||||||
public static final Key CUSTOM = Key.of("minecraft:custom");
|
public static final Key CUSTOM = Key.of("minecraft:custom");
|
||||||
|
|
||||||
public static void register(Key key, HitBoxFactory factory) {
|
public static void register(Key key, HitBoxConfigFactory factory) {
|
||||||
((WritableRegistry<HitBoxFactory>) BuiltInRegistries.HITBOX_FACTORY)
|
((WritableRegistry<HitBoxConfigFactory>) BuiltInRegistries.HITBOX_FACTORY)
|
||||||
.register(ResourceKey.create(Registries.HITBOX_FACTORY.location(), key), factory);
|
.register(ResourceKey.create(Registries.HITBOX_FACTORY.location(), key), factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HitBox fromMap(Map<String, Object> arguments) {
|
public static HitBoxConfig fromMap(Map<String, Object> arguments) {
|
||||||
Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(Key::of).orElse(HitBoxTypes.INTERACTION);
|
Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(Key::of).orElse(HitBoxTypes.INTERACTION);
|
||||||
HitBoxFactory factory = BuiltInRegistries.HITBOX_FACTORY.getValue(type);
|
HitBoxConfigFactory factory = BuiltInRegistries.HITBOX_FACTORY.getValue(type);
|
||||||
if (factory == null) {
|
if (factory == null) {
|
||||||
throw new LocalizedResourceConfigException("warning.config.furniture.hitbox.invalid_type", type.toString());
|
throw new LocalizedResourceConfigException("warning.config.furniture.hitbox.invalid_type", type.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
|
||||||
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public record Seat(Vector3f offset, float yaw, boolean limitPlayerRotation) {
|
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = Objects.hashCode(offset);
|
|
||||||
result = 31 * result + Float.hashCode(yaw);
|
|
||||||
result = 31 * result + Boolean.hashCode(limitPlayerRotation);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.seat;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
|
|
||||||
|
public interface Seat<O extends SeatOwner> {
|
||||||
|
|
||||||
|
O owner();
|
||||||
|
|
||||||
|
SeatConfig config();
|
||||||
|
|
||||||
|
boolean isOccupied();
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
boolean spawnSeat(Player player, WorldPosition source);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.seat;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record SeatConfig(Vector3f position, float yRot, boolean limitPlayerRotation) {
|
||||||
|
|
||||||
|
public static SeatConfig[] fromObj(Object config) {
|
||||||
|
if (config instanceof List<?>) {
|
||||||
|
List<String> seats = MiscUtils.getAsStringList(config);
|
||||||
|
return seats.stream()
|
||||||
|
.map(arg -> {
|
||||||
|
String[] split = arg.split(" ");
|
||||||
|
if (split.length == 1) return new SeatConfig(ResourceConfigUtils.getAsVector3f(split[0], "seats"), 0, false);
|
||||||
|
return new SeatConfig(ResourceConfigUtils.getAsVector3f(split[0], "seats"), Float.parseFloat(split[1]), true);
|
||||||
|
})
|
||||||
|
.toArray(SeatConfig[]::new);
|
||||||
|
} else if (config != null) {
|
||||||
|
String arg = config.toString();
|
||||||
|
String[] split = arg.split(" ");
|
||||||
|
if (split.length == 1) return new SeatConfig[] {new SeatConfig(ResourceConfigUtils.getAsVector3f(split[0], "seats"), 0, false)};
|
||||||
|
return new SeatConfig[] {new SeatConfig(ResourceConfigUtils.getAsVector3f(split[0], "seats"), Float.parseFloat(split[1]), true)};
|
||||||
|
} else {
|
||||||
|
return new SeatConfig[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.seat;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
|
public interface SeatManager extends Manageable {
|
||||||
|
Key SEAT_KEY = Key.of("craftengine:seat");
|
||||||
|
Key SEAT_EXTRA_DATA_KEY = Key.of("craftengine:seat_extra_data");
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.seat;
|
||||||
|
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
|
||||||
|
public interface SeatOwner {
|
||||||
|
|
||||||
|
void saveCustomData(CompoundTag data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package net.momirealms.craftengine.core.item;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||||
|
import net.momirealms.craftengine.core.plugin.text.minimessage.*;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class NetworkItemBuildContext extends ItemBuildContext {
|
||||||
|
|
||||||
|
public NetworkItemBuildContext(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||||
|
super(player, contexts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static NetworkItemBuildContext empty() {
|
||||||
|
return new NetworkItemBuildContext(null, ContextHolder.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static NetworkItemBuildContext of(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||||
|
return new NetworkItemBuildContext(player, contexts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static NetworkItemBuildContext of(@Nullable Player player, @NotNull ContextHolder.Builder builder) {
|
||||||
|
if (player != null) builder.withParameter(DirectContextParameters.PLAYER, player);
|
||||||
|
return new NetworkItemBuildContext(player, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static NetworkItemBuildContext of(@Nullable Player player) {
|
||||||
|
if (player == null) return new NetworkItemBuildContext(null, ContextHolder.empty());
|
||||||
|
return new NetworkItemBuildContext(player, new ContextHolder(Map.of(DirectContextParameters.PLAYER, () -> player)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected TagResolver[] getInternalTagResolvers() {
|
||||||
|
return new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE, new I18NTag(this), new L10NTag(this), new NamedArgumentTag(this),
|
||||||
|
new PlaceholderTag(this), new ExpressionTag(this), new GlobalVariableTag(this)};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.advancement.AdvancementManager;
|
|||||||
import net.momirealms.craftengine.core.block.BlockManager;
|
import net.momirealms.craftengine.core.block.BlockManager;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
|
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
|
||||||
import net.momirealms.craftengine.core.entity.projectile.ProjectileManager;
|
import net.momirealms.craftengine.core.entity.projectile.ProjectileManager;
|
||||||
|
import net.momirealms.craftengine.core.entity.seat.SeatManager;
|
||||||
import net.momirealms.craftengine.core.font.FontManager;
|
import net.momirealms.craftengine.core.font.FontManager;
|
||||||
import net.momirealms.craftengine.core.item.ItemManager;
|
import net.momirealms.craftengine.core.item.ItemManager;
|
||||||
import net.momirealms.craftengine.core.item.recipe.RecipeManager;
|
import net.momirealms.craftengine.core.item.recipe.RecipeManager;
|
||||||
@@ -76,6 +77,7 @@ public abstract class CraftEngine implements Plugin {
|
|||||||
protected CompatibilityManager compatibilityManager;
|
protected CompatibilityManager compatibilityManager;
|
||||||
protected GlobalVariableManager globalVariableManager;
|
protected GlobalVariableManager globalVariableManager;
|
||||||
protected ProjectileManager projectileManager;
|
protected ProjectileManager projectileManager;
|
||||||
|
protected SeatManager seatManager;
|
||||||
|
|
||||||
private final PluginTaskRegistry preLoadTaskRegistry = new PluginTaskRegistry();
|
private final PluginTaskRegistry preLoadTaskRegistry = new PluginTaskRegistry();
|
||||||
private final PluginTaskRegistry postLoadTaskRegistry = new PluginTaskRegistry();
|
private final PluginTaskRegistry postLoadTaskRegistry = new PluginTaskRegistry();
|
||||||
@@ -151,6 +153,7 @@ public abstract class CraftEngine implements Plugin {
|
|||||||
this.packManager.reload();
|
this.packManager.reload();
|
||||||
this.advancementManager.reload();
|
this.advancementManager.reload();
|
||||||
this.projectileManager.reload();
|
this.projectileManager.reload();
|
||||||
|
this.seatManager.reload();
|
||||||
if (reloadRecipe) {
|
if (reloadRecipe) {
|
||||||
this.recipeManager.reload();
|
this.recipeManager.reload();
|
||||||
}
|
}
|
||||||
@@ -229,6 +232,7 @@ public abstract class CraftEngine implements Plugin {
|
|||||||
this.fontManager.delayedInit();
|
this.fontManager.delayedInit();
|
||||||
this.vanillaLootManager.delayedInit();
|
this.vanillaLootManager.delayedInit();
|
||||||
this.advancementManager.delayedInit();
|
this.advancementManager.delayedInit();
|
||||||
|
this.seatManager.delayedInit();
|
||||||
this.compatibilityManager.onDelayedEnable();
|
this.compatibilityManager.onDelayedEnable();
|
||||||
// reload the plugin
|
// reload the plugin
|
||||||
try {
|
try {
|
||||||
@@ -263,6 +267,7 @@ public abstract class CraftEngine implements Plugin {
|
|||||||
if (this.guiManager != null) this.guiManager.disable();
|
if (this.guiManager != null) this.guiManager.disable();
|
||||||
if (this.soundManager != null) this.soundManager.disable();
|
if (this.soundManager != null) this.soundManager.disable();
|
||||||
if (this.vanillaLootManager != null) this.vanillaLootManager.disable();
|
if (this.vanillaLootManager != null) this.vanillaLootManager.disable();
|
||||||
|
if (this.seatManager != null) this.seatManager.disable();
|
||||||
if (this.translationManager != null) this.translationManager.disable();
|
if (this.translationManager != null) this.translationManager.disable();
|
||||||
if (this.globalVariableManager != null) this.globalVariableManager.disable();
|
if (this.globalVariableManager != null) this.globalVariableManager.disable();
|
||||||
if (this.projectileManager != null) this.projectileManager.disable();
|
if (this.projectileManager != null) this.projectileManager.disable();
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ import net.momirealms.craftengine.core.plugin.context.Context;
|
|||||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||||
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
|
|
||||||
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public sealed interface ComponentProvider extends Function<Context, Component>
|
|||||||
if (context instanceof PlayerOptionalContext playerContext) {
|
if (context instanceof PlayerOptionalContext playerContext) {
|
||||||
Player player = playerContext.player();
|
Player player = playerContext.player();
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
String content = TranslationManager.instance().miniMessageTranslation(this.key, player.locale());
|
String content = TranslationManager.instance().miniMessageTranslation(this.key, player.selectedLocale());
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
return Component.text(this.key);
|
return Component.text(this.key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package net.momirealms.craftengine.core.plugin.text.minimessage;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.minimessage.ParsingException;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||||
|
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
||||||
|
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class L10NTag implements TagResolver {
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public L10NTag(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull net.kyori.adventure.text.minimessage.Context ctx) throws ParsingException {
|
||||||
|
if (!this.has(name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Locale locale = null;
|
||||||
|
if (this.context instanceof PlayerOptionalContext playerOptionalContext && playerOptionalContext.isPlayerPresent()) {
|
||||||
|
locale = playerOptionalContext.player().selectedLocale();
|
||||||
|
}
|
||||||
|
String i18nKey = arguments.popOr("No argument l10n key provided").toString();
|
||||||
|
String translation = TranslationManager.instance().miniMessageTranslation(i18nKey, locale);
|
||||||
|
return Tag.selfClosingInserting(AdventureHelper.miniMessage().deserialize(translation, this.context.tagResolvers()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(@NotNull String name) {
|
||||||
|
return "l10n".equals(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
|||||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
|
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
|
||||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfigFactory;
|
||||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||||
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
||||||
@@ -76,7 +76,7 @@ public class BuiltInRegistries {
|
|||||||
public static final Registry<ConditionFactory<PathContext>> PATH_MATCHER_FACTORY = createConstantBoundRegistry(Registries.PATH_MATCHER_FACTORY, 16);
|
public static final Registry<ConditionFactory<PathContext>> PATH_MATCHER_FACTORY = createConstantBoundRegistry(Registries.PATH_MATCHER_FACTORY, 16);
|
||||||
public static final Registry<ResolutionFactory> RESOLUTION_FACTORY = createConstantBoundRegistry(Registries.RESOLUTION_FACTORY, 16);
|
public static final Registry<ResolutionFactory> RESOLUTION_FACTORY = createConstantBoundRegistry(Registries.RESOLUTION_FACTORY, 16);
|
||||||
public static final Registry<CustomSmithingTransformRecipe.ItemDataProcessor.ProcessorFactory> SMITHING_RESULT_PROCESSOR_FACTORY = createConstantBoundRegistry(Registries.SMITHING_RESULT_PROCESSOR_FACTORY, 16);
|
public static final Registry<CustomSmithingTransformRecipe.ItemDataProcessor.ProcessorFactory> SMITHING_RESULT_PROCESSOR_FACTORY = createConstantBoundRegistry(Registries.SMITHING_RESULT_PROCESSOR_FACTORY, 16);
|
||||||
public static final Registry<HitBoxFactory> HITBOX_FACTORY = createConstantBoundRegistry(Registries.HITBOX_FACTORY, 16);
|
public static final Registry<HitBoxConfigFactory> HITBOX_FACTORY = createConstantBoundRegistry(Registries.HITBOX_FACTORY, 16);
|
||||||
public static final Registry<ResourcePackHostFactory> RESOURCE_PACK_HOST_FACTORY = createConstantBoundRegistry(Registries.RESOURCE_PACK_HOST_FACTORY, 16);
|
public static final Registry<ResourcePackHostFactory> RESOURCE_PACK_HOST_FACTORY = createConstantBoundRegistry(Registries.RESOURCE_PACK_HOST_FACTORY, 16);
|
||||||
public static final Registry<FunctionFactory<PlayerOptionalContext>> EVENT_FUNCTION_FACTORY = createConstantBoundRegistry(Registries.EVENT_FUNCTION_FACTORY, 128);
|
public static final Registry<FunctionFactory<PlayerOptionalContext>> EVENT_FUNCTION_FACTORY = createConstantBoundRegistry(Registries.EVENT_FUNCTION_FACTORY, 128);
|
||||||
public static final Registry<ConditionFactory<PlayerOptionalContext>> EVENT_CONDITION_FACTORY = createConstantBoundRegistry(Registries.EVENT_CONDITION_FACTORY, 128);
|
public static final Registry<ConditionFactory<PlayerOptionalContext>> EVENT_CONDITION_FACTORY = createConstantBoundRegistry(Registries.EVENT_CONDITION_FACTORY, 128);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
|||||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
|
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
|
||||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfigFactory;
|
||||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||||
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
||||||
@@ -78,7 +78,7 @@ public class Registries {
|
|||||||
public static final ResourceKey<Registry<ConditionFactory<PathContext>>> PATH_MATCHER_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory"));
|
public static final ResourceKey<Registry<ConditionFactory<PathContext>>> PATH_MATCHER_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory"));
|
||||||
public static final ResourceKey<Registry<ResolutionFactory>> RESOLUTION_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("resolution_factory"));
|
public static final ResourceKey<Registry<ResolutionFactory>> RESOLUTION_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("resolution_factory"));
|
||||||
public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.ProcessorFactory>> SMITHING_RESULT_PROCESSOR_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory"));
|
public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.ProcessorFactory>> SMITHING_RESULT_PROCESSOR_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory"));
|
||||||
public static final ResourceKey<Registry<HitBoxFactory>> HITBOX_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("hitbox_factory"));
|
public static final ResourceKey<Registry<HitBoxConfigFactory>> HITBOX_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("hitbox_factory"));
|
||||||
public static final ResourceKey<Registry<ResourcePackHostFactory>> RESOURCE_PACK_HOST_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("resource_pack_host_factory"));
|
public static final ResourceKey<Registry<ResourcePackHostFactory>> RESOURCE_PACK_HOST_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("resource_pack_host_factory"));
|
||||||
public static final ResourceKey<Registry<FunctionFactory<PlayerOptionalContext>>> EVENT_FUNCTION_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("event_function_factory"));
|
public static final ResourceKey<Registry<FunctionFactory<PlayerOptionalContext>>> EVENT_FUNCTION_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("event_function_factory"));
|
||||||
public static final ResourceKey<Registry<ConditionFactory<PlayerOptionalContext>>> EVENT_CONDITION_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("event_condition_factory"));
|
public static final ResourceKey<Registry<ConditionFactory<PlayerOptionalContext>>> EVENT_CONDITION_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("event_condition_factory"));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.momirealms.craftengine.core.world.chunk.serialization;
|
package net.momirealms.craftengine.core.world.chunk.serialization;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
|
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||||
@@ -14,6 +15,7 @@ import net.momirealms.sparrow.nbt.ListTag;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public final class DefaultBlockEntitySerializer {
|
public final class DefaultBlockEntitySerializer {
|
||||||
|
|
||||||
@@ -41,9 +43,14 @@ public final class DefaultBlockEntitySerializer {
|
|||||||
BlockPos pos = BlockEntity.readPosAndVerify(data, chunk.chunkPos());
|
BlockPos pos = BlockEntity.readPosAndVerify(data, chunk.chunkPos());
|
||||||
ImmutableBlockState blockState = chunk.getBlockState(pos);
|
ImmutableBlockState blockState = chunk.getBlockState(pos);
|
||||||
if (blockState.blockEntityType() == type) {
|
if (blockState.blockEntityType() == type) {
|
||||||
BlockEntity blockEntity = type.factory().create(pos, blockState);
|
Optional<EntityBlockBehavior> entityBlockBehavior = blockState.behavior().getAs(EntityBlockBehavior.class);
|
||||||
blockEntity.loadCustomData(data);
|
if (entityBlockBehavior.isPresent()) {
|
||||||
blockEntities.add(blockEntity);
|
BlockEntity blockEntity = entityBlockBehavior.get().createBlockEntity(pos, blockState);
|
||||||
|
if (blockEntity != null) {
|
||||||
|
blockEntity.loadCustomData(data);
|
||||||
|
blockEntities.add(blockEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ zstd_version=1.5.7-4
|
|||||||
commons_io_version=2.20.0
|
commons_io_version=2.20.0
|
||||||
commons_lang3_version=3.19.0
|
commons_lang3_version=3.19.0
|
||||||
sparrow_nbt_version=0.10.6
|
sparrow_nbt_version=0.10.6
|
||||||
sparrow_util_version=0.57
|
sparrow_util_version=0.58
|
||||||
fastutil_version=8.5.18
|
fastutil_version=8.5.18
|
||||||
netty_version=4.1.127.Final
|
netty_version=4.1.127.Final
|
||||||
joml_version=1.10.8
|
joml_version=1.10.8
|
||||||
|
|||||||
Reference in New Issue
Block a user