9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-04 15:41:38 +00:00

添加染色家具支持

This commit is contained in:
XiaoMoMi
2025-05-11 20:22:22 +08:00
parent 2d8eb48d51
commit 1b8dabb9e9
14 changed files with 119 additions and 53 deletions

View File

@@ -10,9 +10,10 @@ import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement
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.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -22,7 +23,7 @@ import java.util.UUID;
import java.util.function.Consumer;
public class BukkitFurnitureElement extends AbstractFurnitureElement {
private List<Object> cachedValues;
private final List<Object> commonValues;
public BukkitFurnitureElement(Key item,
Billboard billboard,
@@ -30,35 +31,40 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement {
Vector3f scale,
Vector3f translation,
Vector3f offset,
Quaternionf rotation) {
super(item, billboard, transform, scale, translation, offset, rotation);
Quaternionf rotation,
boolean applyDyedColor) {
super(item, billboard, transform, scale, translation, offset, rotation, applyDyedColor);
this.commonValues = new ArrayList<>();
ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.commonValues);
ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.commonValues);
ItemDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(billboard().id(), this.commonValues);
ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(translation(), this.commonValues);
ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(transform().id(), this.commonValues);
}
@Override
public void initPackets(int entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<Object> packets) {
public void initPackets(int entityId, @NotNull WorldPosition position, @NotNull Quaternionf conjugated, Integer dyedColor, Consumer<Object> packets) {
Vector3f offset = conjugated.transform(new Vector3f(position()));
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entityId, UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
entityId, UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.xRot(),
Reflections.instance$EntityType$ITEM_DISPLAY, 0, Reflections.instance$Vec3$Zero, 0
));
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues()));
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues(dyedColor)));
}
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));
private synchronized List<Object> getCachedValues(Integer color) {
List<Object> cachedValues = new ArrayList<>(this.commonValues);
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(item(), null);
if (item == null) {
CraftEngine.instance().debug(() -> "Failed to create furniture element because item " + item() + " not found");
item = BukkitItemManager.instance().wrap(new ItemStack(Material.BARRIER));
} else {
if (color != null) {
item.dyedColor(color);
item.load();
}
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), this.cachedValues);
ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.cachedValues);
ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.cachedValues);
ItemDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(billboard().id(), this.cachedValues);
ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(translation(), this.cachedValues);
ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(transform().id(), this.cachedValues);
}
return this.cachedValues;
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), cachedValues);
return cachedValues;
}
}

View File

@@ -151,7 +151,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
MiscUtils.getAsVector3f(element.getOrDefault("scale", "1"), "scale"),
MiscUtils.getAsVector3f(element.getOrDefault("translation", "0"), "translation"),
MiscUtils.getAsVector3f(element.getOrDefault("position", "0"), "position"),
MiscUtils.getAsQuaternionf(element.getOrDefault("rotation", "0"), "rotation")
MiscUtils.getAsQuaternionf(element.getOrDefault("rotation", "0"), "rotation"),
(boolean) element.getOrDefault("apply-dyed-color", true)
);
elements.add(furnitureElement);
}

View File

@@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.util.QuaternionUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.bukkit.Location;
import org.bukkit.attribute.Attribute;
@@ -94,10 +95,12 @@ public class LoadedFurniture implements Furniture {
List<Collider> colliders = new ArrayList<>();
World world = world();
WorldPosition position = new WorldPosition(world, x, y, z, yaw, 0);
Integer dyedColor = this.extraData.dyedColor().orElse(null);
for (FurnitureElement element : placement.elements()) {
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
fakeEntityIds.add(entityId);
element.initPackets(entityId, world, x, y, z, yaw, conjugated, packet -> {
element.initPackets(entityId, position, conjugated, dyedColor, packet -> {
packets.add(packet);
if (this.minimized) minimizedPackets.add(packet);
});
@@ -109,7 +112,7 @@ public class LoadedFurniture implements Furniture {
mainEntityIds.add(entityId);
this.hitBoxes.put(entityId, hitBox);
}
hitBox.initPacketsAndColliders(ids, world, x, y, z, yaw, conjugated, (packet, canBeMinimized) -> {
hitBox.initPacketsAndColliders(ids, position, conjugated, (packet, canBeMinimized) -> {
packets.add(packet);
if (this.minimized && !canBeMinimized) {
minimizedPackets.add(packet);

View File

@@ -9,7 +9,7 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
@@ -51,11 +51,11 @@ public class CustomHitBox extends AbstractHitBox {
}
@Override
public void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, 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, BiConsumer<Integer, AABB> aabb) {
Vector3f offset = conjugated.transform(new Vector3f(position()));
try {
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(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.xRot(),
FastNMS.INSTANCE.toNMSEntityType(this.entityType), 0, Reflections.instance$Vec3$Zero, 0
), true);
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);

View File

@@ -4,7 +4,7 @@ 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.ResourceConfigUtils;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -33,7 +33,7 @@ public class HappyGhastHitBox extends AbstractHitBox {
}
@Override
public void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, 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, BiConsumer<Integer, AABB> aabb) {
}
@Override

View File

@@ -9,7 +9,7 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -53,8 +53,12 @@ public class InteractionHitBox extends AbstractHitBox {
}
@Override
public void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, 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, BiConsumer<Integer, AABB> aabb) {
Vector3f offset = conjugated.transform(new Vector3f(position()));
double x = position.x();
double y = position.y();
double z = position.z();
float yaw = position.xRot();
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
@@ -66,7 +70,7 @@ public class InteractionHitBox extends AbstractHitBox {
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);
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
collider.accept(new BukkitCollider(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()));
}
}

View File

@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.entity.furniture.*;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -196,9 +197,13 @@ public class ShulkerHitBox extends AbstractHitBox {
}
@Override
public void initPacketsAndColliders(int[] entityIds, World world, double x, double y, double z, float yaw, 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, BiConsumer<Integer, AABB> aabb) {
Vector3f offset = conjugated.transform(new Vector3f(position()));
try {
double x = position.x();
double y = position.y();
double z = position.z();
float yaw = position.xRot();
double originalY = y + offset.y;
double integerPart = Math.floor(originalY);
double fractionalPart = originalY - integerPart;
@@ -228,7 +233,7 @@ public class ShulkerHitBox extends AbstractHitBox {
Reflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale);
packets.accept(Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[1], Collections.singletonList(attributeInstance)), false);
}
this.spawner.accept(entityIds, world, x, y, z, yaw, offset, packets, collider, aabb);
this.spawner.accept(entityIds, position.world(), x, y, z, yaw, offset, packets, collider, aabb);
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Failed to construct shulker hitbox spawn packet", e);
}

View File

@@ -134,7 +134,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
FurnitureExtraData.builder()
.item(item.copyWithCount(1))
.anchorType(anchorType)
.dyedColor(item.dyedColor().orElse(-1))
.dyedColor(item.dyedColor().orElse(null))
.build(), false);
FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, loadedFurniture, furnitureLocation, context.getHand());

View File

@@ -13,7 +13,7 @@ public class LocationUtils {
private LocationUtils() {}
public static Location toLocation(WorldPosition position) {
return new Location((World) position.world().platformWorld(), position.position().x(), position.position().y(), position.position().z());
return new Location((World) position.world().platformWorld(), position.x(), position.y(), position.z(), position.xRot(), position.yRot());
}
public static Vec3d toVec3d(Location loc) {
@@ -33,11 +33,7 @@ public class LocationUtils {
}
public static Object above(Object blockPos) throws ReflectiveOperationException {
return toBlockPos(
FastNMS.INSTANCE.field$Vec3i$x(blockPos),
FastNMS.INSTANCE.field$Vec3i$y(blockPos) + 1,
FastNMS.INSTANCE.field$Vec3i$z(blockPos)
);
return toBlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) + 1, FastNMS.INSTANCE.field$Vec3i$z(blockPos));
}
public static Object toBlockPos(int x, int y, int z) {

View File

@@ -14,8 +14,16 @@ public abstract class AbstractFurnitureElement implements FurnitureElement {
private final Vector3f translation;
private final Vector3f offset;
private final Quaternionf rotation;
private final boolean applyDyedColor;
public AbstractFurnitureElement(Key item, Billboard billboard, ItemDisplayContext transform, Vector3f scale, Vector3f translation, Vector3f offset, Quaternionf rotation) {
public AbstractFurnitureElement(Key item,
Billboard billboard,
ItemDisplayContext transform,
Vector3f scale,
Vector3f translation,
Vector3f offset,
Quaternionf rotation,
boolean applyDyedColor) {
this.billboard = billboard;
this.transform = transform;
this.scale = scale;
@@ -23,6 +31,12 @@ public abstract class AbstractFurnitureElement implements FurnitureElement {
this.item = item;
this.rotation = rotation;
this.offset = offset;
this.applyDyedColor = applyDyedColor;
}
@Override
public boolean applyDyedColor() {
return applyDyedColor;
}
@Override

View File

@@ -3,7 +3,9 @@ package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -18,11 +20,13 @@ public interface FurnitureElement {
ItemDisplayContext transform();
boolean applyDyedColor();
Vector3f scale();
Vector3f translation();
Vector3f position();
void initPackets(int entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<Object> packets);
void initPackets(int entityId, @NotNull WorldPosition position, @NotNull Quaternionf conjugated, @Nullable Integer dyedColor, Consumer<Object> packets);
}

View File

@@ -68,8 +68,8 @@ public class FurnitureExtraData {
return this;
}
public Builder dyedColor(int color) {
if (color < 0) return this;
public Builder dyedColor(Integer color) {
if (color == null) return this;
this.data.putInt(DYED_COLOR, color);
return this;
}

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -14,7 +14,7 @@ public interface HitBox {
Key type();
void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated,
void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated,
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);

View File

@@ -2,18 +2,51 @@ package net.momirealms.craftengine.core.world;
public class WorldPosition {
private final World world;
private final Position position;
private final double x;
private final double y;
private final double z;
private final float xRot;
private final float yRot;
public WorldPosition(Position position, World world) {
this.position = position;
public WorldPosition(World world, Position position, float xRot, float yRot) {
this.x = position.x();
this.y = position.y();
this.z = position.z();
this.world = world;
this.xRot = xRot;
this.yRot = yRot;
}
public Position position() {
return position;
public WorldPosition(World world, double x, double y, double z, float xRot, float yRot) {
this.world = world;
this.x = x;
this.y = y;
this.z = z;
this.xRot = xRot;
this.yRot = yRot;
}
public double x() {
return x;
}
public double y() {
return y;
}
public double z() {
return z;
}
public World world() {
return world;
}
public float xRot() {
return xRot;
}
public float yRot() {
return yRot;
}
}