mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
家具重构part1
This commit is contained in:
@@ -8,9 +8,8 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
@@ -46,7 +45,7 @@ public final class CraftEngineFurniture {
|
||||
* @return a non-null map containing all loaded custom furniture
|
||||
*/
|
||||
@NotNull
|
||||
public static Map<Key, CustomFurniture> loadedFurniture() {
|
||||
public static Map<Key, FurnitureConfig> loadedFurniture() {
|
||||
return BukkitFurnitureManager.instance().loadedFurniture();
|
||||
}
|
||||
|
||||
@@ -56,7 +55,7 @@ public final class CraftEngineFurniture {
|
||||
* @param id id
|
||||
* @return the custom furniture
|
||||
*/
|
||||
public static CustomFurniture byId(@NotNull Key id) {
|
||||
public static FurnitureConfig byId(@NotNull Key id) {
|
||||
return BukkitFurnitureManager.instance().furnitureById(id).orElse(null);
|
||||
}
|
||||
|
||||
@@ -69,9 +68,11 @@ public final class CraftEngineFurniture {
|
||||
*/
|
||||
@Nullable
|
||||
public static BukkitFurniture place(Location location, Key furnitureId) {
|
||||
CustomFurniture furniture = byId(furnitureId);
|
||||
FurnitureConfig furniture = byId(furnitureId);
|
||||
if (furniture == null) return null;
|
||||
return place(location, furnitureId, furniture.getAnyAnchorType());
|
||||
// fixme API
|
||||
// return place(location, furnitureId, furniture.getAnyAnchorType());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,14 +80,17 @@ public final class CraftEngineFurniture {
|
||||
*
|
||||
* @param location location
|
||||
* @param furnitureId furniture to place
|
||||
* @param anchorType anchor type
|
||||
* @param anchorType anchor id
|
||||
* @return the loaded furniture
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "0.0.66", forRemoval = true)
|
||||
public static BukkitFurniture place(Location location, Key furnitureId, AnchorType anchorType) {
|
||||
CustomFurniture furniture = byId(furnitureId);
|
||||
FurnitureConfig furniture = byId(furnitureId);
|
||||
if (furniture == null) return null;
|
||||
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true);
|
||||
// fixme API
|
||||
// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), true);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,12 +98,15 @@ public final class CraftEngineFurniture {
|
||||
*
|
||||
* @param location location
|
||||
* @param furniture furniture to place
|
||||
* @param anchorType anchor type
|
||||
* @param anchorType anchor id
|
||||
* @return the loaded furniture
|
||||
*/
|
||||
@NotNull
|
||||
public static BukkitFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType) {
|
||||
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true);
|
||||
@Deprecated(since = "0.0.66", forRemoval = true)
|
||||
public static BukkitFurniture place(Location location, FurnitureConfig furniture, AnchorType anchorType) {
|
||||
// fixme API
|
||||
// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), true);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,15 +114,18 @@ public final class CraftEngineFurniture {
|
||||
*
|
||||
* @param location location
|
||||
* @param furnitureId furniture to place
|
||||
* @param anchorType anchor type
|
||||
* @param anchorType anchor id
|
||||
* @param playSound whether to play place sounds
|
||||
* @return the loaded furniture
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "0.0.66", forRemoval = true)
|
||||
public static BukkitFurniture place(Location location, Key furnitureId, AnchorType anchorType, boolean playSound) {
|
||||
CustomFurniture furniture = byId(furnitureId);
|
||||
FurnitureConfig furniture = byId(furnitureId);
|
||||
if (furniture == null) return null;
|
||||
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound);
|
||||
// fixme API
|
||||
// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), playSound);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,13 +133,16 @@ public final class CraftEngineFurniture {
|
||||
*
|
||||
* @param location location
|
||||
* @param furniture furniture to place
|
||||
* @param anchorType anchor type
|
||||
* @param anchorType anchor id
|
||||
* @param playSound whether to play place sounds
|
||||
* @return the loaded furniture
|
||||
*/
|
||||
@NotNull
|
||||
public static BukkitFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType, boolean playSound) {
|
||||
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound);
|
||||
@Deprecated(since = "0.0.66", forRemoval = true)
|
||||
public static BukkitFurniture place(Location location, FurnitureConfig furniture, AnchorType anchorType, boolean playSound) {
|
||||
// fixme API
|
||||
// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), playSound);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +299,7 @@ public final class CraftEngineFurniture {
|
||||
boolean dropLoot,
|
||||
boolean playSound) {
|
||||
if (!furniture.isValid()) return;
|
||||
Location location = ((BukkitFurniture) furniture).dropLocation();
|
||||
Location location = ((BukkitFurniture) furniture).getDropLocation();
|
||||
furniture.destroy();
|
||||
LootTable<ItemStack> lootTable = (LootTable<ItemStack>) furniture.config().lootTable();
|
||||
World world = new BukkitWorld(location.getWorld());
|
||||
@@ -295,7 +308,7 @@ public final class CraftEngineFurniture {
|
||||
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));
|
||||
if (player != null) {
|
||||
Item<?> itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
builder.withParameter(DirectContextParameters.PLAYER, player)
|
||||
|
||||
@@ -49,7 +49,7 @@ public final class AsyncResourcePackCacheEvent extends Event {
|
||||
* Adds an external resource pack to the cache.
|
||||
* <p>
|
||||
* This method accepts either a .zip file or a directory path representing a resource pack.
|
||||
* The resource pack will be added to the appropriate cache collection based on its type.
|
||||
* The resource pack will be added to the appropriate cache collection based on its id.
|
||||
* </p>
|
||||
*
|
||||
* @param path the file system path to the resource pack. Must be either a .zip file or a directory.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.api.event;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public final class FurnitureAttemptPlaceEvent extends PlayerEvent implements Cancellable {
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
private boolean cancelled;
|
||||
private final CustomFurniture furniture;
|
||||
private final FurnitureConfig furniture;
|
||||
private final Location location;
|
||||
private final AnchorType anchorType;
|
||||
private final BlockFace clickedFace;
|
||||
@@ -23,7 +23,7 @@ public final class FurnitureAttemptPlaceEvent extends PlayerEvent implements Can
|
||||
private final InteractionHand hand;
|
||||
|
||||
public FurnitureAttemptPlaceEvent(@NotNull Player player,
|
||||
@NotNull CustomFurniture furniture,
|
||||
@NotNull FurnitureConfig furniture,
|
||||
@NotNull AnchorType anchorType,
|
||||
@NotNull Location location,
|
||||
@NotNull BlockFace clickedFace,
|
||||
@@ -69,7 +69,7 @@ public final class FurnitureAttemptPlaceEvent extends PlayerEvent implements Can
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CustomFurniture furniture() {
|
||||
public FurnitureConfig furniture() {
|
||||
return furniture;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.api.event;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBox;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -45,7 +45,7 @@ public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water")));
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-id", List.of("water")));
|
||||
boolean stackable = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("stackable", false), "stackable");
|
||||
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
|
||||
List<String> positionsToCheck = MiscUtils.getAsStringList(arguments.getOrDefault("positions", List.of()));
|
||||
|
||||
@@ -40,7 +40,7 @@ public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water")));
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-id", List.of("water")));
|
||||
boolean stackable = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("stackable", false), "stackable");
|
||||
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
|
||||
return new OnLiquidBlockBehavior(block, delay, stackable, liquidTypes.contains("water"), liquidTypes.contains("lava"));
|
||||
|
||||
@@ -6,8 +6,8 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
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.render.element.BlockEntityElementConfigFactory;
|
||||
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.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
@@ -19,7 +19,6 @@ import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -173,8 +172,8 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch"),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"),
|
||||
ResourceConfigUtils.getAsQuaternionf(arguments.getOrDefault("rotation", 0f), "rotation"),
|
||||
ItemDisplayContext.valueOf(arguments.getOrDefault("display-context", "none").toString().toUpperCase(Locale.ROOT)),
|
||||
Billboard.valueOf(arguments.getOrDefault("billboard", "fixed").toString().toUpperCase(Locale.ROOT)),
|
||||
ResourceConfigUtils.getAsEnum(ResourceConfigUtils.get(arguments, "display-context", "display-transform"), ItemDisplayContext.class, ItemDisplayContext.NONE),
|
||||
ResourceConfigUtils.getAsEnum(arguments.get("billboard"), Billboard.class, Billboard.FIXED),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-radius", 0f), "shadow-radius"),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-strength", 1f), "shadow-strength")
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
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.render.element.BlockEntityElementConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.display.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.core.entity.ItemEntity;
|
||||
import net.momirealms.craftengine.core.entity.item.ItemEntity;
|
||||
import org.bukkit.entity.Item;
|
||||
|
||||
public class BukkitItemEntity extends BukkitEntity implements ItemEntity {
|
||||
|
||||
@@ -6,7 +6,7 @@ public class ItemDisplayEntityData<T> extends DisplayEntityData<T> {
|
||||
// Item display only
|
||||
public static final ItemDisplayEntityData<Object> DisplayedItem = new ItemDisplayEntityData<>(ItemDisplayEntityData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY);
|
||||
/**
|
||||
* Display type:
|
||||
* Display id:
|
||||
* 0 = NONE
|
||||
* 1 = THIRD_PERSON_LEFT_HAND
|
||||
* 2 = THIRD_PERSON_RIGHT_HAND
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.AbstractCustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureSettings;
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BukkitCustomFurniture extends AbstractCustomFurniture {
|
||||
|
||||
protected BukkitCustomFurniture(@NotNull Key id,
|
||||
@NotNull FurnitureSettings settings,
|
||||
@NotNull Map<AnchorType, Placement> placements,
|
||||
@NotNull Map<EventTrigger, List<Function<Context>>> events,
|
||||
@Nullable LootTable<?> lootTable) {
|
||||
super(id, settings, placements, events, lootTable);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new BuilderImpl();
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder {
|
||||
private Key id;
|
||||
private Map<AnchorType, Placement> placements;
|
||||
private FurnitureSettings settings;
|
||||
private Map<EventTrigger, List<Function<Context>>> events;
|
||||
private LootTable<?> lootTable;
|
||||
|
||||
@Override
|
||||
public CustomFurniture build() {
|
||||
return new BukkitCustomFurniture(id, settings, placements, events, lootTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder id(Key id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder placement(Map<AnchorType, Placement> placements) {
|
||||
this.placements = placements;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,184 +1,166 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitFurniture implements Furniture {
|
||||
private final CustomFurniture furniture;
|
||||
private final CustomFurniture.Placement placement;
|
||||
private FurnitureExtraData extraData;
|
||||
// location
|
||||
private final Location location;
|
||||
// base entity
|
||||
private final WeakReference<Entity> baseEntity;
|
||||
private final int baseEntityId;
|
||||
// colliders
|
||||
private final Collider[] colliderEntities;
|
||||
// cache
|
||||
private final List<Integer> fakeEntityIds;
|
||||
private final List<Integer> entityIds;
|
||||
private final Map<Integer, BukkitHitBox> hitBoxes = new Int2ObjectArrayMap<>();
|
||||
private final Map<Integer, HitBoxPart> hitBoxParts = new Int2ObjectArrayMap<>();
|
||||
private final boolean minimized;
|
||||
private final boolean hasExternalModel;
|
||||
// cached spawn packet
|
||||
private Object cachedSpawnPacket;
|
||||
private Object cachedMinimizedSpawnPacket;
|
||||
private static final UUID INVALID_UUID = new UUID(0, 0);
|
||||
@NotNull
|
||||
private final FurnitureConfig config;
|
||||
@NotNull
|
||||
private final FurnitureDataAccessor dataAccessor;
|
||||
|
||||
public BukkitFurniture(Entity baseEntity,
|
||||
CustomFurniture furniture,
|
||||
FurnitureExtraData extraData) {
|
||||
this.extraData = extraData;
|
||||
this.baseEntityId = baseEntity.getEntityId();
|
||||
this.location = baseEntity.getLocation();
|
||||
this.baseEntity = new WeakReference<>(baseEntity);
|
||||
this.furniture = furniture;
|
||||
this.minimized = furniture.settings().minimized();
|
||||
this.placement = furniture.getValidPlacement(extraData.anchorType().orElseGet(furniture::getAnyAnchorType));
|
||||
private WeakReference<Entity> baseEntity;
|
||||
private FurnitureVariant currentVariant;
|
||||
private Location location;
|
||||
private boolean valid;
|
||||
private UUID uuid;
|
||||
private int entityId;
|
||||
|
||||
List<Integer> fakeEntityIds = new IntArrayList();
|
||||
List<Integer> mainEntityIds = new IntArrayList();
|
||||
mainEntityIds.add(this.baseEntityId);
|
||||
private FurnitureElement[] elements;
|
||||
|
||||
// 绑定外部模型
|
||||
Optional<ExternalModel> optionalExternal = placement.externalModel();
|
||||
if (optionalExternal.isPresent()) {
|
||||
try {
|
||||
optionalExternal.get().bindModel(new BukkitEntity(baseEntity));
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id(), e);
|
||||
}
|
||||
this.hasExternalModel = true;
|
||||
} else {
|
||||
this.hasExternalModel = false;
|
||||
public BukkitFurniture(@NotNull FurnitureConfig config,
|
||||
@NotNull CompoundTag data) {
|
||||
this.dataAccessor = FurnitureDataAccessor.of(data);
|
||||
this.currentVariant = Optional.ofNullable(getVariant()).orElseGet(config::anyVariant);
|
||||
this.config = config;
|
||||
this.baseEntity = new WeakReference<>(null);
|
||||
this.valid = false;
|
||||
this.entityId = -1;
|
||||
this.uuid = INVALID_UUID;
|
||||
}
|
||||
|
||||
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate();
|
||||
List<Object> packets = new ArrayList<>();
|
||||
List<Object> minimizedPackets = new ArrayList<>();
|
||||
List<Collider> colliders = new ArrayList<>(4);
|
||||
private void sync() {
|
||||
WorldPosition position = position();
|
||||
|
||||
|
||||
// 初始化家具的元素
|
||||
for (FurnitureElement element : placement.elements()) {
|
||||
int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
fakeEntityIds.add(entityId);
|
||||
element.initPackets(this, entityId, conjugated, packet -> {
|
||||
packets.add(packet);
|
||||
if (this.minimized) minimizedPackets.add(packet);
|
||||
});
|
||||
FurnitureElementConfig<?>[] elementConfigs = this.currentVariant.elements();
|
||||
FurnitureElement[] elements = new FurnitureElement[elementConfigs.length];
|
||||
for (int i = 0; i < elementConfigs.length; i++) {
|
||||
FurnitureElement o = elementConfigs[i].create(position);
|
||||
elements[i] = o;
|
||||
}
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
// 初始化碰撞箱
|
||||
for (HitBoxConfig hitBoxConfig : this.placement.hitBoxConfigs()) {
|
||||
int[] ids = hitBoxConfig.acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet);
|
||||
List<HitBoxPart> aabbs = new ArrayList<>();
|
||||
|
||||
hitBoxConfig.initPacketsAndColliders(ids, position, conjugated, (packet, canBeMinimized) -> {
|
||||
packets.add(packet);
|
||||
if (this.minimized && !canBeMinimized) {
|
||||
minimizedPackets.add(packet);
|
||||
}
|
||||
}, colliders::add, part -> {
|
||||
this.hitBoxParts.put(part.entityId(), part);
|
||||
aabbs.add(part);
|
||||
});
|
||||
|
||||
BukkitHitBox hitBox = new BukkitHitBox(this, hitBoxConfig, aabbs.toArray(new HitBoxPart[0]));
|
||||
for (int entityId : ids) {
|
||||
fakeEntityIds.add(entityId);
|
||||
mainEntityIds.add(entityId);
|
||||
this.hitBoxes.put(entityId, hitBox);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化缓存的家具包
|
||||
try {
|
||||
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||
if (this.minimized) {
|
||||
this.cachedMinimizedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(minimizedPackets);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id(), e);
|
||||
}
|
||||
|
||||
|
||||
this.fakeEntityIds = fakeEntityIds;
|
||||
this.entityIds = mainEntityIds;
|
||||
this.colliderEntities = colliders.toArray(new Collider[0]);
|
||||
public void addToWorld(Location location) {
|
||||
this.setLocation(location);
|
||||
this.valid = true;
|
||||
Entity baseEntity = null; // fixme 处理生成
|
||||
this.baseEntity = new WeakReference<>(baseEntity);
|
||||
this.uuid = baseEntity.getUniqueId();
|
||||
this.entityId = baseEntity.getEntityId();
|
||||
this.sync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeColliders() {
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld());
|
||||
for (Collider entity : this.colliderEntities) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle());
|
||||
Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity.handle());
|
||||
bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1);
|
||||
public void show(Player player) {
|
||||
for (FurnitureElement element : this.elements) {
|
||||
element.show(player);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object spawnPacket(Player player) {
|
||||
// TODO hasPermission might be slow, can we use a faster way in the future?
|
||||
// TODO Make it based on conditions. So we can dynamically control which furniture should be sent to the player
|
||||
if (!this.minimized || player.hasPermission(FurnitureManager.FURNITURE_ADMIN_NODE)) {
|
||||
return this.cachedSpawnPacket;
|
||||
} else {
|
||||
return this.cachedMinimizedSpawnPacket;
|
||||
@Override
|
||||
public void hide(Player player) {
|
||||
for (FurnitureElement element : this.elements) {
|
||||
element.hide(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CullingData cullingData() {
|
||||
return this.config.cullingData();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FurnitureConfig config() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FurnitureDataAccessor dataAccessor() {
|
||||
return this.dataAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldPosition position() {
|
||||
return LocationUtils.toWorldPosition(this.location);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Location location() {
|
||||
return this.location.clone();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Entity baseEntity() {
|
||||
Entity entity = this.baseEntity.get();
|
||||
if (entity == null) {
|
||||
throw new RuntimeException("Base entity not found. It might be unloaded.");
|
||||
}
|
||||
return entity;
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return baseEntity().isValid();
|
||||
public void destroy() {
|
||||
this.valid = false;
|
||||
Optional.ofNullable(this.baseEntity.get()).ifPresent(Entity::remove);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Location dropLocation() {
|
||||
Optional<Vector3f> dropOffset = this.placement.dropOffset();
|
||||
@Override
|
||||
public UUID uuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int entityId() {
|
||||
return this.entityId;
|
||||
}
|
||||
|
||||
public void teleport(WorldPosition position) {
|
||||
Location newLocation = LocationUtils.toLocation(position);
|
||||
if (newLocation.equals(this.location)) {
|
||||
return;
|
||||
}
|
||||
this.setLocation(newLocation);
|
||||
this.sync();
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
private void setLocation(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public FurnitureVariant getVariant() {
|
||||
return this.config.getVariant(this.dataAccessor.variant().orElseGet(this.config::anyVariantName));
|
||||
}
|
||||
|
||||
public void setVariant(String variant) {
|
||||
FurnitureVariant newVariant = this.config.getVariant(variant);
|
||||
if (newVariant != this.currentVariant) {
|
||||
this.currentVariant = newVariant;
|
||||
this.sync();
|
||||
}
|
||||
}
|
||||
|
||||
// 获取掉落物的位置,受到家具变种的影响
|
||||
public Location getDropLocation() {
|
||||
Optional<Vector3f> dropOffset = this.getVariant().dropOffset();
|
||||
if (dropOffset.isEmpty()) {
|
||||
return location();
|
||||
}
|
||||
@@ -186,105 +168,4 @@ public class BukkitFurniture implements Furniture {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(dropOffset.get()));
|
||||
return new Location(this.location.getWorld(), this.location.getX() + offset.x, this.location.getY() + offset.y, this.location.getZ() - offset.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
this.baseEntity().remove();
|
||||
this.destroyColliders();
|
||||
this.destroySeats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyColliders() {
|
||||
for (Collider entity : this.colliderEntities) {
|
||||
if (entity != null)
|
||||
entity.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroySeats() {
|
||||
for (HitBox hitBox : this.hitBoxes.values()) {
|
||||
for (Seat<HitBox> seat : hitBox.seats()) {
|
||||
seat.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID uuid() {
|
||||
return this.baseEntity().getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int baseEntityId() {
|
||||
return this.baseEntityId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Integer> entityIds() {
|
||||
return Collections.unmodifiableList(this.entityIds);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Integer> fakeEntityIds() {
|
||||
return Collections.unmodifiableList(this.fakeEntityIds);
|
||||
}
|
||||
|
||||
public Collider[] collisionEntities() {
|
||||
return this.colliderEntities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable HitBox hitBoxByEntityId(int id) {
|
||||
return this.hitBoxes.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable HitBoxPart hitBoxPartByEntityId(int id) {
|
||||
return this.hitBoxParts.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AnchorType anchorType() {
|
||||
return this.placement.anchorType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Key id() {
|
||||
return this.furniture.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CustomFurniture config() {
|
||||
return this.furniture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExternalModel() {
|
||||
return hasExternalModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FurnitureExtraData extraData() {
|
||||
return this.extraData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtraData(FurnitureExtraData extraData) {
|
||||
this.extraData = extraData;
|
||||
this.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
try {
|
||||
this.baseEntity().getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, this.extraData.toBytes());
|
||||
} catch (IOException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to save furniture data.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.core.entity.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureElement;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.data.FireworkExplosion;
|
||||
import net.momirealms.craftengine.core.util.Color;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitFurnitureElement extends AbstractFurnitureElement {
|
||||
private final List<Object> commonValues;
|
||||
|
||||
public BukkitFurnitureElement(Key item,
|
||||
Billboard billboard,
|
||||
ItemDisplayContext transform,
|
||||
Vector3f scale,
|
||||
Vector3f translation,
|
||||
Vector3f position,
|
||||
Quaternionf rotation,
|
||||
float shadowRadius,
|
||||
float shadowStrength,
|
||||
boolean applyDyedColor) {
|
||||
super(item, billboard, transform, scale, translation, position, rotation, shadowRadius, shadowStrength, applyDyedColor);
|
||||
this.commonValues = new ArrayList<>();
|
||||
ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.commonValues);
|
||||
ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.commonValues);
|
||||
ItemDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(billboard().id(), this.commonValues);
|
||||
ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(translation(), this.commonValues);
|
||||
ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(transform().id(), this.commonValues);
|
||||
ItemDisplayEntityData.ShadowRadius.addEntityDataIfNotDefaultValue(shadowRadius, this.commonValues);
|
||||
ItemDisplayEntityData.ShadowStrength.addEntityDataIfNotDefaultValue(shadowStrength, this.commonValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPackets(Furniture furniture, int entityId, @NotNull Quaternionf conjugated, Consumer<Object> packets) {
|
||||
WorldPosition position = furniture.position();
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
entityId, UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.yRot(),
|
||||
MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||
));
|
||||
if (applyDyedColor()) {
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues(
|
||||
furniture.extraData().dyedColor().orElse(null),
|
||||
furniture.extraData().fireworkExplosionColors().orElse(null)
|
||||
)));
|
||||
} else {
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues(null, null)));
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized List<Object> getCachedValues(@Nullable Color color, int @Nullable [] colors) {
|
||||
List<Object> cachedValues = new ArrayList<>(this.commonValues);
|
||||
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(item(), null);
|
||||
if (item == null) {
|
||||
item = BukkitItemManager.instance().wrap(new ItemStack(Material.BARRIER));
|
||||
} else {
|
||||
if (color != null) {
|
||||
item.dyedColor(color);
|
||||
}
|
||||
if (colors != null) {
|
||||
item.fireworkExplosion(new FireworkExplosion(
|
||||
FireworkExplosion.Shape.SMALL_BALL,
|
||||
new IntArrayList(colors),
|
||||
new IntArrayList(),
|
||||
false,
|
||||
false
|
||||
));
|
||||
}
|
||||
}
|
||||
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), cachedValues);
|
||||
return cachedValues;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new BuilderImpl();
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder {
|
||||
private boolean applyDyedColor;
|
||||
private Key item;
|
||||
private Billboard billboard;
|
||||
private ItemDisplayContext transform;
|
||||
private Vector3f scale;
|
||||
private Vector3f translation;
|
||||
private Vector3f position;
|
||||
private Quaternionf rotation;
|
||||
private float shadowRadius;
|
||||
private float shadowStrength;
|
||||
|
||||
@Override
|
||||
public Builder applyDyedColor(boolean applyDyedColor) {
|
||||
this.applyDyedColor = applyDyedColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder item(Key item) {
|
||||
this.item = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder billboard(Billboard billboard) {
|
||||
this.billboard = billboard;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder transform(ItemDisplayContext transform) {
|
||||
this.transform = transform;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder scale(Vector3f scale) {
|
||||
this.scale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder translation(Vector3f translation) {
|
||||
this.translation = translation;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder position(Vector3f position) {
|
||||
this.position = position;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder rotation(Quaternionf rotation) {
|
||||
this.rotation = rotation;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder shadowStrength(float shadowStrength) {
|
||||
this.shadowStrength = shadowStrength;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder shadowRadius(float shadowRadius) {
|
||||
this.shadowRadius = shadowRadius;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FurnitureElement build() {
|
||||
return new BukkitFurnitureElement(item, billboard, transform, scale, translation, position, rotation, shadowRadius, shadowStrength, applyDyedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,23 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBoxConfig;
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Boat;
|
||||
import org.bukkit.entity.Interaction;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY);
|
||||
@@ -56,30 +45,32 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
|
||||
return this.place(LocationUtils.toLocation(position), furniture, extraData, playSound);
|
||||
public Furniture place(WorldPosition position, FurnitureConfig furniture, FurnitureDataAccessor dataAccessor, boolean playSound) {
|
||||
// return this.place(LocationUtils.toLocation(position), furniture, dataAccessor, playSound);
|
||||
return null;
|
||||
}
|
||||
|
||||
public BukkitFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
|
||||
Optional<AnchorType> optionalAnchorType = extraData.anchorType();
|
||||
if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) {
|
||||
extraData.anchorType(furniture.getAnyAnchorType());
|
||||
}
|
||||
Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> {
|
||||
ItemDisplay display = (ItemDisplay) entity;
|
||||
display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_KEY, PersistentDataType.STRING, furniture.id().toString());
|
||||
try {
|
||||
display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, extraData.toBytes());
|
||||
} catch (IOException e) {
|
||||
this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e);
|
||||
}
|
||||
handleBaseEntityLoadEarly(display);
|
||||
});
|
||||
if (playSound) {
|
||||
SoundData data = furniture.settings().sounds().placeSound();
|
||||
location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume().get(), data.pitch().get());
|
||||
}
|
||||
return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId());
|
||||
public BukkitFurniture place(Location location, FurnitureConfig furniture, FurnitureDataAccessor extraData, boolean playSound) {
|
||||
// Optional<AnchorType> optionalAnchorType = extraData.anchorType();
|
||||
// if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) {
|
||||
// extraData.anchorType(furniture.getAnyAnchorType());
|
||||
// }
|
||||
// Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> {
|
||||
// ItemDisplay display = (ItemDisplay) entity;
|
||||
// display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_KEY, PersistentDataType.STRING, furniture.id().toString());
|
||||
// try {
|
||||
// display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, extraData.toBytes());
|
||||
// } catch (IOException e) {
|
||||
// this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e);
|
||||
// }
|
||||
// handleBaseEntityLoadEarly(display);
|
||||
// });
|
||||
// if (playSound) {
|
||||
// SoundData data = furniture.settings().sounds().placeSound();
|
||||
// location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume().get(), data.pitch().get());
|
||||
// }
|
||||
// return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,34 +79,34 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? MEntityTypes.INTERACTION : MEntityTypes.OAK_BOAT;
|
||||
COLLISION_ENTITY_TYPE = Config.colliderType();
|
||||
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin());
|
||||
if (VersionHelper.isFolia()) {
|
||||
BiConsumer<Entity, Runnable> taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {});
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay display) {
|
||||
taskExecutor.accept(entity, () -> handleBaseEntityLoadEarly(display));
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(interaction));
|
||||
} else if (entity instanceof Boat boat) {
|
||||
taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(boat));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay display) {
|
||||
handleBaseEntityLoadEarly(display);
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
handleCollisionEntityLoadOnEntitiesLoad(interaction);
|
||||
} else if (entity instanceof Boat boat) {
|
||||
handleCollisionEntityLoadOnEntitiesLoad(boat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (VersionHelper.isFolia()) {
|
||||
// BiConsumer<Entity, Runnable> taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {});
|
||||
// for (World world : Bukkit.getWorlds()) {
|
||||
// List<Entity> entities = world.getEntities();
|
||||
// for (Entity entity : entities) {
|
||||
// if (entity instanceof ItemDisplay display) {
|
||||
// taskExecutor.accept(entity, () -> handleBaseEntityLoadEarly(display));
|
||||
// } else if (entity instanceof Interaction interaction) {
|
||||
// taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(interaction));
|
||||
// } else if (entity instanceof Boat boat) {
|
||||
// taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(boat));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// for (World world : Bukkit.getWorlds()) {
|
||||
// List<Entity> entities = world.getEntities();
|
||||
// for (Entity entity : entities) {
|
||||
// if (entity instanceof ItemDisplay display) {
|
||||
// handleBaseEntityLoadEarly(display);
|
||||
// } else if (entity instanceof Interaction interaction) {
|
||||
// handleCollisionEntityLoadOnEntitiesLoad(interaction);
|
||||
// } else if (entity instanceof Boat boat) {
|
||||
// handleCollisionEntityLoadOnEntitiesLoad(boat);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,174 +132,165 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
return this.furnitureByEntityId.get(entityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomFurniture.Builder furnitureBuilder() {
|
||||
return BukkitCustomFurniture.builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FurnitureElement.Builder furnitureElementBuilder() {
|
||||
return BukkitFurnitureElement.builder();
|
||||
}
|
||||
|
||||
protected void handleBaseEntityUnload(Entity entity) {
|
||||
int id = entity.getEntityId();
|
||||
BukkitFurniture furniture = this.furnitureByRealEntityId.remove(id);
|
||||
if (furniture != null) {
|
||||
Location location = entity.getLocation();
|
||||
boolean isPreventing = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
if (!isPreventing) {
|
||||
furniture.destroySeats();
|
||||
}
|
||||
for (int sub : furniture.entityIds()) {
|
||||
this.furnitureByEntityId.remove(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleCollisionEntityUnload(Entity entity) {
|
||||
int id = entity.getEntityId();
|
||||
this.furnitureByRealEntityId.remove(id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // just a misleading name `getTrackedPlayers`
|
||||
protected void handleBaseEntityLoadLate(ItemDisplay display, int depth) {
|
||||
// must be a furniture item
|
||||
String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING);
|
||||
if (id == null) return;
|
||||
|
||||
Key key = Key.of(id);
|
||||
Optional<CustomFurniture> optionalFurniture = furnitureById(key);
|
||||
if (optionalFurniture.isEmpty()) return;
|
||||
|
||||
CustomFurniture customFurniture = optionalFurniture.get();
|
||||
BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
|
||||
if (previous != null) return;
|
||||
|
||||
Location location = display.getLocation();
|
||||
boolean above1_20_1 = VersionHelper.isOrAbove1_20_2();
|
||||
boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
if (above1_20_1) {
|
||||
if (!preventChange) {
|
||||
BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
furniture.initializeColliders();
|
||||
for (Player player : display.getTrackedPlayers()) {
|
||||
BukkitAdaptors.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
this.plugin.networkManager().sendPacket(BukkitAdaptors.adapt(player), furniture.spawnPacket(player));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
for (Player player : display.getTrackedPlayers()) {
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
serverPlayer.entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
this.plugin.networkManager().sendPacket(serverPlayer, furniture.spawnPacket(player));
|
||||
}
|
||||
if (preventChange) {
|
||||
this.plugin.scheduler().sync().runLater(furniture::initializeColliders, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
} else {
|
||||
furniture.initializeColliders();
|
||||
}
|
||||
}
|
||||
if (depth > 2) return;
|
||||
this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
}
|
||||
|
||||
protected void handleCollisionEntityLoadLate(Entity entity, int depth) {
|
||||
// remove the entity if it's not a collision entity, it might be wrongly copied by WorldEdit
|
||||
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) {
|
||||
return;
|
||||
}
|
||||
// not a collision entity
|
||||
Byte flag = entity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
if (flag == null || flag != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = entity.getLocation();
|
||||
World world = location.getWorld();
|
||||
int chunkX = location.getBlockX() >> 4;
|
||||
int chunkZ = location.getBlockZ() >> 4;
|
||||
if (!FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world), chunkX, chunkZ)) {
|
||||
entity.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (depth > 2) return;
|
||||
plugin.scheduler().sync().runLater(() -> {
|
||||
handleCollisionEntityLoadLate(entity, depth + 1);
|
||||
}, 1, world, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public void handleBaseEntityLoadEarly(ItemDisplay display) {
|
||||
String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING);
|
||||
if (id == null) return;
|
||||
// Remove the entity if it's not a valid furniture
|
||||
if (Config.handleInvalidFurniture()) {
|
||||
String mapped = Config.furnitureMappings().get(id);
|
||||
if (mapped != null) {
|
||||
if (mapped.isEmpty()) {
|
||||
display.remove();
|
||||
return;
|
||||
} else {
|
||||
id = mapped;
|
||||
display.getPersistentDataContainer().set(FURNITURE_KEY, PersistentDataType.STRING, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Key key = Key.of(id);
|
||||
Optional<CustomFurniture> optionalFurniture = furnitureById(key);
|
||||
if (optionalFurniture.isPresent()) {
|
||||
CustomFurniture customFurniture = optionalFurniture.get();
|
||||
BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
|
||||
if (previous != null) return;
|
||||
BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
furniture.initializeColliders(); // safely do it here
|
||||
}
|
||||
}
|
||||
|
||||
public void handleCollisionEntityLoadOnEntitiesLoad(Entity collisionEntity) {
|
||||
// faster
|
||||
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(collisionEntity) instanceof CollisionEntity) {
|
||||
collisionEntity.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// not a collision entity
|
||||
Byte flag = collisionEntity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
if (flag == null || flag != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
collisionEntity.remove();
|
||||
}
|
||||
|
||||
private FurnitureExtraData getFurnitureExtraData(Entity baseEntity) throws IOException {
|
||||
byte[] extraData = baseEntity.getPersistentDataContainer().get(FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY);
|
||||
if (extraData == null) return FurnitureExtraData.builder().build();
|
||||
return FurnitureExtraData.fromBytes(extraData);
|
||||
}
|
||||
|
||||
private synchronized BukkitFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture) {
|
||||
FurnitureExtraData extraData;
|
||||
try {
|
||||
extraData = getFurnitureExtraData(display);
|
||||
} catch (IOException e) {
|
||||
extraData = FurnitureExtraData.builder().build();
|
||||
plugin.logger().warn("Furniture extra data could not be loaded", e);
|
||||
}
|
||||
BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, extraData);
|
||||
this.furnitureByRealEntityId.put(bukkitFurniture.baseEntityId(), bukkitFurniture);
|
||||
for (int entityId : bukkitFurniture.entityIds()) {
|
||||
this.furnitureByEntityId.put(entityId, bukkitFurniture);
|
||||
}
|
||||
for (Collider collisionEntity : bukkitFurniture.collisionEntities()) {
|
||||
int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle());
|
||||
this.furnitureByRealEntityId.put(collisionEntityId, bukkitFurniture);
|
||||
}
|
||||
return bukkitFurniture;
|
||||
}
|
||||
//
|
||||
// protected void handleBaseEntityUnload(Entity entity) {
|
||||
// int id = entity.getEntityId();
|
||||
// BukkitFurniture furniture = this.furnitureByRealEntityId.remove(id);
|
||||
// if (furniture != null) {
|
||||
// Location location = entity.getLocation();
|
||||
// boolean isPreventing = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
// if (!isPreventing) {
|
||||
// furniture.destroySeats();
|
||||
// }
|
||||
// for (int sub : furniture.entityIds()) {
|
||||
// this.furnitureByEntityId.remove(sub);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// protected void handleCollisionEntityUnload(Entity entity) {
|
||||
// int id = entity.getEntityId();
|
||||
// this.furnitureByRealEntityId.remove(id);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("deprecation") // just a misleading name `getTrackedPlayers`
|
||||
// protected void handleBaseEntityLoadLate(ItemDisplay display, int depth) {
|
||||
// // must be a furniture item
|
||||
// String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING);
|
||||
// if (id == null) return;
|
||||
//
|
||||
// Key key = Key.of(id);
|
||||
// Optional<FurnitureConfig> optionalFurniture = furnitureById(key);
|
||||
// if (optionalFurniture.isEmpty()) return;
|
||||
//
|
||||
// FurnitureConfig customFurniture = optionalFurniture.get();
|
||||
// BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
|
||||
// if (previous != null) return;
|
||||
//
|
||||
// Location location = display.getLocation();
|
||||
// boolean above1_20_1 = VersionHelper.isOrAbove1_20_2();
|
||||
// boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
// if (above1_20_1) {
|
||||
// if (!preventChange) {
|
||||
// BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
// furniture.initializeColliders();
|
||||
// for (Player player : display.getTrackedPlayers()) {
|
||||
// BukkitAdaptors.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
// this.plugin.networkManager().sendPacket(BukkitAdaptors.adapt(player), furniture.spawnPacket(player));
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
// for (Player player : display.getTrackedPlayers()) {
|
||||
// BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||
// serverPlayer.entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
|
||||
// this.plugin.networkManager().sendPacket(serverPlayer, furniture.spawnPacket(player));
|
||||
// }
|
||||
// if (preventChange) {
|
||||
// this.plugin.scheduler().sync().runLater(furniture::initializeColliders, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
// } else {
|
||||
// furniture.initializeColliders();
|
||||
// }
|
||||
// }
|
||||
// if (depth > 2) return;
|
||||
// this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
// }
|
||||
//
|
||||
// protected void handleCollisionEntityLoadLate(Entity entity, int depth) {
|
||||
// // remove the entity if it's not a collision entity, it might be wrongly copied by WorldEdit
|
||||
// if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) {
|
||||
// return;
|
||||
// }
|
||||
// // not a collision entity
|
||||
// Byte flag = entity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
// if (flag == null || flag != 1) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// Location location = entity.getLocation();
|
||||
// World world = location.getWorld();
|
||||
// int chunkX = location.getBlockX() >> 4;
|
||||
// int chunkZ = location.getBlockZ() >> 4;
|
||||
// if (!FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world), chunkX, chunkZ)) {
|
||||
// entity.remove();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (depth > 2) return;
|
||||
// plugin.scheduler().sync().runLater(() -> {
|
||||
// handleCollisionEntityLoadLate(entity, depth + 1);
|
||||
// }, 1, world, chunkX, chunkZ);
|
||||
// }
|
||||
//
|
||||
// public void handleBaseEntityLoadEarly(ItemDisplay display) {
|
||||
// String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING);
|
||||
// if (id == null) return;
|
||||
// // Remove the entity if it's not a valid furniture
|
||||
// if (Config.handleInvalidFurniture()) {
|
||||
// String mapped = Config.furnitureMappings().get(id);
|
||||
// if (mapped != null) {
|
||||
// if (mapped.isEmpty()) {
|
||||
// display.remove();
|
||||
// return;
|
||||
// } else {
|
||||
// id = mapped;
|
||||
// display.getPersistentDataContainer().set(FURNITURE_KEY, PersistentDataType.STRING, id);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Key key = Key.of(id);
|
||||
// Optional<FurnitureConfig> optionalFurniture = furnitureById(key);
|
||||
// if (optionalFurniture.isPresent()) {
|
||||
// FurnitureConfig customFurniture = optionalFurniture.get();
|
||||
// BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
|
||||
// if (previous != null) return;
|
||||
// BukkitFurniture furniture = addNewFurniture(display, customFurniture);
|
||||
// furniture.initializeColliders(); // safely do it here
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void handleCollisionEntityLoadOnEntitiesLoad(Entity collisionEntity) {
|
||||
// // faster
|
||||
// if (FastNMS.INSTANCE.method$CraftEntity$getHandle(collisionEntity) instanceof CollisionEntity) {
|
||||
// collisionEntity.remove();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // not a collision entity
|
||||
// Byte flag = collisionEntity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
// if (flag == null || flag != 1) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// collisionEntity.remove();
|
||||
// }
|
||||
//
|
||||
// private FurnitureDataAccessor getFurnitureExtraData(Entity baseEntity) throws IOException {
|
||||
// byte[] extraData = baseEntity.getPersistentDataContainer().get(FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY);
|
||||
// if (extraData == null) return FurnitureDataAccessor.builder().build();
|
||||
// return FurnitureDataAccessor.fromBytes(extraData);
|
||||
// }
|
||||
//
|
||||
// private synchronized BukkitFurniture addNewFurniture(ItemDisplay display, FurnitureConfig furniture) {
|
||||
// FurnitureDataAccessor extraData;
|
||||
// try {
|
||||
// extraData = getFurnitureExtraData(display);
|
||||
// } catch (IOException e) {
|
||||
// extraData = FurnitureDataAccessor.builder().build();
|
||||
// plugin.logger().warn("Furniture extra data could not be loaded", e);
|
||||
// }
|
||||
// BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, extraData);
|
||||
// this.furnitureByRealEntityId.put(bukkitFurniture.baseEntityId(), bukkitFurniture);
|
||||
// for (int entityId : bukkitFurniture.entityIds()) {
|
||||
// this.furnitureByEntityId.put(entityId, bukkitFurniture);
|
||||
// }
|
||||
// for (Collider collisionEntity : bukkitFurniture.collisionEntities()) {
|
||||
// int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle());
|
||||
// this.furnitureByRealEntityId.put(collisionEntityId, bukkitFurniture);
|
||||
// }
|
||||
// return bukkitFurniture;
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected HitBoxConfig defaultHitBox() {
|
||||
|
||||
@@ -1,18 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FurnitureEventListener implements Listener {
|
||||
private final BukkitFurnitureManager manager;
|
||||
@@ -21,77 +9,77 @@ public class FurnitureEventListener implements Listener {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load Entities
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntitiesLoadEarly(EntitiesLoadEvent event) {
|
||||
List<Entity> entities = event.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay itemDisplay) {
|
||||
this.manager.handleBaseEntityLoadEarly(itemDisplay);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onWorldLoad(WorldLoadEvent event) {
|
||||
List<Entity> entities = event.getWorld().getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay itemDisplay) {
|
||||
this.manager.handleBaseEntityLoadEarly(itemDisplay);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityLoad(EntityAddToWorldEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (entity instanceof ItemDisplay itemDisplay) {
|
||||
this.manager.handleBaseEntityLoadLate(itemDisplay, 0);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityLoadLate(entity, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unload Entities
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onChunkUnload(ChunkUnloadEvent event) {
|
||||
Entity[] entities = event.getChunk().getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay) {
|
||||
this.manager.handleBaseEntityUnload(entity);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onWorldUnload(WorldUnloadEvent event) {
|
||||
List<Entity> entities = event.getWorld().getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay) {
|
||||
this.manager.handleBaseEntityUnload(entity);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onEntityUnload(EntityRemoveFromWorldEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (entity instanceof ItemDisplay) {
|
||||
this.manager.handleBaseEntityUnload(entity);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
// /*
|
||||
// * Load Entities
|
||||
// */
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
// public void onEntitiesLoadEarly(EntitiesLoadEvent event) {
|
||||
// List<Entity> entities = event.getEntities();
|
||||
// for (Entity entity : entities) {
|
||||
// if (entity instanceof ItemDisplay itemDisplay) {
|
||||
// this.manager.handleBaseEntityLoadEarly(itemDisplay);
|
||||
// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
// this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
// public void onWorldLoad(WorldLoadEvent event) {
|
||||
// List<Entity> entities = event.getWorld().getEntities();
|
||||
// for (Entity entity : entities) {
|
||||
// if (entity instanceof ItemDisplay itemDisplay) {
|
||||
// this.manager.handleBaseEntityLoadEarly(itemDisplay);
|
||||
// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
// this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
// public void onEntityLoad(EntityAddToWorldEvent event) {
|
||||
// Entity entity = event.getEntity();
|
||||
// if (entity instanceof ItemDisplay itemDisplay) {
|
||||
// this.manager.handleBaseEntityLoadLate(itemDisplay, 0);
|
||||
// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
// this.manager.handleCollisionEntityLoadLate(entity, 0);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Unload Entities
|
||||
// */
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
// public void onChunkUnload(ChunkUnloadEvent event) {
|
||||
// Entity[] entities = event.getChunk().getEntities();
|
||||
// for (Entity entity : entities) {
|
||||
// if (entity instanceof ItemDisplay) {
|
||||
// this.manager.handleBaseEntityUnload(entity);
|
||||
// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
// this.manager.handleCollisionEntityUnload(entity);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
// public void onWorldUnload(WorldUnloadEvent event) {
|
||||
// List<Entity> entities = event.getWorld().getEntities();
|
||||
// for (Entity entity : entities) {
|
||||
// if (entity instanceof ItemDisplay) {
|
||||
// this.manager.handleBaseEntityUnload(entity);
|
||||
// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
// this.manager.handleCollisionEntityUnload(entity);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
// public void onEntityUnload(EntityRemoveFromWorldEvent event) {
|
||||
// Entity entity = event.getEntity();
|
||||
// if (entity instanceof ItemDisplay) {
|
||||
// this.manager.handleBaseEntityUnload(entity);
|
||||
// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
// this.manager.handleCollisionEntityUnload(entity);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Color;
|
||||
|
||||
public record ItemColorSource(Color dyedColor, int[] fireworkColors) {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.element;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs;
|
||||
|
||||
public class BukkitFurnitureElementConfigs extends FurnitureElementConfigs {
|
||||
|
||||
static {
|
||||
register(ITEM_DISPLAY, ItemDisplayFurnitureElementConfig.FACTORY);
|
||||
}
|
||||
|
||||
private BukkitFurnitureElementConfigs() {}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.element;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
|
||||
public class ItemDisplayFurnitureElement implements FurnitureElement {
|
||||
private final ItemDisplayFurnitureElementConfig config;
|
||||
|
||||
public ItemDisplayFurnitureElement(ItemDisplayFurnitureElementConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Player player) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(Player player) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.element;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.ItemColorSource;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.core.entity.display.Billboard;
|
||||
import net.momirealms.craftengine.core.entity.display.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.data.FireworkExplosion;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig<ItemDisplayFurnitureElement> {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final BiFunction<Player, ItemColorSource, List<Object>> lazyMetadataPacket;
|
||||
private final BiFunction<Player, ItemColorSource, Item<?>> item;
|
||||
private final Vector3f scale;
|
||||
private final Vector3f position;
|
||||
private final Vector3f translation;
|
||||
private final float xRot;
|
||||
private final float yRot;
|
||||
private final Quaternionf rotation;
|
||||
private final ItemDisplayContext displayContext;
|
||||
private final Billboard billboard;
|
||||
private final float shadowRadius;
|
||||
private final float shadowStrength;
|
||||
private final boolean applyDyedColor;
|
||||
|
||||
public ItemDisplayFurnitureElementConfig(BiFunction<Player, ItemColorSource, Item<?>> item,
|
||||
Vector3f scale,
|
||||
Vector3f position,
|
||||
Vector3f translation,
|
||||
float xRot,
|
||||
float yRot,
|
||||
Quaternionf rotation,
|
||||
ItemDisplayContext displayContext,
|
||||
Billboard billboard,
|
||||
float shadowRadius,
|
||||
float shadowStrength,
|
||||
boolean applyDyedColor) {
|
||||
this.scale = scale;
|
||||
this.position = position;
|
||||
this.translation = translation;
|
||||
this.xRot = xRot;
|
||||
this.yRot = yRot;
|
||||
this.rotation = rotation;
|
||||
this.displayContext = displayContext;
|
||||
this.billboard = billboard;
|
||||
this.shadowRadius = shadowRadius;
|
||||
this.shadowStrength = shadowStrength;
|
||||
this.applyDyedColor = applyDyedColor;
|
||||
this.item = item;
|
||||
this.lazyMetadataPacket = (player, source) -> {
|
||||
List<Object> dataValues = new ArrayList<>();
|
||||
ItemDisplayEntityData.DisplayedItem.addEntityData(item.apply(player, source).getLiteralObject(), dataValues);
|
||||
ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues);
|
||||
ItemDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues);
|
||||
ItemDisplayEntityData.BillboardConstraints.addEntityData(this.billboard.id(), dataValues);
|
||||
ItemDisplayEntityData.Translation.addEntityData(this.translation, dataValues);
|
||||
ItemDisplayEntityData.DisplayType.addEntityData(this.displayContext.id(), dataValues);
|
||||
ItemDisplayEntityData.ShadowRadius.addEntityData(this.shadowRadius, dataValues);
|
||||
ItemDisplayEntityData.ShadowStrength.addEntityData(this.shadowStrength, dataValues);
|
||||
return dataValues;
|
||||
};
|
||||
}
|
||||
|
||||
public Vector3f scale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Vector3f translation() {
|
||||
return translation;
|
||||
}
|
||||
|
||||
public float xRot() {
|
||||
return xRot;
|
||||
}
|
||||
|
||||
public float yRot() {
|
||||
return yRot;
|
||||
}
|
||||
|
||||
public Quaternionf rotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public ItemDisplayContext displayContext() {
|
||||
return displayContext;
|
||||
}
|
||||
|
||||
public Billboard billboard() {
|
||||
return billboard;
|
||||
}
|
||||
|
||||
public float shadowRadius() {
|
||||
return shadowRadius;
|
||||
}
|
||||
|
||||
public float shadowStrength() {
|
||||
return shadowStrength;
|
||||
}
|
||||
|
||||
public boolean applyDyedColor() {
|
||||
return applyDyedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemDisplayFurnitureElement create(@NotNull WorldPosition position) {
|
||||
return new ItemDisplayFurnitureElement(this);
|
||||
}
|
||||
|
||||
public static class Factory implements FurnitureElementConfigFactory {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <E extends FurnitureElement> FurnitureElementConfig<E> create(Map<String, Object> arguments) {
|
||||
Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.furniture.element.item_display.missing_item"));
|
||||
boolean applyDyedColor = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("apply-dyed-color", true), "apply-dyed-color");
|
||||
return (FurnitureElementConfig<E>) new ItemDisplayFurnitureElementConfig(
|
||||
(player, colorSource) -> {
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player);
|
||||
if (applyDyedColor && colorSource != null && wrappedItem != null) {
|
||||
Optional.ofNullable(colorSource.dyedColor()).ifPresent(wrappedItem::dyedColor);
|
||||
Optional.ofNullable(colorSource.fireworkColors()).ifPresent(colors -> wrappedItem.fireworkExplosion(new FireworkExplosion(
|
||||
FireworkExplosion.Shape.SMALL_BALL,
|
||||
new IntArrayList(colors),
|
||||
new IntArrayList(),
|
||||
false,
|
||||
false
|
||||
)));
|
||||
}
|
||||
return Optional.ofNullable(wrappedItem).orElseGet(() -> BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, null));
|
||||
},
|
||||
ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"),
|
||||
ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position"),
|
||||
ResourceConfigUtils.getAsVector3f(arguments.get("translation"), "translation"),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch"),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"),
|
||||
ResourceConfigUtils.getAsQuaternionf(arguments.getOrDefault("rotation", 0f), "rotation"),
|
||||
ResourceConfigUtils.getAsEnum(ResourceConfigUtils.get(arguments, "display-context", "display-transform"), ItemDisplayContext.class, ItemDisplayContext.NONE),
|
||||
ResourceConfigUtils.getAsEnum(arguments.get("billboard"), Billboard.class, Billboard.FIXED),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-radius", 0f), "shadow-radius"),
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-strength", 1f), "shadow-strength"),
|
||||
applyDyedColor
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxTypes;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxTypes;
|
||||
|
||||
public class BukkitHitBoxTypes extends HitBoxTypes {
|
||||
|
||||
|
||||
@@ -1,42 +1,34 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.AbstractHitBoxConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxTypes;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.Map;
|
||||
|
||||
public class CustomHitBoxConfig extends AbstractHitBoxConfig {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final float scale;
|
||||
private final EntityType entityType;
|
||||
private final List<Object> cachedValues = new ArrayList<>();
|
||||
|
||||
public CustomHitBoxConfig(SeatConfig[] seats, Vector3f position, EntityType type, float scale, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
||||
public CustomHitBoxConfig(SeatConfig[] seats,
|
||||
Vector3f position,
|
||||
EntityType type,
|
||||
float scale,
|
||||
boolean blocksBuilding,
|
||||
boolean canBeHitByProjectile) {
|
||||
super(seats, position, false, blocksBuilding, canBeHitByProjectile);
|
||||
this.scale = scale;
|
||||
this.entityType = type;
|
||||
BaseEntityData.NoGravity.addEntityDataIfNotDefaultValue(true, this.cachedValues);
|
||||
BaseEntityData.Silent.addEntityDataIfNotDefaultValue(true, this.cachedValues);
|
||||
BaseEntityData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedValues);
|
||||
}
|
||||
|
||||
public EntityType entityType() {
|
||||
@@ -52,41 +44,13 @@ public class CustomHitBoxConfig extends AbstractHitBoxConfig {
|
||||
return HitBoxTypes.CUSTOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, Consumer<HitBoxPart> aabb) {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
try {
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
entityId[0], UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.yRot(),
|
||||
FastNMS.INSTANCE.method$CraftEntityType$toNMSEntityType(this.entityType), 0, CoreReflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
||||
if (VersionHelper.isOrAbove1_20_5() && this.scale != 1) {
|
||||
Object attributeInstance = CoreReflections.constructor$AttributeInstance.newInstance(MAttributeHolders.SCALE, (Consumer<?>) (o) -> {});
|
||||
CoreReflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale);
|
||||
packets.accept(NetworkReflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityId[0], Collections.singletonList(attributeInstance)), false);
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to construct custom hitbox spawn packet", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initShapeForPlacement(double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<AABB> aabbs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] acquireEntityIds(Supplier<Integer> entityIdSupplier) {
|
||||
return new int[] {entityIdSupplier.get()};
|
||||
}
|
||||
|
||||
public static class Factory implements HitBoxConfigFactory {
|
||||
|
||||
@Override
|
||||
public HitBoxConfig create(Map<String, Object> arguments) {
|
||||
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
||||
float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1), "scale");
|
||||
String type = (String) arguments.getOrDefault("entity-type", "slime");
|
||||
String type = (String) arguments.getOrDefault("entity-id", "slime");
|
||||
EntityType entityType = Registry.ENTITY_TYPE.get(new NamespacedKey("minecraft", type));
|
||||
if (entityType == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.hitbox.custom.invalid_entity", new IllegalArgumentException("EntityType not found: " + type), type);
|
||||
|
||||
@@ -7,7 +7,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.*;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
@@ -5,7 +5,8 @@ import net.momirealms.craftengine.bukkit.entity.furniture.BukkitCollider;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.*;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
@@ -9,7 +9,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeH
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.*;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
|
||||
@@ -1,43 +1,18 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptPlaceEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfig;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
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.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FurnitureItemBehavior extends ItemBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
@@ -57,121 +32,121 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
}
|
||||
|
||||
public InteractionResult place(UseOnContext context) {
|
||||
Optional<CustomFurniture> optionalCustomFurniture = BukkitFurnitureManager.instance().furnitureById(this.id);
|
||||
if (optionalCustomFurniture.isEmpty()) {
|
||||
CraftEngine.instance().logger().warn("Furniture " + this.id + " not found");
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
CustomFurniture customFurniture = optionalCustomFurniture.get();
|
||||
|
||||
Direction clickedFace = context.getClickedFace();
|
||||
AnchorType anchorType = switch (clickedFace) {
|
||||
case EAST, WEST, NORTH, SOUTH -> AnchorType.WALL;
|
||||
case UP -> AnchorType.GROUND;
|
||||
case DOWN -> AnchorType.CEILING;
|
||||
};
|
||||
|
||||
CustomFurniture.Placement placement = customFurniture.getPlacement(anchorType);
|
||||
if (placement == null) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
Player player = context.getPlayer();
|
||||
// todo adventure check
|
||||
if (player != null && player.isAdventureMode()) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
Vec3d clickedPosition = context.getClickLocation();
|
||||
|
||||
// trigger event
|
||||
org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null;
|
||||
World world = (World) context.getLevel().platformWorld();
|
||||
|
||||
// get position and rotation for placement
|
||||
Vec3d finalPlacePosition;
|
||||
double furnitureYaw;
|
||||
if (anchorType == AnchorType.WALL) {
|
||||
furnitureYaw = Direction.getYaw(clickedFace);
|
||||
if (clickedFace == Direction.EAST || clickedFace == Direction.WEST) {
|
||||
Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.y(), clickedPosition.z()));
|
||||
finalPlacePosition = new Vec3d(clickedPosition.x(), xz.left(), xz.right());
|
||||
} else {
|
||||
Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.y()));
|
||||
finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z());
|
||||
}
|
||||
} else {
|
||||
furnitureYaw = placement.rotationRule().apply(180 + (player != null ? player.yRot() : 0));
|
||||
Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z()));
|
||||
finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right());
|
||||
}
|
||||
|
||||
Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0);
|
||||
|
||||
List<AABB> aabbs = new ArrayList<>();
|
||||
for (HitBoxConfig hitBoxConfig : placement.hitBoxConfigs()) {
|
||||
hitBoxConfig.initShapeForPlacement(finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - furnitureYaw), 0).conjugate(), aabbs::add);
|
||||
}
|
||||
if (!aabbs.isEmpty()) {
|
||||
if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!BukkitCraftEngine.instance().antiGriefProvider().canPlace(bukkitPlayer, furnitureLocation)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(),
|
||||
DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z()));
|
||||
if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
Item<?> item = context.getItem();
|
||||
// 不可能
|
||||
if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL;
|
||||
|
||||
BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place(
|
||||
furnitureLocation.clone(), customFurniture,
|
||||
FurnitureExtraData.builder()
|
||||
.item(item.copyWithCount(1))
|
||||
.anchorType(anchorType)
|
||||
.dyedColor(item.dyedColor().orElse(null))
|
||||
.fireworkExplosionColors(item.fireworkExplosion().map(explosion -> explosion.colors().toIntArray()).orElse(null))
|
||||
.build(), false);
|
||||
|
||||
if (player != null) {
|
||||
FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand());
|
||||
if (EventUtils.fireAndCheckCancel(placeEvent)) {
|
||||
bukkitFurniture.destroy();
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.FURNITURE, bukkitFurniture)
|
||||
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation))
|
||||
.withParameter(DirectContextParameters.EVENT, dummy)
|
||||
.withParameter(DirectContextParameters.HAND, context.getHand())
|
||||
.withParameter(DirectContextParameters.ITEM_IN_HAND, item)
|
||||
);
|
||||
customFurniture.execute(functionContext, EventTrigger.PLACE);
|
||||
if (dummy.isCancelled()) {
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
if (!player.canInstabuild()) {
|
||||
item.count(item.count() - 1);
|
||||
}
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
|
||||
context.getLevel().playBlockSound(finalPlacePosition, customFurniture.settings().sounds().placeSound());
|
||||
// Optional<FurnitureConfig> optionalCustomFurniture = BukkitFurnitureManager.instance().furnitureById(this.id);
|
||||
// if (optionalCustomFurniture.isEmpty()) {
|
||||
// CraftEngine.instance().logger().warn("Furniture " + this.id + " not found");
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
// FurnitureConfig customFurniture = optionalCustomFurniture.get();
|
||||
//
|
||||
// Direction clickedFace = context.getClickedFace();
|
||||
// AnchorType anchorType = switch (clickedFace) {
|
||||
// case EAST, WEST, NORTH, SOUTH -> AnchorType.WALL;
|
||||
// case UP -> AnchorType.GROUND;
|
||||
// case DOWN -> AnchorType.CEILING;
|
||||
// };
|
||||
//
|
||||
// FurnitureConfig.Variant placement = customFurniture.getPlacement(anchorType);
|
||||
// if (placement == null) {
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
//
|
||||
// Player player = context.getPlayer();
|
||||
// // todo adventure check
|
||||
// if (player != null && player.isAdventureMode()) {
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
//
|
||||
// Vec3d clickedPosition = context.getClickLocation();
|
||||
//
|
||||
// // trigger event
|
||||
// org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null;
|
||||
// World world = (World) context.getLevel().platformWorld();
|
||||
//
|
||||
// // get position and rotation for placement
|
||||
// Vec3d finalPlacePosition;
|
||||
// double furnitureYaw;
|
||||
// if (anchorType == AnchorType.WALL) {
|
||||
// furnitureYaw = Direction.getYaw(clickedFace);
|
||||
// if (clickedFace == Direction.EAST || clickedFace == Direction.WEST) {
|
||||
// Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.y(), clickedPosition.z()));
|
||||
// finalPlacePosition = new Vec3d(clickedPosition.x(), xz.left(), xz.right());
|
||||
// } else {
|
||||
// Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.y()));
|
||||
// finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z());
|
||||
// }
|
||||
// } else {
|
||||
// furnitureYaw = placement.rotationRule().apply(180 + (player != null ? player.yRot() : 0));
|
||||
// Pair<Double, Double> xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z()));
|
||||
// finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right());
|
||||
// }
|
||||
//
|
||||
// Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0);
|
||||
//
|
||||
// List<AABB> aabbs = new ArrayList<>();
|
||||
// for (HitBoxConfig hitBoxConfig : placement.hitBoxConfigs()) {
|
||||
// hitBoxConfig.initShapeForPlacement(finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - furnitureYaw), 0).conjugate(), aabbs::add);
|
||||
// }
|
||||
// if (!aabbs.isEmpty()) {
|
||||
// if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) {
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!BukkitCraftEngine.instance().antiGriefProvider().canPlace(bukkitPlayer, furnitureLocation)) {
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
//
|
||||
// if (player != null) {
|
||||
// FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(),
|
||||
// DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z()));
|
||||
// if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Item<?> item = context.getItem();
|
||||
// // 不可能
|
||||
// if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL;
|
||||
//
|
||||
// BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place(
|
||||
// furnitureLocation.clone(), customFurniture,
|
||||
// FurnitureDataAccessor.builder()
|
||||
// .item(item.copyWithCount(1))
|
||||
// .anchorType(anchorType)
|
||||
// .dyedColor(item.dyedColor().orElse(null))
|
||||
// .fireworkExplosionColors(item.fireworkExplosion().map(explosion -> explosion.colors().toIntArray()).orElse(null))
|
||||
// .build(), false);
|
||||
//
|
||||
// if (player != null) {
|
||||
// FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand());
|
||||
// if (EventUtils.fireAndCheckCancel(placeEvent)) {
|
||||
// bukkitFurniture.destroy();
|
||||
// return InteractionResult.FAIL;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Cancellable dummy = Cancellable.dummy();
|
||||
// PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder()
|
||||
// .withParameter(DirectContextParameters.FURNITURE, bukkitFurniture)
|
||||
// .withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation))
|
||||
// .withParameter(DirectContextParameters.EVENT, dummy)
|
||||
// .withParameter(DirectContextParameters.HAND, context.getHand())
|
||||
// .withParameter(DirectContextParameters.ITEM_IN_HAND, item)
|
||||
// );
|
||||
// customFurniture.execute(functionContext, EventTrigger.PLACE);
|
||||
// if (dummy.isCancelled()) {
|
||||
// return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
// }
|
||||
//
|
||||
// if (player != null) {
|
||||
// if (!player.canInstabuild()) {
|
||||
// item.count(item.count() - 1);
|
||||
// }
|
||||
// player.swingHand(context.getHand());
|
||||
// }
|
||||
//
|
||||
// context.getLevel().playBlockSound(finalPlacePosition, customFurniture.settings().sounds().placeSound());
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.renderer.element.BukkitBlockEntityElementConfigs;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.element.BukkitFurnitureElementConfigs;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes;
|
||||
import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeatManager;
|
||||
@@ -162,6 +163,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
BukkitItemBehaviors.init();
|
||||
BukkitHitBoxTypes.init();
|
||||
BukkitBlockEntityElementConfigs.init();
|
||||
BukkitFurnitureElementConfigs.init();
|
||||
// 初始化 onload 阶段的兼容性
|
||||
super.compatibilityManager().onLoad();
|
||||
// 创建网络管理器
|
||||
|
||||
@@ -39,7 +39,7 @@ public class BukkitPlatform implements Platform {
|
||||
Map<String, Object> map = (Map<String, Object>) MRegistryOps.NBT.convertTo(MRegistryOps.JAVA, tag);
|
||||
return map.get("root");
|
||||
} catch (CommandSyntaxException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.snbt.invalid_syntax", e, nbt);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.snbt.invalid_syntax", e, nbt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class BukkitPlatform implements Platform {
|
||||
CompoundTag map = (CompoundTag) MRegistryOps.NBT.convertTo(MRegistryOps.SPARROW_NBT, tag);
|
||||
return map.get("root");
|
||||
} catch (CommandSyntaxException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.type.snbt.invalid_syntax", e, nbt);
|
||||
throw new LocalizedResourceConfigException("warning.config.id.snbt.invalid_syntax", e, nbt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class DebugItemDataCommand extends BukkitCommandFeature<CommandSender> {
|
||||
} else if (nbt instanceof short[]) {
|
||||
value = Arrays.toString((short[]) nbt);
|
||||
} else {
|
||||
value = "Unknown array type";
|
||||
value = "Unknown array id";
|
||||
}
|
||||
} else {
|
||||
value = nbt.toString();
|
||||
|
||||
@@ -5,7 +5,7 @@ import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.plugin.command.FlagKeys;
|
||||
@@ -42,19 +42,19 @@ public class DebugSpawnFurnitureCommand extends BukkitCommandFeature<CommandSend
|
||||
return CompletableFuture.completedFuture(plugin().furnitureManager().cachedSuggestions());
|
||||
}
|
||||
}))
|
||||
.optional("anchor-type", EnumParser.enumParser(AnchorType.class))
|
||||
.optional("anchor-id", EnumParser.enumParser(AnchorType.class))
|
||||
.flag(FlagKeys.SILENT_FLAG)
|
||||
.handler(context -> {
|
||||
NamespacedKey namespacedKey = context.get("id");
|
||||
Key id = KeyUtils.namespacedKey2Key(namespacedKey);
|
||||
BukkitFurnitureManager furnitureManager = BukkitFurnitureManager.instance();
|
||||
Optional<CustomFurniture> optionalCustomFurniture = furnitureManager.furnitureById(id);
|
||||
Optional<FurnitureConfig> optionalCustomFurniture = furnitureManager.furnitureById(id);
|
||||
if (optionalCustomFurniture.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Location location = context.get("location");
|
||||
CustomFurniture customFurniture = optionalCustomFurniture.get();
|
||||
AnchorType anchorType = (AnchorType) context.optional("anchor-type").orElse(customFurniture.getAnyAnchorType());
|
||||
FurnitureConfig customFurniture = optionalCustomFurniture.get();
|
||||
AnchorType anchorType = (AnchorType) context.optional("anchor-id").orElse(customFurniture.getAnyAnchorType());
|
||||
boolean playSound = context.flags().hasFlag("silent");
|
||||
CraftEngineFurniture.place(location, customFurniture, anchorType, playSound);
|
||||
});
|
||||
|
||||
@@ -15,7 +15,6 @@ import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bukkit.parser.PlayerParser;
|
||||
import org.incendo.cloud.parser.standard.BooleanParser;
|
||||
import org.incendo.cloud.parser.standard.DoubleParser;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.advancement.network.AdvancementHolder;
|
||||
import net.momirealms.craftengine.core.advancement.network.AdvancementProgress;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxPart;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBox;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxPart;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
@@ -3711,11 +3711,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
if (actionType == 1) {
|
||||
// ATTACK
|
||||
boolean usingSecondaryAction = buf.readBoolean();
|
||||
if (entityId != furniture.baseEntityId()) {
|
||||
if (entityId != furniture.entityId()) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(furniture.baseEntityId());
|
||||
buf.writeVarInt(furniture.entityId());
|
||||
buf.writeVarInt(actionType);
|
||||
buf.writeBoolean(usingSecondaryAction);
|
||||
}
|
||||
@@ -3765,11 +3765,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
float z = buf.readFloat();
|
||||
InteractionHand hand = buf.readVarInt() == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
boolean usingSecondaryAction = buf.readBoolean();
|
||||
if (entityId != furniture.baseEntityId()) {
|
||||
if (entityId != furniture.entityId()) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(furniture.baseEntityId());
|
||||
buf.writeVarInt(furniture.entityId());
|
||||
buf.writeVarInt(actionType);
|
||||
buf.writeFloat(x).writeFloat(y).writeFloat(z);
|
||||
buf.writeVarInt(hand == InteractionHand.MAIN_HAND ? 0 : 1);
|
||||
@@ -3864,11 +3864,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
} else if (actionType == 0) {
|
||||
int hand = buf.readVarInt();
|
||||
boolean usingSecondaryAction = buf.readBoolean();
|
||||
if (entityId != furniture.baseEntityId()) {
|
||||
if (entityId != furniture.entityId()) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(furniture.baseEntityId());
|
||||
buf.writeVarInt(furniture.entityId());
|
||||
buf.writeVarInt(actionType);
|
||||
buf.writeVarInt(hand);
|
||||
buf.writeBoolean(usingSecondaryAction);
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ProjectilePacketHandler implements EntityPacketHandler {
|
||||
|
||||
public void convertAddCustomProjectilePacket(FriendlyByteBuf buf, ByteBufPacketEvent event) {
|
||||
UUID uuid = buf.readUUID();
|
||||
buf.readVarInt(); // type
|
||||
buf.readVarInt(); // id
|
||||
double x = buf.readDouble();
|
||||
double y = buf.readDouble();
|
||||
double z = buf.readDouble();
|
||||
|
||||
@@ -35,7 +35,7 @@ public class PayloadHelper {
|
||||
@SuppressWarnings("unchecked")
|
||||
NetworkCodec<FriendlyByteBuf, ModPacket> codec = (NetworkCodec<FriendlyByteBuf, ModPacket>) BuiltInRegistries.MOD_PACKET.getValue(data.type());
|
||||
if (codec == null) {
|
||||
CraftEngine.instance().logger().warn("Unknown data type class: " + data.getClass().getName());
|
||||
CraftEngine.instance().logger().warn("Unknown data id class: " + data.getClass().getName());
|
||||
return;
|
||||
}
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
@@ -65,7 +65,7 @@ public class PayloadHelper {
|
||||
@SuppressWarnings("unchecked")
|
||||
NetworkCodec<FriendlyByteBuf, ModPacket> codec = (NetworkCodec<FriendlyByteBuf, ModPacket>) BuiltInRegistries.MOD_PACKET.getValue(type);
|
||||
if (codec == null) {
|
||||
Debugger.COMMON.debug(() -> "Unknown data type received: " + type);
|
||||
Debugger.COMMON.debug(() -> "Unknown data id received: " + type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,9 @@ items:
|
||||
sounds:
|
||||
break: minecraft:block.bamboo_wood.break
|
||||
place: minecraft:block.bamboo_wood.place
|
||||
placement:
|
||||
variants:
|
||||
ground:
|
||||
loot-spawn-offset: 0.5,0.5,0
|
||||
rules:
|
||||
rotation: FOUR
|
||||
alignment: CENTER
|
||||
elements:
|
||||
- item: default:bench
|
||||
display-transform: NONE
|
||||
|
||||
@@ -160,8 +160,8 @@ warning.config.sound.missing_name: "<yellow>Problem in Datei <arg:0> gefunden -
|
||||
warning.config.jukebox_song.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Doppelter Jukebox-Song '<arg:1>'. Bitte prüfe, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow>Problem in Datei <arg:0> gefunden - Beim Jukebox-Song '<arg:1>' fehlt das erforderliche 'sound'-Argument.</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Doppeltes Furniture '<arg:1>'. Bitte prüfe, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow>Problem in Datei <arg:0> gefunden - Beim Furniture '<arg:1>' fehlt das erforderliche 'placement'-Argument.</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow>Problem in Datei <arg:0> gefunden - Beim Furniture '<arg:1>' fehlt das erforderliche 'item'-Argument für eines seiner Elemente.</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow>Problem in Datei <arg:0> gefunden - Beim Furniture '<arg:1>' fehlt das erforderliche 'variants'-Argument.</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow>Problem in Datei <arg:0> gefunden - Beim Furniture '<arg:1>' fehlt das erforderliche 'item'-Argument für eines seiner Elemente.</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow>Problem in Datei <arg:0> gefunden - Das Furniture '<arg:1>' verwendet einen unbekannten Einstellungs-Typ '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Das Furniture '<arg:1>' verwendet einen ungültigen Hitbox-Typ '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Problem in Datei <arg:0> gefunden - Das Furniture '<arg:1>' verwendet eine benutzerdefinierte Hitbox mit ungültigem Entity-Typ '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -190,8 +190,9 @@ warning.config.sound.missing_name: "<yellow>Issue found in file <arg:0> - The so
|
||||
warning.config.jukebox_song.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated jukebox song '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow>Issue found in file <arg:0> - The jukebox song '<arg:1>' is missing the required 'sound' argument.</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated furniture '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is missing the required 'placement' argument.</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is missing the required 'item' argument for one of its elements.</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is missing the required 'variants' argument.</yellow>"
|
||||
warning.config.furniture.element.invalid_type: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using an invalid element type '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is missing the required 'item' argument for 'item_display' element.</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using an unknown setting type '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using an invalid hitbox type '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Issue found in file <arg:0> - The furniture '<arg:1>' is using a custom hitbox with invalid entity type '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -111,8 +111,8 @@ warning.config.sound.missing_name: "<yellow>Problema encontrado en el archivo <a
|
||||
warning.config.jukebox_song.duplicate: "<yellow>Problema encontrado en el archivo <arg:0> - Canción de tocadiscos duplicada '<arg:1>'. Verifica si hay la misma configuración en otros archivos.</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow>Problema encontrado en el archivo <arg:0> - La canción de tocadiscos '<arg:1>' carece del argumento requerido 'sound'.</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow>Problema encontrado en el archivo <arg:0> - Mueble duplicado '<arg:1>'. Verifica si hay la misma configuración en otros archivos.</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' carece del argumento requerido 'placement'.</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' carece del argumento requerido 'item' para uno de sus elementos.</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' carece del argumento requerido 'variants'.</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' carece del argumento requerido 'item' para uno de sus elementos.</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' está usando un tipo de configuración desconocido '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' está usando un tipo de hitbox inválido '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Problema encontrado en el archivo <arg:0> - El mueble '<arg:1>' está usando un hitbox personalizado con un tipo de entidad inválido '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -175,8 +175,8 @@ warning.config.sound.missing_name: "<yellow>Problème trouvé dans le fichier <a
|
||||
warning.config.jukebox_song.duplicate: "<yellow>Problème trouvé dans le fichier <arg:0> - Chanson de jukebox dupliquée '<arg:1>'. Vérifiez s’il existe la même configuration dans d’autres fichiers.</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow>Problème trouvé dans le fichier <arg:0> - La chanson de jukebox '<arg:1>' manque l’argument obligatoire 'sound'.</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow>Problème trouvé dans le fichier <arg:0> - Meuble dupliqué '<arg:1>'. Vérifiez s’il existe la même configuration dans d’autres fichiers.</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' manque l’argument obligatoire 'placement'.</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' manque l’argument obligatoire 'item' pour un de ses éléments.</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' manque l’argument obligatoire 'variants'.</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' manque l’argument obligatoire 'item' pour un de ses éléments.</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' utilise un type de paramètre inconnu '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' utilise un type de hitbox invalide '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Problème trouvé dans le fichier <arg:0> - Le meuble '<arg:1>' utilise un hitbox personnalisé avec un type d’entité invalide '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -148,8 +148,8 @@ warning.config.sound.missing_name: "<yellow>Проблема найдена в
|
||||
warning.config.jukebox_song.duplicate: "<yellow>Проблема найдена в файле <arg:0> - Дублированная песня музыкального автомата '<arg:1>'. Проверьте, есть ли такая же конфигурация в других файлах.</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow>Проблема найдена в файле <arg:0> - В песне музыкального автомата '<arg:1>' отсутствует необходимый 'sound' аргумент.</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow>Проблема найдена в файле <arg:0> - Дублированная мебель '<arg:1>'. Проверьте, есть ли такая же конфигурация в других файлах.</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow>Проблема найдена в файле <arg:0> - В мебели '<arg:1>' отсутствует необходимый 'placement' аргумент.</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow>Проблема найдена в файле <arg:0> - В мебели '<arg:1>' отсутствует необходимый 'item' аргумент для одного из его элементов.</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow>Проблема найдена в файле <arg:0> - В мебели '<arg:1>' отсутствует необходимый 'variants' аргумент.</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow>Проблема найдена в файле <arg:0> - В мебели '<arg:1>' отсутствует необходимый 'item' аргумент для одного из его элементов.</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow>Проблема найдена в файле <arg:0> - Мебель '<arg:1>' использует неизвестный тип настройки '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>Проблема найдена в файле <arg:0> - Мебель '<arg:1>' использует недопустимый тип хитбокса '<arg:2>'.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Проблема найдена в файле <arg:0> - Мебель '<arg:1>' использует пользовательский хитбокс с недопустимым типом сущности '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -110,8 +110,8 @@ warning.config.sound.missing_name: "<yellow><arg:0> dosyasında sorun bulundu -
|
||||
warning.config.jukebox_song.duplicate: "<yellow><arg:0> dosyasında sorun bulundu - Yinelenen müzik çalar şarkısı '<arg:1>'. Diğer dosyalarda aynı yapılandırmanın olup olmadığını kontrol edin.</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' müzik çalar şarkısı gerekli 'sound' argümanı eksik.</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow><arg:0> dosyasında sorun bulundu - Yinelenen mobilya '<arg:1>'. Diğer dosyalarda aynı yapılandırmanın olup olmadığını kontrol edin.</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası gerekli 'placement' argümanı eksik.</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası, elementlerinden biri için gerekli 'item' argümanı eksik.</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası gerekli 'variants' argümanı eksik.</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası, elementlerinden biri için gerekli 'item' argümanı eksik.</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası bilinmeyen bir ayar türü '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası geçersiz bir hitbox türü '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' mobilyası, geçersiz varlık türü '<arg:2>' olan özel bir hitbox kullanıyor.</yellow>"
|
||||
|
||||
@@ -183,8 +183,8 @@ warning.config.sound.missing_name: "<yellow>在文件 <arg:0> 发现问题 - 音
|
||||
warning.config.jukebox_song.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的唱片机歌曲 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
|
||||
warning.config.jukebox_song.missing_sound: "<yellow>在文件 <arg:0> 发现问题 - 唱片机歌曲 '<arg:1>' 缺少必需的 'sound' 参数</yellow>"
|
||||
warning.config.furniture.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的家具 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
|
||||
warning.config.furniture.missing_placement: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 缺少必需的 'placement' 参数</yellow>"
|
||||
warning.config.furniture.element.missing_item: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 的某个元素缺少必需的 'item' 参数</yellow>"
|
||||
warning.config.furniture.missing_variants: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 缺少必需的 'variants' 参数</yellow>"
|
||||
warning.config.furniture.element.item_display.missing_item: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 的 'item_display' 元素缺少必需的 'item' 参数</yellow>"
|
||||
warning.config.furniture.settings.unknown: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 使用了未知的设置类型 '<arg:2>'</yellow>"
|
||||
warning.config.furniture.hitbox.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 使用了无效的碰撞箱类型 '<arg:2>'</yellow>"
|
||||
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>在文件 <arg:0> 发现问题 - 家具 '<arg:1>' 的自定义碰撞箱使用了无效的实体类型 '<arg:2>'</yellow>"
|
||||
|
||||
@@ -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);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
// external model providers
|
||||
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]),
|
||||
variants.put(variantName, new FurnitureVariant(
|
||||
elements.toArray(new FurnitureElementConfig[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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,26 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
package net.momirealms.craftengine.core.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBox;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxPart;
|
||||
import net.momirealms.craftengine.core.entity.seat.Seat;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.world.EntityHitResult;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BukkitHitBox implements HitBox {
|
||||
public abstract class AbstractHitBox implements HitBox {
|
||||
private final Furniture furniture;
|
||||
private final HitBoxConfig config;
|
||||
private final HitBoxPart[] parts;
|
||||
private final Seat<HitBox>[] seats;
|
||||
private Seat<HitBox>[] seats;
|
||||
|
||||
public BukkitHitBox(Furniture furniture, HitBoxConfig config, HitBoxPart[] parts) {
|
||||
public AbstractHitBox(Furniture furniture, HitBoxConfig config, HitBoxPart[] parts) {
|
||||
this.parts = parts;
|
||||
this.config = config;
|
||||
this.furniture = furniture;
|
||||
this.seats = createSeats(config);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Seat<HitBox>[] createSeats(HitBoxConfig config) {
|
||||
SeatConfig[] seatConfigs = config.seats();
|
||||
Seat<HitBox>[] seats = new Seat[seatConfigs.length];
|
||||
for (int i = 0; i < seatConfigs.length; i++) {
|
||||
seats[i] = new BukkitSeat<>(this, seatConfigs[i]);
|
||||
}
|
||||
return seats;
|
||||
}
|
||||
protected abstract void createSeats(HitBoxConfig config);
|
||||
|
||||
@Override
|
||||
public HitBoxPart[] parts() {
|
||||
@@ -65,6 +51,6 @@ public class BukkitHitBox implements HitBox {
|
||||
@Override
|
||||
public void saveCustomData(CompoundTag data) {
|
||||
data.putString("type", "furniture");
|
||||
data.putInt("entity_id", this.furniture.baseEntityId());
|
||||
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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user