mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-27 02:49:15 +00:00
家具重构part1
This commit is contained in:
@@ -711,12 +711,8 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
}
|
||||
|
||||
private CullingData parseCullingData(Object arguments) {
|
||||
if (arguments instanceof Boolean b && !b) {
|
||||
return null;
|
||||
}
|
||||
if (!(arguments instanceof Map)) {
|
||||
return new CullingData(DEFAULT_BLOCK_ENTITY_AABB, Config.entityCullingViewDistance(), 0.5, true);
|
||||
}
|
||||
if (arguments instanceof Boolean b && !b) return null;
|
||||
if (!(arguments instanceof Map)) return new CullingData(DEFAULT_BLOCK_ENTITY_AABB, Config.entityCullingViewDistance(), 0.5, true);
|
||||
Map<String, Object> argumentsMap = ResourceConfigUtils.getAsMap(arguments, "entity-culling");
|
||||
return new CullingData(
|
||||
ResourceConfigUtils.getAsAABB(argumentsMap.getOrDefault("aabb", 1), "aabb"),
|
||||
|
||||
@@ -78,7 +78,7 @@ public abstract class BlockBehavior {
|
||||
return (boolean) superMethod.call();
|
||||
}
|
||||
|
||||
// 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType type
|
||||
// 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType id
|
||||
// 1.20.5+ BlockState state, PathComputationType pathComputationType
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return (boolean) superMethod.call();
|
||||
|
||||
@@ -41,6 +41,7 @@ public class BlockSettings {
|
||||
float friction = 0.6f;
|
||||
float speedFactor = 1f;
|
||||
float jumpFactor = 1f;
|
||||
Map<CustomDataType<?>, Object> customData = new IdentityHashMap<>(4);
|
||||
|
||||
private BlockSettings() {}
|
||||
|
||||
@@ -107,9 +108,29 @@ public class BlockSettings {
|
||||
newSettings.speedFactor = settings.speedFactor;
|
||||
newSettings.jumpFactor = settings.jumpFactor;
|
||||
newSettings.friction = settings.friction;
|
||||
newSettings.customData = new IdentityHashMap<>(settings.customData);
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getCustomData(CustomDataType<T> type) {
|
||||
return (T) this.customData.get(type);
|
||||
}
|
||||
|
||||
public void clearCustomData() {
|
||||
this.customData.clear();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T removeCustomData(CustomDataType<?> type) {
|
||||
return (T) this.customData.remove(type);
|
||||
}
|
||||
|
||||
public <T> void addCustomData(CustomDataType<T> key, T value) {
|
||||
this.customData.put(key, value);
|
||||
}
|
||||
|
||||
public Set<Key> tags() {
|
||||
return tags;
|
||||
}
|
||||
@@ -542,7 +563,7 @@ public class BlockSettings {
|
||||
}));
|
||||
}
|
||||
|
||||
private static void registerFactory(String id, Modifier.Factory factory) {
|
||||
public static void registerFactory(String id, Modifier.Factory factory) {
|
||||
FACTORIES.put(id, factory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.concurrent.Callable;
|
||||
|
||||
public interface IsPathFindableBlockBehavior {
|
||||
|
||||
// 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType type
|
||||
// 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType id
|
||||
// 1.20.5+ BlockState state, PathComputationType pathComputationType
|
||||
boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public abstract class BlockEntity {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public final CompoundTag saveAsTag() {
|
||||
public CompoundTag saveAsTag() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
this.saveId(tag);
|
||||
this.savePos(tag);
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
public final class BlockEntityTypeKeys {
|
||||
private BlockEntityTypeKeys() {}
|
||||
|
||||
public static final Key INACTIVE = Key.of("craftengine:inactive");
|
||||
public static final Key UNSAFE_COMPOSITE = Key.of("craftengine:unsafe_composite");
|
||||
public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage");
|
||||
public static final Key SIMPLE_PARTICLE = Key.of("craftengine:simple_particle");
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
public abstract class BlockEntityTypes {
|
||||
public static final BlockEntityType<InactiveBlockEntity> INACTIVE = register(BlockEntityTypeKeys.INACTIVE);
|
||||
|
||||
public static <T extends BlockEntity> BlockEntityType<T> register(Key id) {
|
||||
BlockEntityType<T> type = new BlockEntityType<>(id);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.momirealms.craftengine.core.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
|
||||
public class InactiveBlockEntity extends BlockEntity {
|
||||
private final CompoundTag tag;
|
||||
|
||||
public InactiveBlockEntity(BlockPos pos,
|
||||
ImmutableBlockState blockState,
|
||||
CompoundTag tag) {
|
||||
super(BlockEntityTypes.INACTIVE, pos, blockState);
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag saveAsTag() {
|
||||
return this.tag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.Cullable;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class CustomEntity implements Cullable {
|
||||
protected final CustomEntityType<?> type;
|
||||
protected final UUID uuid;
|
||||
protected WorldPosition position;
|
||||
protected boolean valid = true;
|
||||
|
||||
protected CustomEntity(CustomEntityType<?> type, WorldPosition position, UUID uuid) {
|
||||
this.position = position;
|
||||
this.type = type;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public CompoundTag saveAsTag() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
this.saveId(tag);
|
||||
this.savePos(tag);
|
||||
this.saveCustomData(tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
private void savePos(CompoundTag tag) {
|
||||
tag.putDouble("x", this.position.x());
|
||||
tag.putDouble("y", this.position.y());
|
||||
tag.putDouble("z", this.position.z());
|
||||
tag.putFloat("x_rot", this.position.xRot());
|
||||
tag.putFloat("y_rot", this.position.yRot());
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
public UUID uuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public double x() {
|
||||
return this.position.x();
|
||||
}
|
||||
|
||||
public double y() {
|
||||
return this.position.y();
|
||||
}
|
||||
|
||||
public double z() {
|
||||
return this.position.z();
|
||||
}
|
||||
|
||||
public float yRot() {
|
||||
return this.position.yRot();
|
||||
}
|
||||
|
||||
public float xRot() {
|
||||
return this.position.xRot();
|
||||
}
|
||||
|
||||
public CustomEntityType<?> entityType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
protected void saveCustomData(CompoundTag tag) {
|
||||
}
|
||||
|
||||
public void loadCustomData(CompoundTag tag) {
|
||||
}
|
||||
|
||||
private void saveId(CompoundTag tag) {
|
||||
tag.putString("id", this.type.id().asString());
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
this.valid = false;
|
||||
}
|
||||
|
||||
public static UUID readUUID(CompoundTag tag) {
|
||||
return tag.getUUID("uuid");
|
||||
}
|
||||
|
||||
public static WorldPosition readPos(CEWorld world, CompoundTag tag) {
|
||||
double x = tag.getDouble("x");
|
||||
double y = tag.getDouble("y");
|
||||
double z = tag.getDouble("z");
|
||||
float xRot = tag.getFloat("x_rot");
|
||||
float yRot = tag.getFloat("y_rot");
|
||||
return new WorldPosition(world.world, x, y, z, xRot, yRot);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record CustomEntityType<T extends CustomEntity>(Key id, Factory<T> factory) {
|
||||
|
||||
public interface Factory<T extends CustomEntity> {
|
||||
|
||||
T create(UUID uuid, WorldPosition position);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public final class CustomEntityTypeKeys {
|
||||
private CustomEntityTypeKeys() {}
|
||||
|
||||
public static final Key FURNITURE = Key.of("craftengine:furniture");
|
||||
public static final Key INACTIVE = Key.of("craftengine:inactive");
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
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;
|
||||
|
||||
public class CustomEntityTypes {
|
||||
public static final CustomEntityType<InactiveCustomEntity> INACTIVE = register(CustomEntityTypeKeys.INACTIVE, InactiveCustomEntity::new);
|
||||
|
||||
public static <T extends CustomEntity> CustomEntityType<T> register(Key id, CustomEntityType.Factory<T> factory) {
|
||||
CustomEntityType<T> type = new CustomEntityType<>(id, factory);
|
||||
((WritableRegistry<CustomEntityType<?>>) BuiltInRegistries.ENTITY_TYPE)
|
||||
.register(ResourceKey.create(Registries.ENTITY_TYPE.location(), id), type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.NBT;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class InactiveCustomEntity extends CustomEntity {
|
||||
public static final CompoundTag INVALID_TAG = new CompoundTag(Map.of("type", NBT.createString(CustomEntityTypes.INACTIVE.id().asMinimalString())));
|
||||
private final CompoundTag data;
|
||||
|
||||
public InactiveCustomEntity(UUID uuid, WorldPosition position) {
|
||||
super(CustomEntityTypes.INACTIVE, position, uuid);
|
||||
this.data = INVALID_TAG;
|
||||
}
|
||||
|
||||
public InactiveCustomEntity(UUID uuid, WorldPosition position, CompoundTag data) {
|
||||
super(CustomEntityTypes.INACTIVE, position, uuid);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag saveAsTag() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
// 不正常的数据不要存储
|
||||
return this.data != INVALID_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable CullingData cullingData() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
package net.momirealms.craftengine.core.entity.display;
|
||||
|
||||
public enum Billboard {
|
||||
FIXED(0),
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
package net.momirealms.craftengine.core.entity.display;
|
||||
|
||||
public enum ItemDisplayContext {
|
||||
NONE(0),
|
||||
@@ -1,89 +0,0 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class AbstractCustomFurniture implements CustomFurniture {
|
||||
private final Key id;
|
||||
private final FurnitureSettings settings;
|
||||
private final Map<AnchorType, Placement> placements;
|
||||
private final Map<EventTrigger, List<Function<Context>>> events;
|
||||
@Nullable
|
||||
private final LootTable<?> lootTable;
|
||||
|
||||
private final AnchorType anyType;
|
||||
|
||||
protected AbstractCustomFurniture(@NotNull Key id,
|
||||
@NotNull FurnitureSettings settings,
|
||||
@NotNull Map<AnchorType, Placement> placements,
|
||||
@NotNull Map<EventTrigger, List<Function<Context>>> events,
|
||||
@Nullable LootTable<?> lootTable) {
|
||||
this.id = id;
|
||||
this.settings = settings;
|
||||
this.placements = placements;
|
||||
this.lootTable = lootTable;
|
||||
this.events = events;
|
||||
this.anyType = placements.keySet().stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Context context, EventTrigger trigger) {
|
||||
for (Function<Context> function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) {
|
||||
function.run(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<AnchorType, Placement> placements() {
|
||||
return this.placements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FurnitureSettings settings() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable LootTable<?> lootTable() {
|
||||
return this.lootTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnchorType getAnyAnchorType() {
|
||||
return this.anyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedPlacement(AnchorType anchorType) {
|
||||
return this.placements.containsKey(anchorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placement getPlacement(AnchorType anchorType) {
|
||||
return this.placements.get(anchorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placement getValidPlacement(AnchorType anchorType) {
|
||||
Placement placement = this.placements.get(anchorType);
|
||||
if (placement == null) {
|
||||
return this.placements.get(getAnyAnchorType());
|
||||
}
|
||||
return placement;
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
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 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 position;
|
||||
private final Quaternionf rotation;
|
||||
private final boolean applyDyedColor;
|
||||
private final float shadowRadius;
|
||||
private final float shadowStrength;
|
||||
|
||||
public AbstractFurnitureElement(Key item,
|
||||
Billboard billboard,
|
||||
ItemDisplayContext transform,
|
||||
Vector3f scale,
|
||||
Vector3f translation,
|
||||
Vector3f position,
|
||||
Quaternionf rotation,
|
||||
float shadowRadius,
|
||||
float shadowStrength,
|
||||
boolean applyDyedColor) {
|
||||
this.billboard = billboard;
|
||||
this.transform = transform;
|
||||
this.scale = scale;
|
||||
this.translation = translation;
|
||||
this.item = item;
|
||||
this.rotation = rotation;
|
||||
this.position = position;
|
||||
this.applyDyedColor = applyDyedColor;
|
||||
this.shadowRadius = shadowRadius;
|
||||
this.shadowStrength = shadowStrength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float shadowRadius() {
|
||||
return shadowRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float shadowStrength() {
|
||||
return shadowStrength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyDyedColor() {
|
||||
return applyDyedColor;
|
||||
}
|
||||
|
||||
@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 position;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,24 @@
|
||||
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.entity.furniture.element.FurnitureElementConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxTypes;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.PendingConfigSection;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.config.IdSectionConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||
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.collision.AABB;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@@ -21,7 +26,7 @@ import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class AbstractFurnitureManager implements FurnitureManager {
|
||||
protected final Map<Key, CustomFurniture> byId = new HashMap<>();
|
||||
protected final Map<Key, FurnitureConfig> byId = new HashMap<>();
|
||||
private final CraftEngine plugin;
|
||||
private final FurnitureParser furnitureParser;
|
||||
// Cached command suggestions
|
||||
@@ -56,12 +61,12 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomFurniture> furnitureById(Key id) {
|
||||
public Optional<FurnitureConfig> furnitureById(Key id) {
|
||||
return Optional.ofNullable(this.byId.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Key, CustomFurniture> loadedFurniture() {
|
||||
public Map<Key, FurnitureConfig> loadedFurniture() {
|
||||
return Collections.unmodifiableMap(this.byId);
|
||||
}
|
||||
|
||||
@@ -72,10 +77,6 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
||||
|
||||
protected abstract HitBoxConfig defaultHitBox();
|
||||
|
||||
protected abstract FurnitureElement.Builder furnitureElementBuilder();
|
||||
|
||||
protected abstract CustomFurniture.Builder furnitureBuilder();
|
||||
|
||||
public class FurnitureParser extends IdSectionConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[] { "furniture" };
|
||||
private final List<PendingConfigSection> pendingConfigSections = new ArrayList<>();
|
||||
@@ -107,91 +108,72 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
||||
return LoadingSequence.FURNITURE;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, String node, Key id, Map<String, Object> section) {
|
||||
if (AbstractFurnitureManager.this.byId.containsKey(id)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.duplicate");
|
||||
}
|
||||
EnumMap<AnchorType, CustomFurniture.Placement> placements = new EnumMap<>(AnchorType.class);
|
||||
Object placementObj = section.get("placement");
|
||||
Map<String, Object> placementMap = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(placementObj, "warning.config.furniture.missing_placement"), false);
|
||||
if (placementMap.isEmpty()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.missing_placement");
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : placementMap.entrySet()) {
|
||||
// anchor type
|
||||
AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH));
|
||||
Map<String, Object> placementArguments = MiscUtils.castToMap(entry.getValue(), false);
|
||||
Optional<Vector3f> optionalLootSpawnOffset = Optional.ofNullable(placementArguments.get("loot-spawn-offset")).map(it -> ResourceConfigUtils.getAsVector3f(it, "loot-spawn-offset"));
|
||||
// furniture display elements
|
||||
List<FurnitureElement> elements = new ArrayList<>();
|
||||
List<Map<String, Object>> elementConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("elements", List.of());
|
||||
for (Map<String, Object> element : elementConfigs) {
|
||||
FurnitureElement furnitureElement = furnitureElementBuilder()
|
||||
.item(Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(element.get("item"), "warning.config.furniture.element.missing_item")))
|
||||
.applyDyedColor(ResourceConfigUtils.getAsBoolean(element.getOrDefault("apply-dyed-color", true), "apply-dyed-color"))
|
||||
.billboard(ResourceConfigUtils.getOrDefault(element.get("billboard"), o -> Billboard.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), Billboard.FIXED))
|
||||
.transform(ResourceConfigUtils.getOrDefault(ResourceConfigUtils.get(element, "transform", "display-transform"), o -> ItemDisplayContext.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), ItemDisplayContext.NONE))
|
||||
.scale(ResourceConfigUtils.getAsVector3f(element.getOrDefault("scale", "1"), "scale"))
|
||||
.position(ResourceConfigUtils.getAsVector3f(element.getOrDefault("position", "0"), "position"))
|
||||
.translation(ResourceConfigUtils.getAsVector3f(element.getOrDefault("translation", "0"), "translation"))
|
||||
.rotation(ResourceConfigUtils.getAsQuaternionf(element.getOrDefault("rotation", "0"), "rotation"))
|
||||
.shadowRadius(ResourceConfigUtils.getAsFloat(element.getOrDefault("shadow-radius", 0f), "shadow-radius"))
|
||||
.shadowStrength(ResourceConfigUtils.getAsFloat(element.getOrDefault("shadow-strength", 1f), "shadow-strength"))
|
||||
.build();
|
||||
elements.add(furnitureElement);
|
||||
}
|
||||
|
||||
// external model providers
|
||||
Map<String, Object> variantsMap = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "variants", "placement", "variant"), "warning.config.furniture.missing_variants"), "variants");
|
||||
if (variantsMap.isEmpty()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.missing_variants");
|
||||
}
|
||||
|
||||
Map<String, FurnitureVariant> variants = new HashMap<>();
|
||||
for (Map.Entry<String, Object> e0 : variantsMap.entrySet()) {
|
||||
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("elements"), FurnitureElementConfigs::fromMap);
|
||||
|
||||
// fixme 外部模型不应该在这
|
||||
Optional<ExternalModel> externalModel;
|
||||
if (placementArguments.containsKey("model-engine")) {
|
||||
externalModel = Optional.of(plugin.compatibilityManager().createModel("ModelEngine", placementArguments.get("model-engine").toString()));
|
||||
} else if (placementArguments.containsKey("better-model")) {
|
||||
externalModel = Optional.of(plugin.compatibilityManager().createModel("BetterModel", placementArguments.get("better-model").toString()));
|
||||
if (variantArguments.containsKey("model-engine")) {
|
||||
externalModel = Optional.of(plugin.compatibilityManager().createModel("ModelEngine", variantArguments.get("model-engine").toString()));
|
||||
} else if (variantArguments.containsKey("better-model")) {
|
||||
externalModel = Optional.of(plugin.compatibilityManager().createModel("BetterModel", variantArguments.get("better-model").toString()));
|
||||
} else {
|
||||
externalModel = Optional.empty();
|
||||
}
|
||||
|
||||
// add hitboxes
|
||||
List<HitBoxConfig> hitboxes = ResourceConfigUtils.parseConfigAsList(placementArguments.get("hitboxes"), HitBoxTypes::fromMap);
|
||||
List<HitBoxConfig> hitboxes = ResourceConfigUtils.parseConfigAsList(variantArguments.get("hitboxes"), HitBoxTypes::fromMap);
|
||||
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
|
||||
hitboxes = List.of(defaultHitBox());
|
||||
}
|
||||
|
||||
// rules
|
||||
Map<String, Object> ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true);
|
||||
if (ruleSection != null) {
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
anchorType,
|
||||
elements.toArray(new FurnitureElement[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("alignment"), o -> AlignmentRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), AlignmentRule.CENTER),
|
||||
externalModel,
|
||||
optionalLootSpawnOffset
|
||||
));
|
||||
} else {
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
anchorType,
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBoxConfig[0]),
|
||||
RotationRule.ANY,
|
||||
AlignmentRule.CENTER,
|
||||
externalModel,
|
||||
optionalLootSpawnOffset
|
||||
));
|
||||
}
|
||||
variants.put(variantName, new FurnitureVariant(
|
||||
elements.toArray(new FurnitureElementConfig[0]),
|
||||
hitboxes.toArray(new HitBoxConfig[0]),
|
||||
externalModel,
|
||||
optionalLootSpawnOffset
|
||||
));
|
||||
}
|
||||
|
||||
CustomFurniture furniture = furnitureBuilder()
|
||||
AABB maxAABB = null;
|
||||
|
||||
FurnitureConfig furniture = FurnitureConfig.builder()
|
||||
.id(id)
|
||||
.settings(FurnitureSettings.fromMap(MiscUtils.castToMap(section.get("settings"), true)))
|
||||
.placement(placements)
|
||||
.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);
|
||||
}
|
||||
|
||||
private CullingData parseCullingData(Object arguments, AABB maxHitbox) {
|
||||
if (arguments instanceof Boolean b && !b)
|
||||
return null;
|
||||
if (!(arguments instanceof Map))
|
||||
return new CullingData(maxHitbox, Config.entityCullingViewDistance(), 0.5, true);
|
||||
Map<String, Object> argumentsMap = ResourceConfigUtils.getAsMap(arguments, "entity-culling");
|
||||
return new CullingData(
|
||||
ResourceConfigUtils.getAsAABB(argumentsMap.getOrDefault("aabb", maxHitbox), "aabb"),
|
||||
ResourceConfigUtils.getAsInt(argumentsMap.getOrDefault("view-distance", Config.entityCullingViewDistance()), "view-distance"),
|
||||
ResourceConfigUtils.getAsDouble(argumentsMap.getOrDefault("aabb-expansion", 0.5), "aabb-expansion"),
|
||||
ResourceConfigUtils.getAsBoolean(argumentsMap.getOrDefault("ray-tracing", true), "ray-tracing")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
@Deprecated(since = "0.0.66", forRemoval = true)
|
||||
public enum AnchorType {
|
||||
GROUND(0),
|
||||
WALL(1),
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
// TODO 家具的设计存在问题。家具也应该存在不同的状态,而不是根据放置规则直接决定状态类型
|
||||
public interface CustomFurniture {
|
||||
|
||||
void execute(Context context, EventTrigger trigger);
|
||||
|
||||
Key id();
|
||||
|
||||
Map<AnchorType, Placement> placements();
|
||||
|
||||
FurnitureSettings settings();
|
||||
|
||||
@Nullable
|
||||
LootTable<?> lootTable();
|
||||
|
||||
AnchorType getAnyAnchorType();
|
||||
|
||||
boolean isAllowedPlacement(AnchorType anchorType);
|
||||
|
||||
Placement getPlacement(AnchorType anchorType);
|
||||
|
||||
Placement getValidPlacement(AnchorType anchorType);
|
||||
|
||||
interface Builder {
|
||||
|
||||
Builder id(Key id);
|
||||
|
||||
Builder placement(Map<AnchorType, Placement> placements);
|
||||
|
||||
Builder settings(FurnitureSettings settings);
|
||||
|
||||
Builder lootTable(LootTable<?> lootTable);
|
||||
|
||||
Builder events(Map<EventTrigger, List<Function<Context>>> events);
|
||||
|
||||
CustomFurniture build();
|
||||
}
|
||||
|
||||
record Placement(AnchorType anchorType,
|
||||
FurnitureElement[] elements,
|
||||
HitBoxConfig[] hitBoxConfigs,
|
||||
RotationRule rotationRule,
|
||||
AlignmentRule alignmentRule,
|
||||
Optional<ExternalModel> externalModel,
|
||||
Optional<Vector3f> dropOffset) {
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,28 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.entity.CustomEntity;
|
||||
import net.momirealms.craftengine.core.entity.CustomEntityType;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
public abstract class Furniture extends CustomEntity {
|
||||
protected final FurnitureConfig config;
|
||||
protected final FurnitureDataAccessor dataAccessor;
|
||||
|
||||
public interface Furniture {
|
||||
void initializeColliders();
|
||||
|
||||
WorldPosition position();
|
||||
|
||||
boolean isValid();
|
||||
|
||||
void destroy();
|
||||
|
||||
void destroyColliders();
|
||||
|
||||
void destroySeats();
|
||||
|
||||
UUID uuid();
|
||||
|
||||
int baseEntityId();
|
||||
|
||||
@Nullable
|
||||
HitBox hitBoxByEntityId(int id);
|
||||
|
||||
@Nullable HitBoxPart hitBoxPartByEntityId(int id);
|
||||
public Furniture(CustomEntityType<?> type, WorldPosition position, FurnitureConfig config, CompoundTag data) {
|
||||
super(type, position);
|
||||
this.dataAccessor = new FurnitureDataAccessor(data);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
AnchorType anchorType();
|
||||
public FurnitureConfig config() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Key id();
|
||||
|
||||
@NotNull
|
||||
CustomFurniture config();
|
||||
|
||||
boolean hasExternalModel();
|
||||
|
||||
FurnitureExtraData extraData();
|
||||
|
||||
void setExtraData(FurnitureExtraData extraData);
|
||||
|
||||
void save();
|
||||
public FurnitureDataAccessor dataAccessor() {
|
||||
return this.dataAccessor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface FurnitureConfig {
|
||||
|
||||
void execute(Context context, EventTrigger trigger);
|
||||
|
||||
Key id();
|
||||
|
||||
FurnitureSettings settings();
|
||||
|
||||
@Nullable
|
||||
LootTable<?> lootTable();
|
||||
|
||||
Map<String, FurnitureVariant> variants();
|
||||
|
||||
default FurnitureVariant anyVariant() {
|
||||
return variants().values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
default String anyVariantName() {
|
||||
return variants().keySet().stream().findFirst().get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
FurnitureVariant getVariant(String variantName);
|
||||
|
||||
@NotNull
|
||||
FurnitureBehavior behavior();
|
||||
|
||||
CullingData cullingData();
|
||||
|
||||
static Builder builder() {
|
||||
return new FurnitureConfigImpl.BuilderImpl();
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
|
||||
Builder id(Key id);
|
||||
|
||||
Builder variants(Map<String, FurnitureVariant> variants);
|
||||
|
||||
Builder settings(FurnitureSettings settings);
|
||||
|
||||
Builder lootTable(LootTable<?> lootTable);
|
||||
|
||||
Builder events(Map<EventTrigger, List<Function<Context>>> events);
|
||||
|
||||
Builder behavior(FurnitureBehavior behavior);
|
||||
|
||||
Builder cullingData(CullingData cullingData);
|
||||
|
||||
FurnitureConfig build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.momirealms.craftengine.core.entity.furniture.behavior.EmptyFurnitureBehavior;
|
||||
import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
class FurnitureConfigImpl implements FurnitureConfig {
|
||||
private final Key id;
|
||||
private final FurnitureSettings settings;
|
||||
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;
|
||||
|
||||
private FurnitureConfigImpl(@NotNull Key id,
|
||||
@NotNull FurnitureSettings settings,
|
||||
@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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Context context, EventTrigger trigger) {
|
||||
for (Function<Context> function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) {
|
||||
function.run(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FurnitureSettings settings() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable LootTable<?> lootTable() {
|
||||
return this.lootTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, FurnitureVariant> variants() {
|
||||
return this.variants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FurnitureBehavior behavior() {
|
||||
return this.behavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CullingData cullingData() {
|
||||
return this.cullingData;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FurnitureVariant getVariant(String variantName) {
|
||||
return this.variants.get(variantName);
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder {
|
||||
private Key id;
|
||||
private Map<String, FurnitureVariant> variants;
|
||||
private FurnitureSettings settings;
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder id(Key id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder variants(Map<String, FurnitureVariant> variants) {
|
||||
this.variants = variants;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder settings(FurnitureSettings settings) {
|
||||
this.settings = settings;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder lootTable(LootTable<?> lootTable) {
|
||||
this.lootTable = lootTable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder events(Map<EventTrigger, List<Function<Context>>> events) {
|
||||
this.events = events;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder cullingData(CullingData cullingData) {
|
||||
this.cullingData = cullingData;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder behavior(FurnitureBehavior behavior) {
|
||||
this.behavior = behavior;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,34 +6,53 @@ import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.util.Color;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.NBT;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FurnitureExtraData {
|
||||
public class FurnitureDataAccessor {
|
||||
public static final String ITEM = "item";
|
||||
public static final String DYED_COLOR = "dyed_color";
|
||||
public static final String FIREWORK_EXPLOSION_COLORS = "firework_explosion_colors";
|
||||
public static final String VARIANT = "variant";
|
||||
@ApiStatus.Obsolete
|
||||
public static final String ANCHOR_TYPE = "anchor_type";
|
||||
|
||||
private final CompoundTag data;
|
||||
|
||||
public FurnitureExtraData(CompoundTag data) {
|
||||
public FurnitureDataAccessor(CompoundTag data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static FurnitureExtraData of(CompoundTag data) {
|
||||
return new FurnitureExtraData(data);
|
||||
public static FurnitureDataAccessor of(CompoundTag data) {
|
||||
return new FurnitureDataAccessor(data);
|
||||
}
|
||||
|
||||
public CompoundTag copyTag() {
|
||||
return this.data.copy();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public CompoundTag unsafeTag() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public void addCustomData(String key, Tag value) {
|
||||
this.data.put(key, value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Tag getCustomData(String key) {
|
||||
return this.data.get(key);
|
||||
}
|
||||
|
||||
public void removeCustomData(String key) {
|
||||
this.data.remove(key);
|
||||
}
|
||||
|
||||
public Optional<Item<?>> item() {
|
||||
byte[] data = this.data.getByteArray(ITEM);
|
||||
if (data == null) return Optional.empty();
|
||||
@@ -45,73 +64,57 @@ public class FurnitureExtraData {
|
||||
}
|
||||
}
|
||||
|
||||
public void setItem(Item<?> item) {
|
||||
this.data.putByteArray(ITEM, item.toByteArray());
|
||||
}
|
||||
|
||||
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) {
|
||||
this.data.putIntArray(FIREWORK_EXPLOSION_COLORS, colors);
|
||||
}
|
||||
|
||||
public Optional<Color> dyedColor() {
|
||||
if (this.data.containsKey(DYED_COLOR)) return Optional.of(Color.fromDecimal(this.data.getInt(DYED_COLOR)));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public void setDyedColor(Color color) {
|
||||
this.data.putInt(DYED_COLOR, color.color());
|
||||
}
|
||||
|
||||
public Optional<String> variant() {
|
||||
return Optional.ofNullable(this.data.getString(VARIANT));
|
||||
}
|
||||
|
||||
public void setVariant(String variant) {
|
||||
this.data.putString(VARIANT, variant);
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public Optional<AnchorType> anchorType() {
|
||||
if (this.data.containsKey(ANCHOR_TYPE)) return Optional.of(AnchorType.byId(this.data.getInt(ANCHOR_TYPE)));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public FurnitureExtraData anchorType(AnchorType type) {
|
||||
@ApiStatus.Obsolete
|
||||
public FurnitureDataAccessor anchorType(AnchorType type) {
|
||||
this.data.putInt(ANCHOR_TYPE, type.getId());
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
public static FurnitureDataAccessor fromBytes(final byte[] data) throws IOException {
|
||||
return new FurnitureDataAccessor(NBT.fromBytes(data));
|
||||
}
|
||||
|
||||
public static FurnitureExtraData fromBytes(final byte[] data) throws IOException {
|
||||
return new FurnitureExtraData(NBT.fromBytes(data));
|
||||
}
|
||||
|
||||
public static byte[] toBytes(final FurnitureExtraData data) throws IOException {
|
||||
public static byte[] toBytes(final FurnitureDataAccessor data) throws IOException {
|
||||
return NBT.toBytes(data.data);
|
||||
}
|
||||
|
||||
public byte[] toBytes() throws IOException {
|
||||
return toBytes(this);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final CompoundTag data;
|
||||
|
||||
public Builder() {
|
||||
this.data = new CompoundTag();
|
||||
}
|
||||
|
||||
public Builder item(Item<?> item) {
|
||||
this.data.putByteArray(ITEM, item.toByteArray());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder dyedColor(Color color) {
|
||||
if (color == null) return this;
|
||||
this.data.putInt(DYED_COLOR, color.color());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fireworkExplosionColors(int[] colors) {
|
||||
if (colors == null) return this;
|
||||
this.data.putIntArray(FIREWORK_EXPLOSION_COLORS, colors);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder anchorType(AnchorType type) {
|
||||
this.data.putInt(ANCHOR_TYPE, type.getId());
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnitureExtraData build() {
|
||||
return new FurnitureExtraData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface FurnitureElement {
|
||||
Quaternionf rotation();
|
||||
|
||||
Key item();
|
||||
|
||||
Billboard billboard();
|
||||
|
||||
ItemDisplayContext transform();
|
||||
|
||||
float shadowRadius();
|
||||
|
||||
float shadowStrength();
|
||||
|
||||
boolean applyDyedColor();
|
||||
|
||||
Vector3f scale();
|
||||
|
||||
Vector3f translation();
|
||||
|
||||
Vector3f position();
|
||||
|
||||
void initPackets(Furniture furniture, int entityId, @NotNull Quaternionf conjugated, Consumer<Object> packets);
|
||||
|
||||
interface Builder {
|
||||
|
||||
Builder item(Key item);
|
||||
|
||||
Builder billboard(Billboard billboard);
|
||||
|
||||
Builder transform(ItemDisplayContext transform);
|
||||
|
||||
Builder scale(Vector3f scale);
|
||||
|
||||
Builder translation(Vector3f translation);
|
||||
|
||||
Builder position(Vector3f position);
|
||||
|
||||
Builder rotation(Quaternionf rotation);
|
||||
|
||||
Builder applyDyedColor(boolean applyDyedColor);
|
||||
|
||||
Builder shadowStrength(float shadowStrength);
|
||||
|
||||
Builder shadowRadius(float shadowRadius);
|
||||
|
||||
FurnitureElement build();
|
||||
}
|
||||
}
|
||||
@@ -25,11 +25,11 @@ public interface FurnitureManager extends Manageable {
|
||||
|
||||
Collection<Suggestion> cachedSuggestions();
|
||||
|
||||
Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound);
|
||||
Furniture place(WorldPosition position, FurnitureConfig furniture, FurnitureDataAccessor extraData, boolean playSound);
|
||||
|
||||
Optional<CustomFurniture> furnitureById(Key id);
|
||||
Optional<FurnitureConfig> furnitureById(Key id);
|
||||
|
||||
Map<Key, CustomFurniture> loadedFurniture();
|
||||
Map<Key, FurnitureConfig> loadedFurniture();
|
||||
|
||||
boolean isFurnitureRealEntity(int entityId);
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.CustomDataType;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FurnitureSettings {
|
||||
@@ -13,6 +15,7 @@ public class FurnitureSettings {
|
||||
FurnitureSounds sounds = FurnitureSounds.EMPTY;
|
||||
@Nullable
|
||||
Key itemId;
|
||||
Map<CustomDataType<?>, Object> customData = new IdentityHashMap<>(4);
|
||||
|
||||
private FurnitureSettings() {}
|
||||
|
||||
@@ -29,6 +32,7 @@ public class FurnitureSettings {
|
||||
newSettings.sounds = settings.sounds;
|
||||
newSettings.itemId = settings.itemId;
|
||||
newSettings.minimized = settings.minimized;
|
||||
newSettings.customData = new IdentityHashMap<>(settings.customData);
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
@@ -45,6 +49,25 @@ public class FurnitureSettings {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getCustomData(CustomDataType<T> type) {
|
||||
return (T) this.customData.get(type);
|
||||
}
|
||||
|
||||
public void clearCustomData() {
|
||||
this.customData.clear();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T removeCustomData(CustomDataType<?> type) {
|
||||
return (T) this.customData.remove(type);
|
||||
}
|
||||
|
||||
public <T> void addCustomData(CustomDataType<T> key, T value) {
|
||||
this.customData.put(key, value);
|
||||
}
|
||||
|
||||
public FurnitureSounds sounds() {
|
||||
return sounds;
|
||||
}
|
||||
@@ -103,7 +126,7 @@ public class FurnitureSettings {
|
||||
}));
|
||||
}
|
||||
|
||||
private static void registerFactory(String id, FurnitureSettings.Modifier.Factory factory) {
|
||||
public static void registerFactory(String id, FurnitureSettings.Modifier.Factory factory) {
|
||||
FACTORIES.put(id, factory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public record FurnitureVariant(FurnitureElementConfig<?>[] elements,
|
||||
HitBoxConfig[] hitBoxConfigs,
|
||||
Optional<ExternalModel> externalModel,
|
||||
Optional<Vector3f> dropOffset) {
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
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,7 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
||||
|
||||
public final class EmptyFurnitureBehavior implements FurnitureBehavior {
|
||||
private EmptyFurnitureBehavior() {}
|
||||
|
||||
public static final EmptyFurnitureBehavior INSTANCE = new EmptyFurnitureBehavior();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.tick.FurnitureTicker;
|
||||
|
||||
public interface FurnitureBehavior {
|
||||
|
||||
default <T extends Furniture> FurnitureTicker<T> createSyncFurnitureTicker(T furniture) {
|
||||
return null;
|
||||
}
|
||||
|
||||
default <T extends Furniture> FurnitureTicker<T> createAsyncBlockEntityTicker(T furniture) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.element;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
|
||||
public interface FurnitureElement {
|
||||
|
||||
void show(Player player);
|
||||
|
||||
void hide(Player player);
|
||||
|
||||
default void deactivate() {}
|
||||
|
||||
default void activate() {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.element;
|
||||
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface FurnitureElementConfig<E extends FurnitureElement> {
|
||||
|
||||
E create(@NotNull WorldPosition position);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.element;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface FurnitureElementConfigFactory {
|
||||
|
||||
<E extends FurnitureElement> FurnitureElementConfig<E> create(Map<String, Object> args);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.element;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
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 FurnitureElementConfigs {
|
||||
public static final Key ITEM_DISPLAY = Key.of("craftengine:item_display");
|
||||
public static final Key TEXT_DISPLAY = Key.of("craftengine:text_display");
|
||||
public static final Key ITEM = Key.of("craftengine:item");
|
||||
|
||||
public static void register(Key key, FurnitureElementConfigFactory type) {
|
||||
((WritableRegistry<FurnitureElementConfigFactory>) BuiltInRegistries.FURNITURE_ELEMENT_TYPE)
|
||||
.register(ResourceKey.create(Registries.FURNITURE_ELEMENT_TYPE.location(), key), type);
|
||||
}
|
||||
|
||||
public static <E extends FurnitureElement> FurnitureElementConfig<E> fromMap(Map<String, Object> arguments) {
|
||||
Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(it -> Key.withDefaultNamespace(it, "craftengine")).orElse(ITEM_DISPLAY);
|
||||
FurnitureElementConfigFactory factory = BuiltInRegistries.FURNITURE_ELEMENT_TYPE.getValue(type);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.element.invalid_type", type.toString());
|
||||
}
|
||||
return factory.create(arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||
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 abstract class AbstractHitBox implements HitBox {
|
||||
private final Furniture furniture;
|
||||
private final HitBoxConfig config;
|
||||
private final HitBoxPart[] parts;
|
||||
private Seat<HitBox>[] seats;
|
||||
|
||||
public AbstractHitBox(Furniture furniture, HitBoxConfig config, HitBoxPart[] parts) {
|
||||
this.parts = parts;
|
||||
this.config = config;
|
||||
this.furniture = furniture;
|
||||
}
|
||||
|
||||
protected abstract void createSeats(HitBoxConfig config);
|
||||
|
||||
@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.entityId());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import org.joml.Vector3f;
|
||||
@@ -30,16 +30,16 @@ public abstract class AbstractHitBoxConfig implements HitBoxConfig {
|
||||
|
||||
@Override
|
||||
public boolean blocksBuilding() {
|
||||
return blocksBuilding;
|
||||
return this.blocksBuilding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHitByProjectile() {
|
||||
return canBeHitByProjectile;
|
||||
return this.canBeHitByProjectile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUseItemOn() {
|
||||
return canUseItemOn;
|
||||
return this.canUseItemOn;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatOwner;
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public interface HitBoxConfig {
|
||||
|
||||
Key type();
|
||||
|
||||
SeatConfig[] seats();
|
||||
|
||||
Vector3f position();
|
||||
|
||||
boolean blocksBuilding();
|
||||
|
||||
boolean canBeHitByProjectile();
|
||||
|
||||
boolean canUseItemOn();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
@@ -14,6 +14,7 @@ public class HitBoxTypes {
|
||||
public static final Key INTERACTION = Key.of("minecraft:interaction");
|
||||
public static final Key SHULKER = Key.of("minecraft:shulker");
|
||||
public static final Key HAPPY_GHAST = Key.of("minecraft:happy_ghast");
|
||||
public static final Key VIRTUAL = Key.of("minecraft:virtual");
|
||||
public static final Key CUSTOM = Key.of("minecraft:custom");
|
||||
|
||||
public static void register(Key key, HitBoxConfigFactory factory) {
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture.tick;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
|
||||
public interface FurnitureTicker<T extends Furniture> {
|
||||
|
||||
void tick(T furniture);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
package net.momirealms.craftengine.core.entity.item;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.core.entity.projectile;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.entity.display.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.display.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.Optional;
|
||||
* This interface provides methods for managing item properties such as custom model data,
|
||||
* damage, display name, lore, enchantments, and tags.
|
||||
*
|
||||
* @param <I> the type of the item implementation
|
||||
* @param <I> the id of the item implementation
|
||||
*/
|
||||
public interface Item<I> {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.entity.display.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.display.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta;
|
||||
import net.momirealms.craftengine.core.item.equipment.ComponentBasedEquipment;
|
||||
import net.momirealms.craftengine.core.item.equipment.Equipment;
|
||||
@@ -134,6 +134,12 @@ public class ItemSettings {
|
||||
this.customData.clear();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T removeCustomData(CustomDataType<?> type) {
|
||||
return (T) this.customData.remove(type);
|
||||
}
|
||||
|
||||
public <T> void addCustomData(CustomDataType<T> key, T value) {
|
||||
this.customData.put(key, value);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ public class CustomSmithingTransformRecipe<T> extends AbstractedFixedResultRecip
|
||||
@Override
|
||||
public CustomSmithingTransformRecipe<A> readMap(Key id, Map<String, Object> arguments) {
|
||||
List<String> base = MiscUtils.getAsStringList(arguments.get("base"));
|
||||
List<String> template = MiscUtils.getAsStringList(arguments.get("template-type"));
|
||||
List<String> template = MiscUtils.getAsStringList(arguments.get("template-id"));
|
||||
List<String> addition = MiscUtils.getAsStringList(arguments.get("addition"));
|
||||
boolean mergeComponents = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("merge-components", true), "merge-components");
|
||||
boolean mergeEnchantments = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("merge-enchantments", false), "merge-enchantments");
|
||||
|
||||
@@ -141,7 +141,7 @@ public class CustomSmithingTrimRecipe<T> extends AbstractRecipe<T>
|
||||
@Override
|
||||
public CustomSmithingTrimRecipe<A> readMap(Key id, Map<String, Object> arguments) {
|
||||
List<String> base = MiscUtils.getAsStringList(arguments.get("base"));
|
||||
List<String> template = MiscUtils.getAsStringList(arguments.get("template-type"));
|
||||
List<String> template = MiscUtils.getAsStringList(arguments.get("template-id"));
|
||||
List<String> addition = MiscUtils.getAsStringList(arguments.get("addition"));
|
||||
Key pattern = VersionHelper.isOrAbove1_21_5() ? Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("pattern"), "warning.config.recipe.smithing_trim.missing_pattern")) : null;
|
||||
return new CustomSmithingTrimRecipe<>(id,
|
||||
|
||||
@@ -87,12 +87,12 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
public static Formula fromMap(Map<String, Object> map) {
|
||||
String type = (String) map.get("type");
|
||||
if (type == null) {
|
||||
throw new NullPointerException("number type cannot be null");
|
||||
throw new NullPointerException("number id cannot be null");
|
||||
}
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
FormulaFactory factory = BuiltInRegistries.FORMULA_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Unknown formula type: " + type);
|
||||
throw new IllegalArgumentException("Unknown formula id: " + type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class ItemModels {
|
||||
Key key = Key.withDefaultNamespace(type, "minecraft");
|
||||
ItemModelReader reader = BuiltInRegistries.ITEM_MODEL_READER.getValue(key);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("Invalid item model type: " + key);
|
||||
throw new IllegalArgumentException("Invalid item model id: " + key);
|
||||
}
|
||||
return reader.read(json);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class ConditionProperties {
|
||||
Key key = Key.withDefaultNamespace(type, "minecraft");
|
||||
ConditionPropertyReader reader = BuiltInRegistries.CONDITION_PROPERTY_READER.getValue(key);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("Invalid condition property type: " + key);
|
||||
throw new IllegalArgumentException("Invalid condition property id: " + key);
|
||||
}
|
||||
return reader.read(json);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class RangeDispatchProperties {
|
||||
Key key = Key.withDefaultNamespace(type, "minecraft");
|
||||
RangeDispatchPropertyReader reader = BuiltInRegistries.RANGE_DISPATCH_PROPERTY_READER.getValue(key);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("Invalid range dispatch property type: " + key);
|
||||
throw new IllegalArgumentException("Invalid range dispatch property id: " + key);
|
||||
}
|
||||
return reader.read(json);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class SelectProperties {
|
||||
Key key = Key.withDefaultNamespace(type, "minecraft");
|
||||
SelectPropertyReader reader = BuiltInRegistries.SELECT_PROPERTY_READER.getValue(key);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("Invalid select property type: " + key);
|
||||
throw new IllegalArgumentException("Invalid select property id: " + key);
|
||||
}
|
||||
return reader.read(json);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class SignSpecialModel implements SpecialModel {
|
||||
@Override
|
||||
public SpecialModel create(Map<String, Object> arguments) {
|
||||
Key type = Key.of(arguments.get("type").toString());
|
||||
String woodType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("wood-type"), "warning.config.item.model.special.sign.missing_wood_type");
|
||||
String woodType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("wood-id"), "warning.config.item.model.special.sign.missing_wood_type");
|
||||
String texture = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("texture"), "warning.config.item.model.special.sign.missing_texture");
|
||||
return new SignSpecialModel(type, woodType, texture);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class SpecialModels {
|
||||
Key key = Key.withDefaultNamespace(type, "minecraft");
|
||||
SpecialModelReader reader = BuiltInRegistries.SPECIAL_MODEL_READER.getValue(key);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("Invalid special model type: " + key);
|
||||
throw new IllegalArgumentException("Invalid special model id: " + key);
|
||||
}
|
||||
return reader.read(json);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class Tints {
|
||||
Key key = Key.withDefaultNamespace(type, "minecraft");
|
||||
TintReader reader = BuiltInRegistries.TINT_READER.getValue(key);
|
||||
if (reader == null) {
|
||||
throw new IllegalArgumentException("Invalid tint type: " + type);
|
||||
throw new IllegalArgumentException("Invalid tint id: " + type);
|
||||
}
|
||||
return reader.read(json);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public enum ObfA {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown resource type: " + xclf);
|
||||
throw new IllegalArgumentException("Unknown resource id: " + xclf);
|
||||
}
|
||||
|
||||
public static final byte[] VALUES = new byte[] {
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.UUID;
|
||||
/**
|
||||
* Simple implementation of {@link Sender} using a {@link SenderFactory}
|
||||
*
|
||||
* @param <T> the command sender type
|
||||
* @param <T> the command sender id
|
||||
*/
|
||||
public final class AbstractSender<T> implements Sender {
|
||||
private final Plugin plugin;
|
||||
|
||||
@@ -448,10 +448,10 @@ public class Config {
|
||||
|
||||
// furniture
|
||||
furniture$hide_base_entity = config.getBoolean("furniture.hide-base-entity", true);
|
||||
furniture$collision_entity_type = ColliderType.valueOf(config.getString("furniture.collision-entity-type", "interaction").toUpperCase(Locale.ENGLISH));
|
||||
furniture$collision_entity_type = ColliderType.valueOf(config.getString("furniture.collision-entity-id", "interaction").toUpperCase(Locale.ENGLISH));
|
||||
|
||||
// equipment
|
||||
equipment$sacrificed_vanilla_armor$type = config.getString("equipment.sacrificed-vanilla-armor.type", "chainmail").toLowerCase(Locale.ENGLISH);
|
||||
equipment$sacrificed_vanilla_armor$type = config.getString("equipment.sacrificed-vanilla-armor.id", "chainmail").toLowerCase(Locale.ENGLISH);
|
||||
if (!AbstractPackManager.ALLOWED_VANILLA_EQUIPMENT.contains(equipment$sacrificed_vanilla_armor$type)) {
|
||||
TranslationManager.instance().log("warning.config.equipment.invalid_sacrificed_armor", equipment$sacrificed_vanilla_armor$type);
|
||||
equipment$sacrificed_vanilla_armor$type = "chainmail";
|
||||
|
||||
@@ -259,7 +259,7 @@ public class StringKeyConstructor extends SafeConstructor {
|
||||
if (value instanceof Number number) {
|
||||
return number.byteValue();
|
||||
}
|
||||
throw new RuntimeException("Unexpected type: " + value.getClass().getName());
|
||||
throw new RuntimeException("Unexpected id: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ public class StringKeyConstructor extends SafeConstructor {
|
||||
if (value instanceof Number number) {
|
||||
return number.shortValue();
|
||||
}
|
||||
throw new RuntimeException("Unexpected type: " + value.getClass().getName());
|
||||
throw new RuntimeException("Unexpected id: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ public class StringKeyConstructor extends SafeConstructor {
|
||||
if (value instanceof Number number) {
|
||||
return number.longValue();
|
||||
}
|
||||
throw new RuntimeException("Unexpected type: " + value.getClass().getName());
|
||||
throw new RuntimeException("Unexpected id: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ public class StringKeyConstructor extends SafeConstructor {
|
||||
if (value instanceof Number number) {
|
||||
return number.floatValue();
|
||||
}
|
||||
throw new RuntimeException("Unexpected type: " + value.getClass().getName());
|
||||
throw new RuntimeException("Unexpected id: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ public class StringKeyConstructor extends SafeConstructor {
|
||||
if (value instanceof Number number) {
|
||||
return number.doubleValue();
|
||||
}
|
||||
throw new RuntimeException("Unexpected type: " + value.getClass().getName());
|
||||
throw new RuntimeException("Unexpected id: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class ExpressionTemplateArgument implements TemplateArgument {
|
||||
public TemplateArgument create(Map<String, Object> arguments) {
|
||||
return new ExpressionTemplateArgument(
|
||||
arguments.getOrDefault("expression", "").toString(),
|
||||
ValueType.valueOf(arguments.getOrDefault("value-type", "double").toString().toUpperCase(Locale.ROOT))
|
||||
ValueType.valueOf(arguments.getOrDefault("value-id", "double").toString().toUpperCase(Locale.ROOT))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class TemplateArguments {
|
||||
Key key = Key.withDefaultNamespace(type0, Key.DEFAULT_NAMESPACE);
|
||||
TemplateArgumentFactory factory = BuiltInRegistries.TEMPLATE_ARGUMENT_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Unknown argument type: " + type);
|
||||
throw new IllegalArgumentException("Unknown argument id: " + type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class DamageFunction<CTX extends Context> extends AbstractConditionalFunc
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
PlayerSelector<CTX> selector = PlayerSelectors.fromObject(arguments.getOrDefault("target", "self"), conditionFactory());
|
||||
Key damageType = Key.of(ResourceConfigUtils.getAsStringOrNull(arguments.getOrDefault("damage-type", "generic")));
|
||||
Key damageType = Key.of(ResourceConfigUtils.getAsStringOrNull(arguments.getOrDefault("damage-id", "generic")));
|
||||
NumberProvider amount = NumberProviders.fromObject(arguments.getOrDefault("amount", 1f));
|
||||
return new DamageFunction<>(selector, damageType, amount, getPredicates(arguments));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class OpenWindowFunction<CTX extends Context> extends AbstractConditional
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
String title = Optional.ofNullable(arguments.get("title")).map(String::valueOf).orElse(null);
|
||||
String rawType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("gui-type"), "warning.config.function.open_window.missing_gui_type");
|
||||
String rawType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("gui-id"), "warning.config.function.open_window.missing_gui_type");
|
||||
try {
|
||||
GuiType type = GuiType.valueOf(rawType.toUpperCase(Locale.ENGLISH));
|
||||
return new OpenWindowFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), type, title);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class RemoveFurnitureFunction<CTX extends Context> extends AbstractCondit
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position)
|
||||
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
||||
.withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.extraData().item().orElse(null));
|
||||
.withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.dataAccessor().item().orElse(null));
|
||||
Optional<Player> optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER);
|
||||
Player player = optionalPlayer.orElse(null);
|
||||
if (player != null) {
|
||||
|
||||
@@ -94,7 +94,7 @@ public class ReplaceFurnitureFunction<CTX extends Context> extends AbstractCondi
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "<arg:furniture.z>"));
|
||||
NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", "<arg:furniture.pitch>"));
|
||||
NumberProvider yaw = NumberProviders.fromObject(arguments.getOrDefault("yaw", "<arg:furniture.yaw>"));
|
||||
AnchorType anchorType = ResourceConfigUtils.getAsEnum(arguments.get("anchor-type"), AnchorType.class, null);
|
||||
AnchorType anchorType = ResourceConfigUtils.getAsEnum(arguments.get("anchor-id"), AnchorType.class, null);
|
||||
boolean dropLoot = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("drop-loot", true), "drop-loot");
|
||||
boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound");
|
||||
return new ReplaceFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, anchorType, dropLoot, playSound, getPredicates(arguments));
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.function;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
@@ -15,7 +12,6 @@ import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||
private final Key furnitureId;
|
||||
@@ -24,7 +20,7 @@ public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditi
|
||||
private final NumberProvider z;
|
||||
private final NumberProvider pitch;
|
||||
private final NumberProvider yaw;
|
||||
private final AnchorType anchorType;
|
||||
private final String variant;
|
||||
private final boolean playSound;
|
||||
|
||||
public SpawnFurnitureFunction(
|
||||
@@ -34,7 +30,7 @@ public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditi
|
||||
NumberProvider z,
|
||||
NumberProvider pitch,
|
||||
NumberProvider yaw,
|
||||
AnchorType anchorType,
|
||||
String variant,
|
||||
boolean playSound,
|
||||
List<Condition<CTX>> predicates
|
||||
) {
|
||||
@@ -45,7 +41,7 @@ public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditi
|
||||
this.z = z;
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
this.anchorType = anchorType;
|
||||
this.variant = variant;
|
||||
this.playSound = playSound;
|
||||
}
|
||||
|
||||
@@ -59,17 +55,18 @@ public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditi
|
||||
float pitchValue = this.pitch.getFloat(ctx);
|
||||
float yawValue = this.yaw.getFloat(ctx);
|
||||
WorldPosition position = new WorldPosition(world, xPos, yPos, zPos, pitchValue, yawValue);
|
||||
spawnFurniture(this.furnitureId, position, this.anchorType, this.playSound);
|
||||
// fixme api
|
||||
// spawnFurniture(this.furnitureId, position, this.anchorType, this.playSound);
|
||||
});
|
||||
}
|
||||
|
||||
public static void spawnFurniture(Key furnitureId, WorldPosition position, AnchorType anchorType, boolean playSound) {
|
||||
CraftEngine.instance().furnitureManager().furnitureById(furnitureId).ifPresent(furniture -> {
|
||||
AnchorType anchor = Optional.ofNullable(anchorType).orElse(furniture.getAnyAnchorType());
|
||||
FurnitureExtraData extraData = FurnitureExtraData.builder().anchorType(anchor).build();
|
||||
CraftEngine.instance().furnitureManager().place(position, furniture, extraData, playSound);
|
||||
});
|
||||
}
|
||||
// public static void spawnFurniture(Key furnitureId, WorldPosition position, AnchorType anchorType, boolean playSound) {
|
||||
// CraftEngine.instance().furnitureManager().furnitureById(furnitureId).ifPresent(furniture -> {
|
||||
// AnchorType anchor = Optional.ofNullable(anchorType).orElse(furniture.getAnyAnchorType());
|
||||
// FurnitureDataAccessor extraData = FurnitureDataAccessor.builder().anchorType(anchor).build();
|
||||
// CraftEngine.instance().furnitureManager().place(position, furniture, extraData, playSound);
|
||||
// });
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
@@ -90,9 +87,9 @@ public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditi
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "<arg:position.z>"));
|
||||
NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", "<arg:position.pitch>"));
|
||||
NumberProvider yaw = NumberProviders.fromObject(arguments.getOrDefault("yaw", "<arg:position.yaw>"));
|
||||
AnchorType anchorType = ResourceConfigUtils.getAsEnum(arguments.get("anchor-type"), AnchorType.class, null);
|
||||
String variant = ResourceConfigUtils.getAsStringOrNull(ResourceConfigUtils.get(arguments, "variant", "anchor-id"));
|
||||
boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound");
|
||||
return new SpawnFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, anchorType, playSound, getPredicates(arguments));
|
||||
return new SpawnFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, variant, playSound, getPredicates(arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ToastFunction<CTX extends Context> extends AbstractConditionalFunct
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
AdvancementType advancementType;
|
||||
String advancementName = arguments.getOrDefault("advancement-type", "goal").toString();
|
||||
String advancementName = arguments.getOrDefault("advancement-id", "goal").toString();
|
||||
try {
|
||||
advancementType = AdvancementType.valueOf(advancementName.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.parameter;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.entity.ItemEntity;
|
||||
import net.momirealms.craftengine.core.entity.item.ItemEntity;
|
||||
import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextKey;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class LangData {
|
||||
temp.put(result, entry.getValue());
|
||||
}
|
||||
},
|
||||
() -> CraftEngine.instance().logger().warn("Unknown lang type: " + key)
|
||||
() -> CraftEngine.instance().logger().warn("Unknown lang id: " + key)
|
||||
);
|
||||
} else {
|
||||
temp.put(key, entry.getValue());
|
||||
|
||||
@@ -5,7 +5,9 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.CustomEntityType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfigFactory;
|
||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
||||
@@ -88,9 +90,11 @@ public class BuiltInRegistries {
|
||||
public static final Registry<PostProcessor.Type<?>> RECIPE_POST_PROCESSOR_TYPE = createConstantBoundRegistry(Registries.RECIPE_POST_PROCESSOR_TYPE, 16);
|
||||
public static final Registry<ItemUpdaterType<?>> ITEM_UPDATER_TYPE = createConstantBoundRegistry(Registries.ITEM_UPDATER_TYPE, 16);
|
||||
public static final Registry<NetworkCodec<FriendlyByteBuf, ? extends ModPacket>> MOD_PACKET = createConstantBoundRegistry(Registries.MOD_PACKET, 16);
|
||||
public static final Registry<BlockEntityType<?>> BLOCK_ENTITY_TYPE = createConstantBoundRegistry(Registries.BLOCK_ENTITY_TYPE, 128);
|
||||
public static final Registry<BlockEntityType<?>> BLOCK_ENTITY_TYPE = createConstantBoundRegistry(Registries.BLOCK_ENTITY_TYPE, 64);
|
||||
public static final Registry<BlockEntityElementConfigFactory> BLOCK_ENTITY_ELEMENT_TYPE = createConstantBoundRegistry(Registries.BLOCK_ENTITY_ELEMENT_TYPE, 16);
|
||||
public static final Registry<CraftRemainderFactory> CRAFT_REMAINDER_FACTORY = createConstantBoundRegistry(Registries.CRAFT_REMAINDER_FACTORY, 16);
|
||||
public static final Registry<CustomEntityType<?>> ENTITY_TYPE = createConstantBoundRegistry(Registries.ENTITY_TYPE, 32);
|
||||
public static final Registry<FurnitureElementConfigFactory> FURNITURE_ELEMENT_TYPE = createConstantBoundRegistry(Registries.FURNITURE_ELEMENT_TYPE, 16);
|
||||
|
||||
private static <T> Registry<T> createConstantBoundRegistry(ResourceKey<? extends Registry<T>> key, int expectedSize) {
|
||||
return new ConstantBoundRegistry<>(key, expectedSize);
|
||||
|
||||
@@ -5,7 +5,9 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.CustomEntityType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfigFactory;
|
||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
||||
@@ -93,4 +95,6 @@ public class Registries {
|
||||
public static final ResourceKey<Registry<BlockEntityType<?>>> BLOCK_ENTITY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block_entity_type"));
|
||||
public static final ResourceKey<Registry<BlockEntityElementConfigFactory>> BLOCK_ENTITY_ELEMENT_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block_entity_element_type"));
|
||||
public static final ResourceKey<Registry<CraftRemainderFactory>> CRAFT_REMAINDER_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("craft_remainder_factory"));
|
||||
public static final ResourceKey<Registry<CustomEntityType<?>>> ENTITY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("entity_type"));
|
||||
public static final ResourceKey<Registry<FurnitureElementConfigFactory>> FURNITURE_ELEMENT_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("furniture_element_type"));
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public record SoundData(Key id, SoundValue volume, SoundValue pitch) {
|
||||
SoundValue pitchValue = Optional.ofNullable(SoundValue.of(map.get("pitch"))).orElse(volume);
|
||||
return new SoundData(id, volumeValue, pitchValue);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Illegal object type for sound data: " + obj.getClass());
|
||||
throw new IllegalArgumentException("Illegal object id for sound data: " + obj.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import java.util.Objects;
|
||||
* A generic class representing a pair of values.
|
||||
* This class provides methods to create and access pairs of values.
|
||||
*
|
||||
* @param <L> the type of the left value
|
||||
* @param <R> the type of the right value
|
||||
* @param <L> the id of the left value
|
||||
* @param <R> the id of the right value
|
||||
*/
|
||||
public record Pair<L, R>(L left, R right) {
|
||||
|
||||
@@ -16,8 +16,8 @@ public record Pair<L, R>(L left, R right) {
|
||||
*
|
||||
* @param left the left value
|
||||
* @param right the right value
|
||||
* @param <L> the type of the left value
|
||||
* @param <R> the type of the right value
|
||||
* @param <L> the id of the left value
|
||||
* @param <R> the id of the right value
|
||||
* @return a new {@link Pair} with the specified values
|
||||
*/
|
||||
public static <L, R> Pair<L, R> of(final L left, final R right) {
|
||||
|
||||
@@ -439,7 +439,7 @@ public class ReflectionUtils {
|
||||
public static List<Method> getMethods(@NotNull Class<?> clazz, @NotNull Class<?> returnType, @NotNull Class<?>... parameterTypes) {
|
||||
List<Method> list = new ArrayList<>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (!returnType.isAssignableFrom(method.getReturnType()) // check type
|
||||
if (!returnType.isAssignableFrom(method.getReturnType()) // check id
|
||||
|| method.getParameterCount() != parameterTypes.length // check length
|
||||
) continue;
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
|
||||
@@ -137,13 +137,13 @@ public final class ResourceConfigUtils {
|
||||
try {
|
||||
return Integer.parseInt(s.replace("_", ""));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.int", e, s, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.int", e, s, option);
|
||||
}
|
||||
}
|
||||
case Boolean b -> {
|
||||
return b ? 1 : 0;
|
||||
}
|
||||
default -> throw new LocalizedResourceConfigException("warning.config.type.int", o.toString(), option);
|
||||
default -> throw new LocalizedResourceConfigException("warning.config.id.int", o.toString(), option);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,11 +162,11 @@ public final class ResourceConfigUtils {
|
||||
try {
|
||||
return Double.parseDouble(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.double", e, s, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.double", e, s, option);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.double", o.toString(), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.double", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,14 +183,14 @@ public final class ResourceConfigUtils {
|
||||
try {
|
||||
return Float.parseFloat(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.float", e, s, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.float", e, s, option);
|
||||
}
|
||||
}
|
||||
case Number number -> {
|
||||
return number.floatValue();
|
||||
}
|
||||
default -> {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.float", o.toString(), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.float", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,15 +206,15 @@ public final class ResourceConfigUtils {
|
||||
case Number n -> {
|
||||
if (n.byteValue() == 0) return false;
|
||||
if (n.byteValue() == 1) return true;
|
||||
throw new LocalizedResourceConfigException("warning.config.type.boolean", String.valueOf(n), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.boolean", String.valueOf(n), option);
|
||||
}
|
||||
case String s -> {
|
||||
if (s.equalsIgnoreCase("true")) return true;
|
||||
if (s.equalsIgnoreCase("false")) return false;
|
||||
throw new LocalizedResourceConfigException("warning.config.type.boolean", s, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.boolean", s, option);
|
||||
}
|
||||
default -> {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.boolean", o.toString(), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.boolean", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,11 +234,11 @@ public final class ResourceConfigUtils {
|
||||
try {
|
||||
return Long.parseLong(s.replace("_", ""));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.long", e, s, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.long", e, s, option);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.long", o.toString(), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.long", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@ public final class ResourceConfigUtils {
|
||||
if (obj instanceof Map<?, ?> map) {
|
||||
return (Map<String, Object>) map;
|
||||
}
|
||||
throw new LocalizedResourceConfigException("warning.config.type.map", String.valueOf(obj), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.map", String.valueOf(obj), option);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -259,7 +259,7 @@ public final class ResourceConfigUtils {
|
||||
if (obj instanceof Map<?, ?> map) {
|
||||
return (Map<String, Object>) map;
|
||||
}
|
||||
throw new LocalizedResourceConfigException("warning.config.type.map", String.valueOf(obj), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.map", String.valueOf(obj), option);
|
||||
}
|
||||
|
||||
public static Vector3f getAsVector3f(Object o, String option) {
|
||||
@@ -274,7 +274,7 @@ public final class ResourceConfigUtils {
|
||||
} else if (split.length == 1) {
|
||||
return new Vector3f(Float.parseFloat(split[0]));
|
||||
} else {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.vector3f", stringFormat, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.vector3f", stringFormat, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,7 +293,7 @@ public final class ResourceConfigUtils {
|
||||
} else if (split.length == 1) {
|
||||
return QuaternionUtils.toQuaternionf(0, (float) -Math.toRadians(Float.parseFloat(split[0])), 0);
|
||||
} else {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.quaternionf", stringFormat, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.quaternionf", stringFormat, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ public final class ResourceConfigUtils {
|
||||
double d = Double.parseDouble(split[0]);
|
||||
return new Vec3d(d, d, d);
|
||||
} else {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.vec3d", stringFormat, option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.vec3d", stringFormat, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,50 +344,54 @@ public final class ResourceConfigUtils {
|
||||
}
|
||||
|
||||
public static AABB getAsAABB(Object o, String option) {
|
||||
if (o == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.aabb", "null", option);
|
||||
}
|
||||
if (o instanceof Number number) {
|
||||
double min = -(number.doubleValue() / 2);
|
||||
double max = number.doubleValue() / 2;
|
||||
return new AABB(min, min, min, max, max, max);
|
||||
} else {
|
||||
double[] args;
|
||||
if (o instanceof List<?> list) {
|
||||
args = new double[list.size()];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (list.get(i) instanceof Number number) {
|
||||
args[i] = number.doubleValue();
|
||||
} else {
|
||||
switch (o) {
|
||||
case null -> throw new LocalizedResourceConfigException("warning.config.id.aabb", "null", option);
|
||||
case AABB aabb -> {
|
||||
return aabb;
|
||||
}
|
||||
case Number number -> {
|
||||
double min = -(number.doubleValue() / 2);
|
||||
double max = number.doubleValue() / 2;
|
||||
return new AABB(min, min, min, max, max, max);
|
||||
}
|
||||
default -> {
|
||||
double[] args;
|
||||
if (o instanceof List<?> list) {
|
||||
args = new double[list.size()];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (list.get(i) instanceof Number number) {
|
||||
args[i] = number.doubleValue();
|
||||
} else {
|
||||
try {
|
||||
args[i] = Double.parseDouble(list.get(i).toString());
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.id.aabb", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String[] split = o.toString().split(",");
|
||||
args = new double[split.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
try {
|
||||
args[i] = Double.parseDouble(list.get(i).toString());
|
||||
args[i] = Double.parseDouble(split[i]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.aabb", o.toString(), option);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.aabb", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String[] split = o.toString().split(",");
|
||||
args = new double[split.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
try {
|
||||
args[i] = Double.parseDouble(split[i]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.aabb", o.toString(), option);
|
||||
}
|
||||
if (args.length == 1) {
|
||||
return new AABB(-args[0] / 2, -args[0] / 2, -args[0] / 2, args[0] / 2, args[0] / 2, args[0] / 2);
|
||||
} else if (args.length == 2) {
|
||||
return new AABB(-args[0] / 2, -args[1] / 2, -args[0] / 2, args[0] / 2, args[1] / 2, args[0] / 2);
|
||||
} else if (args.length == 3) {
|
||||
return new AABB(-args[0] / 2, -args[1] / 2, -args[2] / 2, args[0] / 2, args[1] / 2, args[2] / 2);
|
||||
} else if (args.length == 6) {
|
||||
return new AABB(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
} else {
|
||||
throw new LocalizedResourceConfigException("warning.config.id.aabb", o.toString(), option);
|
||||
}
|
||||
}
|
||||
if (args.length == 1) {
|
||||
return new AABB(-args[0]/2, -args[0]/2, -args[0]/2, args[0]/2, args[0]/2, args[0]/2);
|
||||
} else if (args.length == 2) {
|
||||
return new AABB(-args[0]/2, -args[1]/2, -args[0]/2, args[0]/2, args[1]/2, args[0]/2);
|
||||
} else if (args.length == 3) {
|
||||
return new AABB(-args[0]/2, -args[1]/2, -args[2]/2, args[0]/2, args[1]/2, args[2]/2);
|
||||
} else if (args.length == 6) {
|
||||
return new AABB(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
} else {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.aabb", o.toString(), option);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public final class SNBTReader extends DefaultStringReader {
|
||||
// 1.21.6的SNBT原版是支持 {key:[B;1,2b,0xFF]} 这种奇葩写法的, 越界部分会被自动舍弃, 如0xff的byte值为-1.
|
||||
// 如果需要和原版对齐, 那么只需要判断是否是数字就行了.
|
||||
// if (!(element instanceof Number number))
|
||||
// throw new IllegalArgumentException("Error element type at pos " + getCursor());
|
||||
// throw new IllegalArgumentException("Error element id at pos " + getCursor());
|
||||
if (!(element instanceof Number number))
|
||||
throw new IllegalArgumentException("Error parsing number at pos " + getCursor());
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ import java.util.Objects;
|
||||
* A generic class representing a tuple with three values.
|
||||
* This class provides methods for creating and accessing tuples with three values.
|
||||
*
|
||||
* @param <L> the type of the left value
|
||||
* @param <M> the type of the middle value
|
||||
* @param <R> the type of the right value
|
||||
* @param <L> the id of the left value
|
||||
* @param <M> the id of the middle value
|
||||
* @param <R> the id of the right value
|
||||
*/
|
||||
public record Tuple<L, M, R>(L left, M mid, R right) {
|
||||
|
||||
@@ -18,9 +18,9 @@ public record Tuple<L, M, R>(L left, M mid, R right) {
|
||||
* @param left the left value
|
||||
* @param mid the middle value
|
||||
* @param right the right value
|
||||
* @param <L> the type of the left value
|
||||
* @param <M> the type of the middle value
|
||||
* @param <R> the type of the right value
|
||||
* @param <L> the id of the left value
|
||||
* @param <M> the id of the middle value
|
||||
* @param <R> the id of the right value
|
||||
* @return a new {@link Tuple} with the specified values
|
||||
*/
|
||||
public static <L, M, R> Tuple<L, M, R> of(final L left, final M mid, final R right) {
|
||||
|
||||
@@ -8,18 +8,18 @@ public class TypeUtils {
|
||||
private TypeUtils() {}
|
||||
|
||||
/**
|
||||
* Checks if the provided object is of the specified type.
|
||||
* Checks if the provided object is of the specified id.
|
||||
* If not, throws an IllegalArgumentException with a detailed message.
|
||||
*
|
||||
* @param object The object to check.
|
||||
* @param expectedType The expected class type.
|
||||
* @param <T> The type parameter for expectedType.
|
||||
* @return The object cast to the expected type if it matches.
|
||||
* @throws IllegalArgumentException if the object's type does not match the expected type.
|
||||
* @param expectedType The expected class id.
|
||||
* @param <T> The id parameter for expectedType.
|
||||
* @return The object cast to the expected id if it matches.
|
||||
* @throws IllegalArgumentException if the object's id does not match the expected id.
|
||||
*/
|
||||
public static <T> T checkType(Object object, Class<T> expectedType) {
|
||||
if (!expectedType.isInstance(object)) {
|
||||
throw new IllegalArgumentException("Expected type: " + expectedType.getName() +
|
||||
throw new IllegalArgumentException("Expected id: " + expectedType.getName() +
|
||||
", but got: " + (object == null ? "null" : object.getClass().getName()));
|
||||
}
|
||||
return expectedType.cast(object);
|
||||
@@ -48,7 +48,7 @@ public class TypeUtils {
|
||||
}
|
||||
yield bytes;
|
||||
}
|
||||
default -> throw new IllegalStateException("Unsupported type: " + type.toLowerCase(Locale.ENGLISH));
|
||||
default -> throw new IllegalStateException("Unsupported id: " + type.toLowerCase(Locale.ENGLISH));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.block.entity.render.DynamicBlockEntityRen
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement;
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.*;
|
||||
import net.momirealms.craftengine.core.entity.CustomEntity;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||
@@ -18,6 +19,7 @@ import net.momirealms.craftengine.core.world.*;
|
||||
import net.momirealms.craftengine.core.world.chunk.client.VirtualCullableObject;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultBlockEntityRendererSerializer;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultBlockEntitySerializer;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultEntitySerializer;
|
||||
import net.momirealms.sparrow.nbt.ListTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -30,11 +32,12 @@ public class CEChunk {
|
||||
public final ChunkPos chunkPos;
|
||||
public final CESection[] sections;
|
||||
public final WorldHeight worldHeightAccessor;
|
||||
public final Map<BlockPos, BlockEntity> blockEntities; // 从区域线程上访问,安全
|
||||
public final Map<BlockPos, ReplaceableTickingBlockEntity> tickingSyncBlockEntitiesByPos; // 从区域线程上访问,安全
|
||||
public final Map<BlockPos, ReplaceableTickingBlockEntity> tickingAsyncBlockEntitiesByPos; // 从区域线程上访问,安全
|
||||
public final Map<BlockPos, ConstantBlockEntityRenderer> constantBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取
|
||||
public final Map<BlockPos, DynamicBlockEntityRenderer> dynamicBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取
|
||||
private final Map<UUID, CustomEntity> entities; // 从区域线程上访问,安全
|
||||
private final Map<BlockPos, BlockEntity> blockEntities; // 从区域线程上访问,安全
|
||||
private final Map<BlockPos, ReplaceableTickingBlockEntity> tickingSyncBlockEntitiesByPos; // 从区域线程上访问,安全
|
||||
private final Map<BlockPos, ReplaceableTickingBlockEntity> tickingAsyncBlockEntitiesByPos; // 从区域线程上访问,安全
|
||||
private final Map<BlockPos, ConstantBlockEntityRenderer> constantBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取
|
||||
private final Map<BlockPos, DynamicBlockEntityRenderer> dynamicBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取
|
||||
private final ReentrantReadWriteLock renderLock = new ReentrantReadWriteLock();
|
||||
private volatile boolean dirty;
|
||||
private volatile boolean loaded;
|
||||
@@ -50,10 +53,11 @@ public class CEChunk {
|
||||
this.dynamicBlockEntityRenderers = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
this.tickingSyncBlockEntitiesByPos = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
this.tickingAsyncBlockEntitiesByPos = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
this.entities = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
this.fillEmptySection();
|
||||
}
|
||||
|
||||
public CEChunk(CEWorld world, ChunkPos chunkPos, CESection[] sections, @Nullable ListTag blockEntitiesTag, @Nullable ListTag itemDisplayBlockRenders) {
|
||||
public CEChunk(CEWorld world, ChunkPos chunkPos, CESection[] sections, @Nullable ListTag blockEntitiesTag, @Nullable ListTag blockEntityRenders, @Nullable ListTag entities) {
|
||||
this.world = world;
|
||||
this.chunkPos = chunkPos;
|
||||
this.worldHeightAccessor = world.worldHeight();
|
||||
@@ -80,15 +84,27 @@ public class CEChunk {
|
||||
} else {
|
||||
this.blockEntities = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
}
|
||||
if (itemDisplayBlockRenders != null) {
|
||||
this.constantBlockEntityRenderers = new Object2ObjectOpenHashMap<>(Math.max(itemDisplayBlockRenders.size(), 10), 0.5f);
|
||||
List<BlockPos> blockEntityRendererPoses = DefaultBlockEntityRendererSerializer.deserialize(this.chunkPos, itemDisplayBlockRenders);
|
||||
if (blockEntityRenders != null) {
|
||||
this.constantBlockEntityRenderers = new Object2ObjectOpenHashMap<>(Math.max(blockEntityRenders.size(), 10), 0.5f);
|
||||
List<BlockPos> blockEntityRendererPoses = DefaultBlockEntityRendererSerializer.deserialize(this.chunkPos, blockEntityRenders);
|
||||
for (BlockPos pos : blockEntityRendererPoses) {
|
||||
this.addConstantBlockEntityRenderer(pos);
|
||||
}
|
||||
} else {
|
||||
this.constantBlockEntityRenderers = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
}
|
||||
if (entities != null) {
|
||||
this.entities = new Object2ObjectOpenHashMap<>(Math.max(entities.size(), 10), 0.5f);
|
||||
for (CustomEntity entity : DefaultEntitySerializer.deserialize(world, entities)) {
|
||||
this.entities.put(entity.uuid(), entity);
|
||||
}
|
||||
} else {
|
||||
this.entities = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<UUID, CustomEntity> entities() {
|
||||
return Collections.unmodifiableMap(this.entities);
|
||||
}
|
||||
|
||||
public void spawnBlockEntities(Player player) {
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.InactiveBlockEntity;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
@@ -37,11 +38,13 @@ public final class DefaultBlockEntitySerializer {
|
||||
CompoundTag data = tag.getCompound(i);
|
||||
Key id = Key.of(data.getString("id"));
|
||||
BlockEntityType<?> type = BuiltInRegistries.BLOCK_ENTITY_TYPE.getValue(id);
|
||||
BlockPos pos = BlockEntity.readPosAndVerify(data, chunk.chunkPos());
|
||||
ImmutableBlockState blockState = chunk.getBlockState(pos);
|
||||
if (type == null) {
|
||||
Debugger.BLOCK.debug(() -> "Unknown block entity type: " + id);
|
||||
BlockEntity blockEntity = new InactiveBlockEntity(pos, blockState, data);
|
||||
blockEntities.add(blockEntity);
|
||||
} else {
|
||||
BlockPos pos = BlockEntity.readPosAndVerify(data, chunk.chunkPos());
|
||||
ImmutableBlockState blockState = chunk.getBlockState(pos);
|
||||
if (blockState.blockEntityType() == type) {
|
||||
Optional<EntityBlockBehavior> entityBlockBehavior = blockState.behavior().getAs(EntityBlockBehavior.class);
|
||||
if (entityBlockBehavior.isPresent()) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.world.chunk.serialization;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.CustomEntity;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
@@ -9,6 +10,9 @@ import net.momirealms.sparrow.nbt.ListTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class DefaultChunkSerializer {
|
||||
|
||||
private DefaultChunkSerializer() {}
|
||||
@@ -36,6 +40,10 @@ public final class DefaultChunkSerializer {
|
||||
if (!blockEntityRenders.isEmpty()) {
|
||||
chunkNbt.put("block_entity_renderers", blockEntityRenders);
|
||||
}
|
||||
ListTag listTag = new ListTag();
|
||||
Map<UUID, CustomEntity> entities = chunk.entities();
|
||||
|
||||
|
||||
return chunkNbt;
|
||||
}
|
||||
|
||||
@@ -54,7 +62,8 @@ public final class DefaultChunkSerializer {
|
||||
}
|
||||
}
|
||||
ListTag blockEntities = chunkNbt.getList("block_entities");
|
||||
ListTag itemDisplayBlockRenders = chunkNbt.getList("block_entity_renderers");
|
||||
return new CEChunk(world, pos, sectionArray, blockEntities, itemDisplayBlockRenders);
|
||||
ListTag blockEntityRenders = chunkNbt.getList("block_entity_renderers");
|
||||
ListTag entities = chunkNbt.getList("entities");
|
||||
return new CEChunk(world, pos, sectionArray, blockEntities, blockEntityRenders, entities);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.momirealms.craftengine.core.world.chunk.serialization;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.CustomEntity;
|
||||
import net.momirealms.craftengine.core.entity.CustomEntityType;
|
||||
import net.momirealms.craftengine.core.entity.InactiveCustomEntity;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.ListTag;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DefaultEntitySerializer {
|
||||
|
||||
public static ListTag serialize(@NotNull Collection<CustomEntity> entity) {
|
||||
ListTag entities = new ListTag();
|
||||
for (CustomEntity customEntity : entity) {
|
||||
if (customEntity.isValid()) {
|
||||
entities.add(customEntity.saveAsTag());
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public static List<CustomEntity> deserialize(CEWorld world, ListTag entitiesTag) {
|
||||
List<CustomEntity> entities = new ArrayList<>(entitiesTag.size());
|
||||
for (Tag tag : entitiesTag) {
|
||||
if (tag instanceof CompoundTag entityTag) {
|
||||
WorldPosition worldPosition = CustomEntity.readPos(world, entityTag);
|
||||
UUID uuid = CustomEntity.readUUID(entityTag);
|
||||
Key type = Key.of(entityTag.getString("type"));
|
||||
CustomEntityType<?> entityType = BuiltInRegistries.ENTITY_TYPE.getValue(type);
|
||||
if (entityType == null) {
|
||||
InactiveCustomEntity entity = new InactiveCustomEntity(uuid, worldPosition, entityTag);
|
||||
entities.add(entity);
|
||||
} else {
|
||||
CustomEntity entity = entityType.factory().create(uuid, worldPosition);
|
||||
entity.loadCustomData(entityTag);
|
||||
// 加载时无效则直接放弃
|
||||
if (entity.isValid()) {
|
||||
entities.add(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user