mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-23 17:09:19 +00:00
refactor furniture framework
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.DisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.furniture.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitFurnitureElement extends AbstractFurnitureElement {
|
||||
private List<Object> cachedValues;
|
||||
|
||||
public BukkitFurnitureElement(Key item,
|
||||
Billboard billboard,
|
||||
ItemDisplayContext transform,
|
||||
Vector3f scale,
|
||||
Vector3f translation,
|
||||
Vector3f offset,
|
||||
Quaternionf rotation) {
|
||||
super(item, billboard, transform, scale, translation, offset, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer<Object> packets) {
|
||||
try {
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - yaw), 0).conjugate().transform(new Vector3f(position()));
|
||||
packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance(
|
||||
entityId, UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||
Reflections.instance$EntityType$ITEM_DISPLAY, 0, Reflections.instance$Vec3$Zero, 0
|
||||
));
|
||||
packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId, getCachedValues()));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to construct element spawn packet", e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized List<Object> getCachedValues() {
|
||||
if (this.cachedValues == null) {
|
||||
this.cachedValues = new ArrayList<>();
|
||||
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(item(), null);
|
||||
if (item == null) {
|
||||
CraftEngine.instance().logger().warn("Failed to create furniture element for " + item() + " because item " + item() + " not found");
|
||||
item = BukkitItemManager.instance().wrap(new ItemStack(Material.STONE));
|
||||
}
|
||||
DisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), this.cachedValues);
|
||||
DisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.cachedValues);
|
||||
DisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.cachedValues);
|
||||
DisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(billboard().id(), this.cachedValues);
|
||||
DisplayEntityData.Translation.addEntityDataIfNotDefaultValue(translation(), this.cachedValues);
|
||||
DisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(transform().id(), this.cachedValues);
|
||||
}
|
||||
return this.cachedValues;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
@@ -115,7 +116,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
}
|
||||
ItemDisplayContext transform = ItemDisplayContext.valueOf(element.getOrDefault("transform", "NONE").toString().toUpperCase(Locale.ENGLISH));
|
||||
Billboard billboard = Billboard.valueOf(element.getOrDefault("billboard", "FIXED").toString().toUpperCase(Locale.ENGLISH));
|
||||
FurnitureElement furnitureElement = new FurnitureElement(Key.of(key), billboard, transform,
|
||||
FurnitureElement furnitureElement = new BukkitFurnitureElement(Key.of(key), billboard, transform,
|
||||
MiscUtils.getVector3f(element.getOrDefault("scale", "1")),
|
||||
MiscUtils.getVector3f(element.getOrDefault("translation", "0")),
|
||||
MiscUtils.getVector3f(element.getOrDefault("position", "0")),
|
||||
@@ -126,32 +127,10 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
List<Map<String, Object>> hitboxConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("hitboxes", List.of());
|
||||
List<HitBox> hitboxes = new ArrayList<>();
|
||||
for (Map<String, Object> config : hitboxConfigs) {
|
||||
List<String> seats = (List<String>) config.getOrDefault("seats", List.of());
|
||||
Seat[] seatArray = seats.stream()
|
||||
.map(arg -> {
|
||||
String[] split = arg.split(" ");
|
||||
if (split.length == 1) return new Seat(MiscUtils.getVector3f(split[0]), 0, false);
|
||||
return new Seat(MiscUtils.getVector3f(split[0]), Float.parseFloat(split[1]), true);
|
||||
})
|
||||
.toArray(Seat[]::new);
|
||||
Vector3f position = MiscUtils.getVector3f(config.getOrDefault("position", "0"));
|
||||
float width = MiscUtils.getAsFloat(config.getOrDefault("width", "1"));
|
||||
float height = MiscUtils.getAsFloat(config.getOrDefault("height", "1"));
|
||||
HitBox hitBox = new HitBox(
|
||||
position,
|
||||
new Vector3f(width, height, width),
|
||||
seatArray,
|
||||
(boolean) config.getOrDefault("interactive", true)
|
||||
);
|
||||
hitboxes.add(hitBox);
|
||||
hitboxes.add(HitBoxTypes.fromMap(config));
|
||||
}
|
||||
if (hitboxes.isEmpty()) {
|
||||
hitboxes.add(new HitBox(
|
||||
new Vector3f(),
|
||||
new Vector3f(1,1,1),
|
||||
new Seat[0],
|
||||
true
|
||||
));
|
||||
hitboxes.add(InteractionHitBox.DEFAULT);
|
||||
}
|
||||
Map<String, Object> ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true);
|
||||
if (ruleSection != null) {
|
||||
@@ -164,6 +143,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBox[0]),
|
||||
new Collider[0],
|
||||
rotationRule,
|
||||
alignmentRule
|
||||
));
|
||||
@@ -171,6 +151,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBox[0]),
|
||||
new Collider[0],
|
||||
RotationRule.ANY,
|
||||
AlignmentRule.CENTER
|
||||
));
|
||||
@@ -222,6 +203,13 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
tryLeavingSeat(player, vehicle);
|
||||
}
|
||||
}
|
||||
// for (World world : Bukkit.getWorlds()) {
|
||||
// for (Entity entity : world.getEntities()) {
|
||||
// if (entity instanceof CollisionEntity) {
|
||||
// entity.remove();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -252,6 +240,10 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
for (int sub : furniture.interactionEntityIds()) {
|
||||
this.furnitureByInteractionEntityId.remove(sub);
|
||||
}
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
if (interaction instanceof CollisionEntity) {
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxTypes;
|
||||
|
||||
public class BukkitHitBoxTypes extends HitBoxTypes {
|
||||
|
||||
public static void init() {}
|
||||
|
||||
static {
|
||||
register(INTERACTION, InteractionHitBox.FACTORY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.InteractionEntityData;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class InteractionHitBox extends AbstractHitBox {
|
||||
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);
|
||||
private final Vector3f position;
|
||||
private final Vector3f size;
|
||||
private final boolean responsive;
|
||||
private final List<Object> cachedValues = new ArrayList<>();
|
||||
|
||||
public InteractionHitBox(Seat[] seats, Vector3f position, Vector3f size, boolean responsive) {
|
||||
super(seats);
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
this.responsive = responsive;
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(size.y, cachedValues);
|
||||
InteractionEntityData.Width.addEntityDataIfNotDefaultValue(size.x, cachedValues);
|
||||
InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(responsive, cachedValues);
|
||||
}
|
||||
|
||||
public boolean responsive() {
|
||||
return responsive;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Vector3f size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return HitBoxTypes.INTERACTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer<Object> packets) {
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0f, Math.toRadians(180f - yaw), 0f).conjugate().transform(new Vector3f(position()));
|
||||
try {
|
||||
packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance(
|
||||
entityId, UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
|
||||
));
|
||||
packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId, List.copyOf(this.cachedValues)));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to construct hitbox spawn packet", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements HitBoxFactory {
|
||||
|
||||
@Override
|
||||
public HitBox create(Map<String, Object> arguments) {
|
||||
Vector3f position = MiscUtils.getVector3f(arguments.getOrDefault("position", "0"));
|
||||
float width = MiscUtils.getAsFloat(arguments.getOrDefault("width", "1"));
|
||||
float height = MiscUtils.getAsFloat(arguments.getOrDefault("height", "1"));
|
||||
return new InteractionHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
position,
|
||||
new Vector3f(width, height, width),
|
||||
(boolean) arguments.getOrDefault("interactive", true)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.DisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.InteractionEntityData;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.ArrayUtils;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
@@ -19,7 +15,6 @@ import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Vector3f;
|
||||
@@ -35,8 +30,6 @@ public class LoadedFurniture {
|
||||
private final Map<Integer, HitBox> hitBoxes;
|
||||
// location
|
||||
private Location location;
|
||||
// cached spawn packet
|
||||
private Object cachedSpawnPacket;
|
||||
// base entity
|
||||
private final WeakReference<Entity> baseEntity;
|
||||
private final int baseEntityId;
|
||||
@@ -48,6 +41,9 @@ public class LoadedFurniture {
|
||||
private final Set<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
|
||||
private final Vector<Entity> seats = new Vector<>();
|
||||
|
||||
// cached spawn packet
|
||||
private Object cachedSpawnPacket;
|
||||
|
||||
public LoadedFurniture(Entity baseEntity,
|
||||
CustomFurniture furniture,
|
||||
AnchorType anchorType) {
|
||||
@@ -60,78 +56,40 @@ public class LoadedFurniture {
|
||||
this.hitBoxes = new HashMap<>();
|
||||
this.elements = new HashMap<>();
|
||||
List<Integer> entityIds = new ArrayList<>();
|
||||
List<Integer> interactionEntityIds = new ArrayList<>();
|
||||
List<Integer> hitBoxEntityIds = new ArrayList<>();
|
||||
CustomFurniture.Placement placement = furniture.getPlacement(anchorType);
|
||||
for (FurnitureElement element : placement.elements()) {
|
||||
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
entityIds.add(entityId);
|
||||
this.elements.put(entityId, element);
|
||||
}
|
||||
for (HitBox hitBox : placement.hitbox()) {
|
||||
for (HitBox hitBox : placement.hitboxes()) {
|
||||
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
entityIds.add(entityId);
|
||||
interactionEntityIds.add(entityId);
|
||||
hitBoxEntityIds.add(entityId);
|
||||
this.hitBoxes.put(entityId, hitBox);
|
||||
}
|
||||
this.subEntityIds = entityIds;
|
||||
this.interactionEntityIds = interactionEntityIds;
|
||||
this.resetSpawnPackets();
|
||||
this.interactionEntityIds = hitBoxEntityIds;
|
||||
}
|
||||
|
||||
private void resetSpawnPackets() {
|
||||
public synchronized Object spawnPacket() {
|
||||
if (this.cachedSpawnPacket == null) {
|
||||
try {
|
||||
List<Object> packets = new ArrayList<>();
|
||||
for (Map.Entry<Integer, FurnitureElement> entry : elements.entrySet()) {
|
||||
int entityId = entry.getKey();
|
||||
FurnitureElement element = entry.getValue();
|
||||
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(element.item(), null);
|
||||
if (item == null) {
|
||||
CraftEngine.instance().logger().warn("Failed to create furniture element for " + id + " because item " + element.item() + " not found");
|
||||
continue;
|
||||
for (Map.Entry<Integer, FurnitureElement> entry : this.elements.entrySet()) {
|
||||
entry.getValue().addSpawnPackets(entry.getKey(), this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add);
|
||||
}
|
||||
item.load();
|
||||
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate().transform(new Vector3f(element.offset()));
|
||||
Object addEntityPacket = Reflections.constructor$ClientboundAddEntityPacket.newInstance(
|
||||
entityId, UUID.randomUUID(), this.location.getX() + offset.x, this.location.getY() + offset.y, this.location.getZ() - offset.z, 0, this.location.getYaw(),
|
||||
Reflections.instance$EntityType$ITEM_DISPLAY, 0, Reflections.instance$Vec3$Zero, 0
|
||||
);
|
||||
|
||||
ArrayList<Object> values = new ArrayList<>();
|
||||
DisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), values);
|
||||
DisplayEntityData.Scale.addEntityDataIfNotDefaultValue(element.scale(), values);
|
||||
DisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(element.rotation(), values);
|
||||
DisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(element.billboard().id(), values);
|
||||
DisplayEntityData.Translation.addEntityDataIfNotDefaultValue(element.translation(), values);
|
||||
DisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(element.transform().id(), values);
|
||||
Object setDataPacket = Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId, values);
|
||||
|
||||
packets.add(addEntityPacket);
|
||||
packets.add(setDataPacket);
|
||||
}
|
||||
for (Map.Entry<Integer, HitBox> entry : hitBoxes.entrySet()) {
|
||||
int entityId = entry.getKey();
|
||||
HitBox hitBox = entry.getValue();
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate().transform(new Vector3f(hitBox.offset()));
|
||||
Object addEntityPacket = Reflections.constructor$ClientboundAddEntityPacket.newInstance(
|
||||
entityId, UUID.randomUUID(), this.location.getX() + offset.x, this.location.getY() + offset.y, this.location.getZ() - offset.z, 0, this.location.getYaw(),
|
||||
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
|
||||
);
|
||||
|
||||
ArrayList<Object> values = new ArrayList<>();
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(hitBox.size().y, values);
|
||||
InteractionEntityData.Width.addEntityDataIfNotDefaultValue(hitBox.size().x, values);
|
||||
InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(hitBox.responsive(), values);
|
||||
Object setDataPacket = Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId, values);
|
||||
|
||||
packets.add(addEntityPacket);
|
||||
packets.add(setDataPacket);
|
||||
for (Map.Entry<Integer, HitBox> entry : this.hitBoxes.entrySet()) {
|
||||
entry.getValue().addSpawnPackets(entry.getKey(), this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add);
|
||||
}
|
||||
this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e);
|
||||
}
|
||||
}
|
||||
return this.cachedSpawnPacket;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Location location() {
|
||||
@@ -274,8 +232,4 @@ public class LoadedFurniture {
|
||||
this.addSeatEntity(seatEntity);
|
||||
seatEntity.addPassenger(player);
|
||||
}
|
||||
|
||||
public @NotNull Object spawnPacket() {
|
||||
return cachedSpawnPacket;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitHitBoxTypes;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitImageManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors;
|
||||
@@ -142,6 +143,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
}
|
||||
BukkitBlockBehaviors.init();
|
||||
BukkitItemBehaviors.init();
|
||||
BukkitHitBoxTypes.init();
|
||||
super.packManager = new BukkitPackManager(this);
|
||||
super.senderFactory = new BukkitSenderFactory(this);
|
||||
super.itemManager = new BukkitItemManager(this);
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public TestCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
||||
@@ -19,10 +20,18 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.handler(context -> {
|
||||
List<Holder<Key>> holders = plugin().itemManager().tagToItems(Key.of("minecraft:planks"));
|
||||
for (Holder<Key> holder : holders) {
|
||||
context.sender().sendMessage(holder.registeredName());
|
||||
Player player = context.sender();
|
||||
Location location = player.getLocation();
|
||||
try {
|
||||
Object level = Reflections.field$CraftWorld$ServerLevel.get(player.getWorld());
|
||||
Object aabb = FastNMS.INSTANCE.constructor$AABB(location.getBlockX(), location.getBlockY(), location.getBlockZ(),
|
||||
location.getBlockX() + 1, location.getBlockY() + 1, location.getBlockZ() + 1);
|
||||
CollisionEntity nmsEntity = FastNMS.INSTANCE.createCollisionEntity(level, aabb, location.getBlockX() + 0.5, location.getBlockY(), location.getBlockZ() + 0.5, true, false);
|
||||
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(level, nmsEntity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2426,6 +2426,12 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$AABB = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$AABB, double.class, double.class, double.class, double.class, double.class, double.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$BlockGetter = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.BlockGetter"),
|
||||
@@ -5753,22 +5759,27 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$Level$random = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$Level, clazz$RandomSource, 0
|
||||
public static final Field field$Entity$boundingBox = requireNonNull(
|
||||
ReflectionUtils.getInstanceDeclaredField(
|
||||
clazz$Entity, clazz$AABB, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$Mth = requireNonNull(
|
||||
public static final Class<?> clazz$CraftShulker = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("util.Mth"),
|
||||
BukkitReflectionUtils.assembleMCClass("util.MathHelper")
|
||||
BukkitReflectionUtils.assembleCBClass("entity.CraftShulker")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$nextInt = requireNonNull(
|
||||
public static final Class<?> clazz$Shulker = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.entity.monster.Shulker")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$CraftShulker$getHandle = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Mth, int.class, clazz$RandomSource, int.class, int.class
|
||||
clazz$CraftShulker, clazz$Shulker, 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -395,6 +395,4 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
}
|
||||
ceChunk.load();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public abstract class AbstractFurnitureElement implements FurnitureElement {
|
||||
private final Key item;
|
||||
private final Billboard billboard;
|
||||
private final ItemDisplayContext transform;
|
||||
private final Vector3f scale;
|
||||
private final Vector3f translation;
|
||||
private final Vector3f offset;
|
||||
private final Quaternionf rotation;
|
||||
|
||||
public AbstractFurnitureElement(Key item, Billboard billboard, ItemDisplayContext transform, Vector3f scale, Vector3f translation, Vector3f offset, Quaternionf rotation) {
|
||||
this.billboard = billboard;
|
||||
this.transform = transform;
|
||||
this.scale = scale;
|
||||
this.translation = translation;
|
||||
this.item = item;
|
||||
this.rotation = rotation;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Quaternionf rotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key item() {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Billboard billboard() {
|
||||
return billboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemDisplayContext transform() {
|
||||
return transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f scale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f translation() {
|
||||
return translation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f position() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
public abstract class AbstractHitBox implements HitBox {
|
||||
protected final Seat[] seats;
|
||||
|
||||
public AbstractHitBox(Seat[] seats) {
|
||||
this.seats = seats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Seat[] seats() {
|
||||
return seats;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class Collider {
|
||||
private final Vector3f position;
|
||||
private final double width;
|
||||
private final double height;
|
||||
private final boolean canBeHitByProjectile;
|
||||
|
||||
public Collider(boolean canBeHitByProjectile, double height, Vector3f position, double width) {
|
||||
this.canBeHitByProjectile = canBeHitByProjectile;
|
||||
this.height = height;
|
||||
this.position = position;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public boolean canBeHitByProjectile() {
|
||||
return canBeHitByProjectile;
|
||||
}
|
||||
|
||||
public double height() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public double width() {
|
||||
return width;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public class CustomFurniture {
|
||||
private final Key id;
|
||||
private final FurnitureSettings settings;
|
||||
private final EnumMap<AnchorType, Placement> placements;
|
||||
private final AnchorType anyType;
|
||||
@Nullable
|
||||
private final LootTable<?> lootTable;
|
||||
|
||||
@@ -22,6 +23,7 @@ public class CustomFurniture {
|
||||
this.settings = settings;
|
||||
this.placements = placements;
|
||||
this.lootTable = lootTable;
|
||||
this.anyType = placements.keySet().stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public Key id() {
|
||||
@@ -42,7 +44,7 @@ public class CustomFurniture {
|
||||
}
|
||||
|
||||
public AnchorType getAnyPlacement() {
|
||||
return placements.keySet().stream().findFirst().orElse(null);
|
||||
return this.anyType;
|
||||
}
|
||||
|
||||
public boolean isAllowedPlacement(AnchorType anchorType) {
|
||||
@@ -55,19 +57,25 @@ public class CustomFurniture {
|
||||
|
||||
public static class Placement {
|
||||
private final FurnitureElement[] elements;
|
||||
private final HitBox[] hitbox;
|
||||
private final HitBox[] hitboxes;
|
||||
private final Collider[] colliders;
|
||||
private final RotationRule rotationRule;
|
||||
private final AlignmentRule alignmentRule;
|
||||
|
||||
public Placement(FurnitureElement[] elements, HitBox[] hitbox, RotationRule rotationRule, AlignmentRule alignmentRule) {
|
||||
public Placement(FurnitureElement[] elements, HitBox[] hitboxes, Collider[] colliders, RotationRule rotationRule, AlignmentRule alignmentRule) {
|
||||
this.elements = elements;
|
||||
this.hitbox = hitbox;
|
||||
this.hitboxes = hitboxes;
|
||||
this.colliders = colliders;
|
||||
this.rotationRule = rotationRule;
|
||||
this.alignmentRule = alignmentRule;
|
||||
}
|
||||
|
||||
public HitBox[] hitbox() {
|
||||
return hitbox;
|
||||
public HitBox[] hitboxes() {
|
||||
return hitboxes;
|
||||
}
|
||||
|
||||
public Collider[] colliders() {
|
||||
return colliders;
|
||||
}
|
||||
|
||||
public FurnitureElement[] elements() {
|
||||
|
||||
@@ -4,50 +4,22 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class FurnitureElement {
|
||||
private final Key item;
|
||||
private final Billboard billboard;
|
||||
private final ItemDisplayContext transform;
|
||||
private final Vector3f scale;
|
||||
private final Vector3f translation;
|
||||
private final Vector3f offset;
|
||||
private final Quaternionf rotation;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public FurnitureElement(Key item, Billboard billboard, ItemDisplayContext transform, Vector3f scale, Vector3f translation, Vector3f offset, Quaternionf rotation) {
|
||||
this.billboard = billboard;
|
||||
this.transform = transform;
|
||||
this.scale = scale;
|
||||
this.translation = translation;
|
||||
this.item = item;
|
||||
this.rotation = rotation;
|
||||
this.offset = offset;
|
||||
}
|
||||
public interface FurnitureElement {
|
||||
Quaternionf rotation();
|
||||
|
||||
public Quaternionf rotation() {
|
||||
return rotation;
|
||||
}
|
||||
Key item();
|
||||
|
||||
public Key item() {
|
||||
return item;
|
||||
}
|
||||
Billboard billboard();
|
||||
|
||||
public Billboard billboard() {
|
||||
return billboard;
|
||||
}
|
||||
ItemDisplayContext transform();
|
||||
|
||||
public ItemDisplayContext transform() {
|
||||
return transform;
|
||||
}
|
||||
Vector3f scale();
|
||||
|
||||
public Vector3f scale() {
|
||||
return scale;
|
||||
}
|
||||
Vector3f translation();
|
||||
|
||||
public Vector3f translation() {
|
||||
return translation;
|
||||
}
|
||||
Vector3f position();
|
||||
|
||||
public Vector3f offset() {
|
||||
return offset;
|
||||
}
|
||||
void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer<Object> packets);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,14 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public class HitBox {
|
||||
private final Vector3f position;
|
||||
private final Vector3f size;
|
||||
private final Seat[] seats;
|
||||
private final boolean responsive;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public HitBox(Vector3f position, Vector3f size, Seat[] seats, boolean responsive) {
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
this.seats = seats;
|
||||
this.responsive = responsive;
|
||||
}
|
||||
public interface HitBox {
|
||||
|
||||
public boolean responsive() {
|
||||
return responsive;
|
||||
}
|
||||
Key type();
|
||||
|
||||
public Seat[] seats() {
|
||||
return seats;
|
||||
}
|
||||
void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer<Object> packets);
|
||||
|
||||
public Vector3f offset() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Vector3f size() {
|
||||
return size;
|
||||
}
|
||||
Seat[] seats();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
|
||||
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(MiscUtils.getVector3f(split[0]), 0, false);
|
||||
return new Seat(MiscUtils.getVector3f(split[0]), Float.parseFloat(split[1]), true);
|
||||
})
|
||||
.toArray(Seat[]::new);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class HitBoxTypes {
|
||||
public static final Key INTERACTION = Key.of("minecraft:interaction");
|
||||
public static final Key SHULKER = Key.of("minecraft:shulker");
|
||||
|
||||
public static void register(Key key, HitBoxFactory factory) {
|
||||
Holder.Reference<HitBoxFactory> holder = ((WritableRegistry<HitBoxFactory>) BuiltInRegistries.HITBOX_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.HITBOX_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
public static HitBox fromMap(Map<String, Object> arguments) {
|
||||
Key type = Optional.ofNullable((String) arguments.get("type")).map(Key::of).orElse(HitBoxTypes.INTERACTION);
|
||||
HitBoxFactory factory = BuiltInRegistries.HITBOX_FACTORY.getValue(type);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Unknown hitbox type: " + type);
|
||||
}
|
||||
return factory.create(arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.core.plugin.locale;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.Plugin;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.core.plugin.locale;
|
||||
|
||||
import net.momirealms.craftengine.core.block.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.block.BlockStateVariantProvider;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.momirealms.craftengine.core.plugin.locale;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.translation.Translator;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.registry;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
@@ -45,6 +46,7 @@ public class BuiltInRegistries {
|
||||
public static final Registry<PathMatcherFactory> PATH_MATCHER_FACTORY = createRegistry(Registries.PATH_MATCHER_FACTORY);
|
||||
public static final Registry<ResolutionFactory> RESOLUTION_FACTORY = createRegistry(Registries.RESOLUTION_FACTORY);
|
||||
public static final Registry<CustomSmithingTransformRecipe.ItemDataProcessor.Factory> SMITHING_RESULT_PROCESSOR_FACTORY = createRegistry(Registries.SMITHING_RESULT_PROCESSOR_FACTORY);
|
||||
public static final Registry<HitBoxFactory> HITBOX_FACTORY = createRegistry(Registries.HITBOX_FACTORY);
|
||||
|
||||
private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) {
|
||||
return new MappedRegistry<>(key);
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.registry;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
@@ -46,4 +47,5 @@ public class Registries {
|
||||
public static final ResourceKey<Registry<PathMatcherFactory>> PATH_MATCHER_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory"));
|
||||
public static final ResourceKey<Registry<ResolutionFactory>> RESOLUTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resolution_factory"));
|
||||
public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.Factory>> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory"));
|
||||
public static final ResourceKey<Registry<HitBoxFactory>> HITBOX_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("hitbox_factory"));
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ mojang_brigadier_version=1.0.18
|
||||
byte_buddy_version=1.15.11
|
||||
snake_yaml_version=2.3
|
||||
anti_grief_version=0.13
|
||||
nms_helper_version=0.12
|
||||
nms_helper_version=0.19
|
||||
# Ignite Dependencies
|
||||
mixinextras_version=0.4.1
|
||||
mixin_version=0.15.2+mixin.0.8.7
|
||||
|
||||
Reference in New Issue
Block a user