9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-03 22:26:16 +00:00

家具重构part3

This commit is contained in:
XiaoMoMi
2025-12-03 01:30:29 +08:00
parent 0a6bd37c36
commit d2bb9103bd
30 changed files with 580 additions and 388 deletions

View File

@@ -124,7 +124,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
String variantName = e0.getKey();
Map<String, Object> variantArguments = ResourceConfigUtils.getAsMap(e0.getValue(), variantName);
Optional<Vector3f> optionalLootSpawnOffset = Optional.ofNullable(variantArguments.get("loot-spawn-offset")).map(it -> ResourceConfigUtils.getAsVector3f(it, "loot-spawn-offset"));
List<FurnitureElementConfig<?>> elements = ResourceConfigUtils.parseConfigAsList(variantArguments.get("elementConfigs"), FurnitureElementConfigs::fromMap);
List<FurnitureElementConfig<?>> elements = ResourceConfigUtils.parseConfigAsList(variantArguments.get("elements"), FurnitureElementConfigs::fromMap);
// fixme 外部模型不应该在这
Optional<ExternalModel> externalModel;
@@ -141,7 +141,12 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
hitboxes = List.of(defaultHitBox());
}
// fixme 动态计算aabb因为家具具有朝向
AABB maxAABB = new AABB(0,0,0,1,1,1);
variants.put(variantName, new FurnitureVariant(
variantName,
parseCullingData(section.get("entity-culling"), maxAABB),
elements.toArray(new FurnitureElementConfig[0]),
hitboxes.toArray(new FurnitureHitBoxConfig[0]),
externalModel,
@@ -149,15 +154,13 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
));
}
AABB maxAABB = null;
FurnitureConfig furniture = FurnitureConfig.builder()
.id(id)
.settings(FurnitureSettings.fromMap(MiscUtils.castToMap(section.get("settings"), true)))
.variants(variants)
.events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")))
.lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true)))
.cullingData(parseCullingData(section.get("entity-culling"), maxAABB))
.build();
AbstractFurnitureManager.this.byId.put(id, furniture);
}

View File

@@ -1,6 +1,10 @@
package net.momirealms.craftengine.core.entity.furniture;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.momirealms.craftengine.core.entity.Entity;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
@@ -15,13 +19,12 @@ import net.momirealms.craftengine.core.world.Cullable;
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.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class Furniture implements Cullable {
@@ -29,18 +32,20 @@ public abstract class Furniture implements Cullable {
public final FurnitureDataAccessor dataAccessor;
public final WeakReference<Entity> metaDataEntity;
protected CullingData cullingData;
protected FurnitureVariant currentVariant;
protected FurnitureElement[] elements;
protected Collider[] colliders;
protected FurnitureHitBox[] hitboxes;
protected Int2ObjectMap<FurnitureHitBox> hitboxMap;
protected int[] entityIds;
protected int[] virtualEntityIds;
protected int[] colliderEntityIds;
protected Furniture(Entity metaDataEntity, FurnitureDataAccessor data, FurnitureConfig config) {
this.config = config;
this.dataAccessor = data;
this.metaDataEntity = new WeakReference<>(metaDataEntity);
this.setVariant(config.getVariant(data));
}
public WeakReference<Entity> metaDataEntity() {
@@ -48,25 +53,24 @@ public abstract class Furniture implements Cullable {
}
public FurnitureVariant getCurrentVariant() {
return currentVariant;
}
public String getCurrentVariantName() {
return null;
return this.currentVariant;
}
public void setVariant(FurnitureVariant variant) {
this.currentVariant = variant;
WorldPosition position = this.position();
this.hitboxMap = new Int2ObjectOpenHashMap<>();
// 初始化家具元素
IntList virtualEntityIds = new IntArrayList();
FurnitureElementConfig<?>[] elementConfigs = variant.elementConfigs();
this.elements = new FurnitureElement[elementConfigs.length];
for (int i = 0; i < elementConfigs.length; i++) {
this.elements[i] = elementConfigs[i].create(this);
FurnitureElement element = elementConfigs[i].create(this);
this.elements[i] = element;
element.collectVirtualEntityId(virtualEntityIds::addLast);
}
// 初始化碰撞箱
FurnitureHitBoxConfig<?>[] furnitureHitBoxConfigs = variant.furnitureHitBoxConfigs();
List<Collider> colliders = new ArrayList<>(furnitureHitBoxConfigs.length);
FurnitureHitBoxConfig<?>[] furnitureHitBoxConfigs = variant.hitBoxConfigs();
ObjectArrayList<Collider> colliders = new ObjectArrayList<>(furnitureHitBoxConfigs.length);
this.hitboxes = new FurnitureHitBox[furnitureHitBoxConfigs.length];
for (int i = 0; i < furnitureHitBoxConfigs.length; i++) {
FurnitureHitBox hitbox = furnitureHitBoxConfigs[i].create(this);
@@ -74,12 +78,23 @@ public abstract class Furniture implements Cullable {
for (int hitboxEntityId : hitbox.virtualEntityIds()) {
this.hitboxMap.put(hitboxEntityId, hitbox);
}
Collider collider = hitbox.collider();
if (collider != null) {
colliders.add(collider);
}
colliders.addAll(hitbox.colliders());
hitbox.collectVirtualEntityIds(virtualEntityIds::addLast);
}
// 虚拟碰撞箱的实体id
this.virtualEntityIds = virtualEntityIds.toIntArray();
this.colliders = colliders.toArray(new Collider[0]);
this.colliderEntityIds = colliders.stream().mapToInt(Collider::entityId).toArray();
this.cullingData = createCullingData(variant.cullingData());
}
private CullingData createCullingData(CullingData parent) {
if (parent == null) return null;
AABB aabb = parent.aabb;
WorldPosition position = position();
Vec3d pos1 = getRelativePosition(position, new Vector3f((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ));
Vec3d pos2 = getRelativePosition(position, new Vector3f((float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ));
return new CullingData(new AABB(pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z), parent.maxDistance, parent.aabbExpansion, parent.rayTracing);
}
@Nullable
@@ -90,15 +105,20 @@ public abstract class Furniture implements Cullable {
@Nullable
@Override
public CullingData cullingData() {
return this.config.cullingData();
return this.cullingData;
}
public Key id() {
return this.config.id();
}
public int[] entityIds() {
return this.entityIds;
// 会发给玩家的包
public int[] virtualEntityIds() {
return this.virtualEntityIds;
}
public int[] colliderEntityIds() {
return colliderEntityIds;
}
public UUID uuid() {
@@ -146,11 +166,11 @@ public abstract class Furniture implements Cullable {
public abstract void destroy();
public FurnitureConfig config() {
return config;
return this.config;
}
public FurnitureDataAccessor dataAccessor() {
return dataAccessor;
return this.dataAccessor;
}
public Collider[] colliders() {

View File

@@ -0,0 +1,6 @@
package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.util.Color;
public record FurnitureColorSource(Color dyedColor, int[] fireworkColors) {
}

View File

@@ -67,8 +67,6 @@ public interface FurnitureConfig {
}
CullingData cullingData();
static Builder builder() {
return new FurnitureConfigImpl.BuilderImpl();
}
@@ -87,8 +85,6 @@ public interface FurnitureConfig {
Builder behavior(FurnitureBehavior behavior);
Builder cullingData(CullingData cullingData);
FurnitureConfig build();
}
}

View File

@@ -23,7 +23,6 @@ class FurnitureConfigImpl implements FurnitureConfig {
private final Map<String, FurnitureVariant> variants;
private final Map<EventTrigger, List<Function<Context>>> events;
private final FurnitureBehavior behavior;
private final CullingData cullingData;
@Nullable
private final LootTable<?> lootTable;
@@ -32,14 +31,12 @@ class FurnitureConfigImpl implements FurnitureConfig {
@NotNull Map<String, FurnitureVariant> variants,
@NotNull Map<EventTrigger, List<Function<Context>>> events,
@NotNull FurnitureBehavior behavior,
@Nullable CullingData cullingData,
@Nullable LootTable<?> lootTable) {
this.id = id;
this.settings = settings;
this.variants = ImmutableMap.copyOf(variants);
this.lootTable = lootTable;
this.behavior = behavior;
this.cullingData = cullingData;
this.events = events;
}
@@ -75,11 +72,6 @@ class FurnitureConfigImpl implements FurnitureConfig {
return this.behavior;
}
@Override
public CullingData cullingData() {
return this.cullingData;
}
@Nullable
@Override
public FurnitureVariant getVariant(String variantName) {
@@ -93,11 +85,10 @@ class FurnitureConfigImpl implements FurnitureConfig {
private Map<EventTrigger, List<Function<Context>>> events;
private LootTable<?> lootTable;
private FurnitureBehavior behavior = EmptyFurnitureBehavior.INSTANCE;
private CullingData cullingData;
@Override
public FurnitureConfig build() {
return new FurnitureConfigImpl(this.id, this.settings, this.variants, this.events, this.behavior, this.cullingData, this.lootTable);
return new FurnitureConfigImpl(this.id, this.settings, this.variants, this.events, this.behavior, this.lootTable);
}
@Override
@@ -130,12 +121,6 @@ class FurnitureConfigImpl implements FurnitureConfig {
return this;
}
@Override
public Builder cullingData(CullingData cullingData) {
this.cullingData = cullingData;
return this;
}
@Override
public Builder behavior(FurnitureBehavior behavior) {
this.behavior = behavior;

View File

@@ -68,12 +68,20 @@ public class FurnitureDataAccessor {
this.data.putByteArray(ITEM, item.toByteArray());
}
public FurnitureColorSource getColorSource() {
return new FurnitureColorSource(dyedColor().orElse(null), fireworkExplosionColors().orElse(null));
}
public Optional<int[]> fireworkExplosionColors() {
if (this.data.containsKey(FIREWORK_EXPLOSION_COLORS)) return Optional.of(this.data.getIntArray(FIREWORK_EXPLOSION_COLORS));
return Optional.empty();
}
public void setFireworkExplosionColors(int[] colors) {
if (colors == null) {
this.data.remove(FIREWORK_EXPLOSION_COLORS);
return;
}
this.data.putIntArray(FIREWORK_EXPLOSION_COLORS, colors);
}
@@ -82,7 +90,11 @@ public class FurnitureDataAccessor {
return Optional.empty();
}
public void setDyedColor(Color color) {
public void setDyedColor(@Nullable Color color) {
if (color == null) {
this.data.remove(DYED_COLOR);
return;
}
this.data.putInt(DYED_COLOR, color.color());
}

View File

@@ -1,6 +1,5 @@
package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.entity.AbstractEntity;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
@@ -31,16 +30,14 @@ public interface FurnitureManager extends Manageable {
Map<Key, FurnitureConfig> loadedFurniture();
boolean isFurnitureRealEntity(int entityId);
boolean isFurnitureMetaEntity(int entityId);
@Nullable
Furniture loadedFurnitureByRealEntityId(int entityId);
Furniture loadedFurnitureByMetaEntityId(int entityId);
@Nullable
default Furniture loadedFurnitureByRealEntity(AbstractEntity entity) {
return loadedFurnitureByRealEntityId(entity.entityID());
}
Furniture loadedFurnitureByVirtualEntityId(int entityId);
@Nullable
Furniture loadedFurnitureByEntityId(int entityId);
Furniture loadedFurnitureByColliderEntityId(int entityId);
}

View File

@@ -2,12 +2,16 @@ package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import java.util.Optional;
public record FurnitureVariant(FurnitureElementConfig<?>[] elementConfigs,
FurnitureHitBoxConfig<?>[] furnitureHitBoxConfigs,
public record FurnitureVariant(String name,
@Nullable CullingData cullingData,
FurnitureElementConfig<?>[] elementConfigs,
FurnitureHitBoxConfig<?>[] hitBoxConfigs,
Optional<ExternalModel> externalModel,
Optional<Vector3f> dropOffset) {
}

View File

@@ -2,8 +2,14 @@ package net.momirealms.craftengine.core.entity.furniture.element;
import net.momirealms.craftengine.core.entity.player.Player;
import java.util.function.Consumer;
public interface FurnitureElement {
int[] virtualEntityIds();
void collectVirtualEntityId(Consumer<Integer> collector);
void show(Player player);
void hide(Player player);

View File

@@ -10,7 +10,11 @@ public abstract class AbstractFurnitureHitBoxConfig<H extends FurnitureHitBox> i
protected final boolean blocksBuilding;
protected final boolean canBeHitByProjectile;
public AbstractFurnitureHitBoxConfig(SeatConfig[] seats, Vector3f position, boolean canUseItemOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
public AbstractFurnitureHitBoxConfig(SeatConfig[] seats,
Vector3f position,
boolean canUseItemOn,
boolean blocksBuilding,
boolean canBeHitByProjectile) {
this.seats = seats;
this.position = position;
this.canUseItemOn = canUseItemOn;

View File

@@ -4,26 +4,41 @@ import net.momirealms.craftengine.core.entity.furniture.Collider;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.entity.seat.Seat;
import net.momirealms.craftengine.core.entity.seat.SeatOwner;
import net.momirealms.craftengine.core.world.EntityHitResult;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public interface FurnitureHitBox extends SeatOwner {
Seat<FurnitureHitBox>[] seats();
AABB aabb();
Vec3d position();
@Nullable
Collider collider();
Seat<FurnitureHitBox>[] seats();
AABB[] aabb();
List<Collider> colliders();
int[] virtualEntityIds();
void collectVirtualEntityIds(Consumer<Integer> collector);
void show(Player player);
void hide(Player player);
FurnitureHitBoxConfig<?> config();
default Optional<EntityHitResult> clip(Vec3d min, Vec3d max) {
for (AABB value : aabb()) {
Optional<EntityHitResult> clip = value.clip(min, max);
if (clip.isPresent()) {
return clip;
}
}
return Optional.empty();
}
}

View File

@@ -2,8 +2,12 @@ package net.momirealms.craftengine.core.entity.furniture.hitbox;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.core.world.collision.AABB;
import org.joml.Vector3f;
import java.util.function.Consumer;
public interface FurnitureHitBoxConfig<H extends FurnitureHitBox> {
H create(Furniture furniture);
@@ -17,4 +21,6 @@ public interface FurnitureHitBoxConfig<H extends FurnitureHitBox> {
boolean canBeHitByProjectile();
boolean canUseItemOn();
void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer);
}

View File

@@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.advancement.AdvancementType;
import net.momirealms.craftengine.core.block.entity.render.ConstantBlockEntityRenderer;
import net.momirealms.craftengine.core.entity.AbstractEntity;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.context.CooldownData;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
@@ -217,12 +218,18 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract void removeTrackedBlockEntities(Collection<BlockPos> renders);
public abstract void addTrackedFurniture(int entityId, Furniture furniture);
public abstract void clearTrackedBlockEntities();
@Override
public void remove() {
}
public abstract void removeTrackedFurniture(int entityId);
public abstract void clearTrackedFurniture();
public abstract WorldPosition eyePosition();
@Override

View File

@@ -14,7 +14,7 @@ public class FurnitureParameterProvider implements ChainParameterProvider<Furnit
static {
CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, f -> f.config().id());
CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Furniture::uuid);
CONTEXT_FUNCTIONS.put(DirectContextParameters.VARIANT, Furniture::getCurrentVariantName);
CONTEXT_FUNCTIONS.put(DirectContextParameters.VARIANT, f -> f.getCurrentVariant().name());
CONTEXT_FUNCTIONS.put(DirectContextParameters.X, furniture -> furniture.position().x());
CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, furniture -> furniture.position().y());
CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, furniture -> furniture.position().z());

View File

@@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.entity.player.Player;
public interface EntityPacketHandler {
default boolean handleEntitiesRemove(IntList entityIds) {
default boolean handleEntitiesRemove(NetWorkUser user, IntList entityIds) {
return false;
}

View File

@@ -266,6 +266,8 @@ public final class ResourceConfigUtils {
if (o == null) return new Vector3f();
if (o instanceof List<?> list && list.size() == 3) {
return new Vector3f(Float.parseFloat(list.get(0).toString()), Float.parseFloat(list.get(1).toString()), Float.parseFloat(list.get(2).toString()));
} else if (o instanceof Number number) {
return new Vector3f(number.floatValue());
} else {
String stringFormat = o.toString();
String[] split = stringFormat.split(",");