9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

重构家具读取

This commit is contained in:
XiaoMoMi
2025-05-21 17:08:26 +08:00
parent 2f215e2140
commit c788689277
26 changed files with 585 additions and 352 deletions

View File

@@ -6,7 +6,8 @@ import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser; import ch.njol.skript.lang.SkriptParser;
import ch.njol.util.Kleenean; import ch.njol.util.Kleenean;
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -23,9 +24,9 @@ public class EffRemoveFurniture extends Effect {
protected void execute(Event e) { protected void execute(Event e) {
for (Entity entity : entities.getArray(e)) { for (Entity entity : entities.getArray(e)) {
if (CraftEngineFurniture.isFurniture(entity)) { if (CraftEngineFurniture.isFurniture(entity)) {
LoadedFurniture loadedFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity); Furniture bukkitFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity);
if (loadedFurniture != null) { if (bukkitFurniture != null) {
loadedFurniture.destroy(); bukkitFurniture.destroy();
} }
} }
} }

View File

@@ -3,8 +3,11 @@ package net.momirealms.craftengine.bukkit.api;
import net.momirealms.craftengine.bukkit.entity.BukkitEntity; import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld; import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@@ -29,4 +32,8 @@ public final class BukkitAdaptors {
public static BukkitBlockInWorld adapt(final Block block) { public static BukkitBlockInWorld adapt(final Block block) {
return new BukkitBlockInWorld(block); return new BukkitBlockInWorld(block);
} }
public static Location toLocation(WorldPosition position) {
return LocationUtils.toLocation(position);
}
} }

View File

@@ -1,13 +1,14 @@
package net.momirealms.craftengine.bukkit.api; package net.momirealms.craftengine.bukkit.api;
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.bukkit.nms.CollisionEntity; import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.entity.furniture.AnchorType; import net.momirealms.craftengine.core.entity.furniture.AnchorType;
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; 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.FurnitureExtraData;
import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.loot.LootTable;
@@ -48,7 +49,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@Nullable @Nullable
public static LoadedFurniture place(Location location, Key furnitureId) { public static Furniture place(Location location, Key furnitureId) {
CustomFurniture furniture = byId(furnitureId); CustomFurniture furniture = byId(furnitureId);
if (furniture == null) return null; if (furniture == null) return null;
return place(location, furnitureId, furniture.getAnyPlacement()); return place(location, furnitureId, furniture.getAnyPlacement());
@@ -63,7 +64,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@Nullable @Nullable
public static LoadedFurniture place(Location location, Key furnitureId, AnchorType anchorType) { public static Furniture place(Location location, Key furnitureId, AnchorType anchorType) {
CustomFurniture furniture = byId(furnitureId); CustomFurniture furniture = byId(furnitureId);
if (furniture == null) return null; if (furniture == null) return null;
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true);
@@ -78,7 +79,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@NotNull @NotNull
public static LoadedFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType) { public static Furniture place(Location location, CustomFurniture furniture, AnchorType anchorType) {
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true);
} }
@@ -92,7 +93,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@Nullable @Nullable
public static LoadedFurniture place(Location location, Key furnitureId, AnchorType anchorType, boolean playSound) { public static Furniture place(Location location, Key furnitureId, AnchorType anchorType, boolean playSound) {
CustomFurniture furniture = byId(furnitureId); CustomFurniture furniture = byId(furnitureId);
if (furniture == null) return null; if (furniture == null) return null;
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound);
@@ -108,7 +109,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@NotNull @NotNull
public static LoadedFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType, boolean playSound) { public static Furniture place(Location location, CustomFurniture furniture, AnchorType anchorType, boolean playSound) {
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound);
} }
@@ -152,7 +153,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@Nullable @Nullable
public static LoadedFurniture getLoadedFurnitureByBaseEntity(@NotNull Entity baseEntity) { public static Furniture getLoadedFurnitureByBaseEntity(@NotNull Entity baseEntity) {
return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntity.getEntityId()); return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntity.getEntityId());
} }
@@ -163,7 +164,7 @@ public final class CraftEngineFurniture {
* @return the loaded furniture * @return the loaded furniture
*/ */
@Nullable @Nullable
public static LoadedFurniture getLoadedFurnitureBySeat(@NotNull Entity seat) { public static Furniture getLoadedFurnitureBySeat(@NotNull Entity seat) {
Integer baseEntityId = seat.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER); Integer baseEntityId = seat.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
if (baseEntityId == null) return null; if (baseEntityId == null) return null;
return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntityId); return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntityId);
@@ -172,107 +173,108 @@ public final class CraftEngineFurniture {
/** /**
* Removes furniture * Removes furniture
* *
* @param furniture furniture base entity * @param entity furniture base entity
* @return success or not * @return success or not
*/ */
public static boolean remove(@NotNull Entity furniture) { public static boolean remove(@NotNull Entity entity) {
if (!isFurniture(furniture)) return false; if (!isFurniture(entity)) return false;
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId()); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entity.getEntityId());
if (loadedFurniture == null) return false; if (furniture == null) return false;
loadedFurniture.destroy(); furniture.destroy();
return true; return true;
} }
/** /**
* Removes furniture, with more options * Removes furniture, with more options
* *
* @param furniture furniture base entity * @param entity furniture base entity
* @param dropLoot whether to drop loots * @param dropLoot whether to drop loots
* @param playSound whether to play break sound * @param playSound whether to play break sound
* @return success or not * @return success or not
*/ */
public static boolean remove(@NotNull Entity furniture, public static boolean remove(@NotNull Entity entity,
boolean dropLoot, boolean dropLoot,
boolean playSound) { boolean playSound) {
if (!isFurniture(furniture)) return false; if (!isFurniture(entity)) return false;
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId()); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entity.getEntityId());
if (loadedFurniture == null) return false; if (furniture == null) return false;
remove(loadedFurniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound); remove(furniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound);
return true; return true;
} }
/** /**
* Removes furniture, with more options * Removes furniture, with more options
* *
* @param furniture furniture base entity * @param entity furniture base entity
* @param player the player who removes the furniture * @param player the player who removes the furniture
* @param dropLoot whether to drop loots * @param dropLoot whether to drop loots
* @param playSound whether to play break sound * @param playSound whether to play break sound
* @return success or not * @return success or not
*/ */
public static boolean remove(@NotNull Entity furniture, public static boolean remove(@NotNull Entity entity,
@Nullable Player player, @Nullable Player player,
boolean dropLoot, boolean dropLoot,
boolean playSound) { boolean playSound) {
if (!isFurniture(furniture)) return false; if (!isFurniture(entity)) return false;
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId()); Furniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entity.getEntityId());
if (loadedFurniture == null) return false; if (furniture == null) return false;
remove(loadedFurniture, player, dropLoot, playSound); remove(furniture, player, dropLoot, playSound);
return true; return true;
} }
/** /**
* Removes furniture by providing furniture instance * Removes furniture by providing furniture instance
* *
* @param loadedFurniture loaded furniture * @param furniture loaded furniture
* @param dropLoot whether to drop loots * @param dropLoot whether to drop loots
* @param playSound whether to play break sound * @param playSound whether to play break sound
*/ */
public static void remove(@NotNull LoadedFurniture loadedFurniture, public static void remove(@NotNull Furniture furniture,
boolean dropLoot, boolean dropLoot,
boolean playSound) { boolean playSound) {
remove(loadedFurniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound); remove(furniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound);
} }
/** /**
* Removes furniture by providing furniture instance * Removes furniture by providing furniture instance
* *
* @param loadedFurniture loaded furniture * @param furniture loaded furniture
* @param player the player who removes the furniture * @param player the player who removes the furniture
* @param dropLoot whether to drop loots * @param dropLoot whether to drop loots
* @param playSound whether to play break sound * @param playSound whether to play break sound
*/ */
public static void remove(@NotNull LoadedFurniture loadedFurniture, public static void remove(@NotNull Furniture furniture,
@Nullable Player player, @Nullable Player player,
boolean dropLoot, boolean dropLoot,
boolean playSound) { boolean playSound) {
remove(loadedFurniture, player == null ? null : BukkitCraftEngine.instance().adapt(player), dropLoot, playSound); remove(furniture, player == null ? null : BukkitCraftEngine.instance().adapt(player), dropLoot, playSound);
} }
/** /**
* Removes furniture by providing furniture instance * Removes furniture by providing furniture instance
* *
* @param loadedFurniture loaded furniture * @param furniture loaded furniture
* @param player the player who removes the furniture * @param player the player who removes the furniture
* @param dropLoot whether to drop loots * @param dropLoot whether to drop loots
* @param playSound whether to play break sound * @param playSound whether to play break sound
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void remove(@NotNull LoadedFurniture loadedFurniture, public static void remove(@NotNull Furniture furniture,
@Nullable net.momirealms.craftengine.core.entity.player.Player player, @Nullable net.momirealms.craftengine.core.entity.player.Player player,
boolean dropLoot, boolean dropLoot,
boolean playSound) { boolean playSound) {
Location location = loadedFurniture.dropLocation(); if (!furniture.isValid()) return;
loadedFurniture.destroy(); Location location = ((BukkitFurniture) furniture).dropLocation();
LootTable<ItemStack> lootTable = (LootTable<ItemStack>) loadedFurniture.config().lootTable(); furniture.destroy();
LootTable<ItemStack> lootTable = (LootTable<ItemStack>) furniture.config().lootTable();
World world = new BukkitWorld(location.getWorld()); World world = new BukkitWorld(location.getWorld());
WorldPosition position = new WorldPosition(world, location.getX(), location.getY(), location.getZ()); WorldPosition position = new WorldPosition(world, location.getX(), location.getY(), location.getZ());
if (dropLoot && lootTable != null) { if (dropLoot && lootTable != null) {
ContextHolder.Builder builder = ContextHolder.builder() ContextHolder.Builder builder = ContextHolder.builder()
.withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.POSITION, position)
.withParameter(DirectContextParameters.FURNITURE, loadedFurniture) .withParameter(DirectContextParameters.FURNITURE, furniture)
.withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, loadedFurniture.extraData().item().orElse(null)); .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.extraData().item().orElse(null));
if (player != null) { if (player != null) {
builder.withParameter(DirectContextParameters.PLAYER, player); builder.withParameter(DirectContextParameters.PLAYER, player);
} }
@@ -282,7 +284,7 @@ public final class CraftEngineFurniture {
} }
} }
if (playSound) { if (playSound) {
world.playBlockSound(position, loadedFurniture.config().settings().sounds().breakSound()); world.playBlockSound(position, furniture.config().settings().sounds().breakSound());
} }
} }
} }

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.bukkit.api.event; package net.momirealms.craftengine.bukkit.api.event;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
@@ -11,10 +12,10 @@ import org.jetbrains.annotations.NotNull;
public class FurnitureBreakEvent extends PlayerEvent implements Cancellable { public class FurnitureBreakEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private boolean cancelled; private boolean cancelled;
private final LoadedFurniture furniture; private final BukkitFurniture furniture;
public FurnitureBreakEvent(@NotNull Player player, public FurnitureBreakEvent(@NotNull Player player,
@NotNull LoadedFurniture furniture) { @NotNull BukkitFurniture furniture) {
super(player); super(player);
this.furniture = furniture; this.furniture = furniture;
} }
@@ -25,7 +26,7 @@ public class FurnitureBreakEvent extends PlayerEvent implements Cancellable {
} }
@NotNull @NotNull
public LoadedFurniture furniture() { public Furniture furniture() {
return this.furniture; return this.furniture;
} }

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.bukkit.api.event; package net.momirealms.craftengine.bukkit.api.event;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionHand;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -12,12 +13,12 @@ import org.jetbrains.annotations.NotNull;
public class FurnitureInteractEvent extends PlayerEvent implements Cancellable { public class FurnitureInteractEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private boolean cancelled; private boolean cancelled;
private final LoadedFurniture furniture; private final BukkitFurniture furniture;
private final InteractionHand hand; private final InteractionHand hand;
private final Location interactionPoint; private final Location interactionPoint;
public FurnitureInteractEvent(@NotNull Player player, public FurnitureInteractEvent(@NotNull Player player,
@NotNull LoadedFurniture furniture, @NotNull BukkitFurniture furniture,
@NotNull InteractionHand hand, @NotNull InteractionHand hand,
@NotNull Location interactionPoint) { @NotNull Location interactionPoint) {
super(player); super(player);
@@ -42,7 +43,7 @@ public class FurnitureInteractEvent extends PlayerEvent implements Cancellable {
} }
@NotNull @NotNull
public LoadedFurniture furniture() { public Furniture furniture() {
return this.furniture; return this.furniture;
} }

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.bukkit.api.event; package net.momirealms.craftengine.bukkit.api.event;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionHand;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -12,12 +13,12 @@ import org.jetbrains.annotations.NotNull;
public class FurniturePlaceEvent extends PlayerEvent implements Cancellable { public class FurniturePlaceEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private final Location location; private final Location location;
private final LoadedFurniture furniture; private final BukkitFurniture furniture;
private final InteractionHand hand; private final InteractionHand hand;
private boolean cancelled; private boolean cancelled;
public FurniturePlaceEvent(@NotNull Player player, public FurniturePlaceEvent(@NotNull Player player,
@NotNull LoadedFurniture furniture, @NotNull BukkitFurniture furniture,
@NotNull Location location, @NotNull Location location,
@NotNull InteractionHand hand) { @NotNull InteractionHand hand) {
super(player); super(player);
@@ -32,7 +33,7 @@ public class FurniturePlaceEvent extends PlayerEvent implements Cancellable {
} }
@NotNull @NotNull
public LoadedFurniture furniture() { public Furniture furniture() {
return this.furniture; return this.furniture;
} }

View File

@@ -0,0 +1,74 @@
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.PlayerOptionalContext;
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<PlayerOptionalContext>>> 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<PlayerOptionalContext>>> 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<PlayerOptionalContext>>> events) {
this.events = events;
return this;
}
}
}

View File

@@ -1,9 +1,13 @@
package net.momirealms.craftengine.bukkit.entity.furniture; package net.momirealms.craftengine.bukkit.entity.furniture;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.momirealms.craftengine.bukkit.entity.BukkitEntity; import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.EntityUtils;
import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.entity.furniture.*; import net.momirealms.craftengine.core.entity.furniture.*;
@@ -29,7 +33,7 @@ import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.*; import java.util.*;
public class LoadedFurniture implements Furniture { public class BukkitFurniture implements Furniture {
private final Key id; private final Key id;
private final CustomFurniture furniture; private final CustomFurniture furniture;
private final AnchorType anchorType; private final AnchorType anchorType;
@@ -44,8 +48,8 @@ public class LoadedFurniture implements Furniture {
// cache // cache
private final List<Integer> fakeEntityIds; private final List<Integer> fakeEntityIds;
private final List<Integer> entityIds; private final List<Integer> entityIds;
private final Map<Integer, HitBox> hitBoxes = new HashMap<>(); private final Map<Integer, HitBox> hitBoxes = new Int2ObjectArrayMap<>();
private final Map<Integer, AABB> aabb = new HashMap<>(); private final Map<Integer, AABB> aabb = new Int2ObjectArrayMap<>();
private final boolean minimized; private final boolean minimized;
private final boolean hasExternalModel; private final boolean hasExternalModel;
// seats // seats
@@ -55,7 +59,7 @@ public class LoadedFurniture implements Furniture {
private Object cachedSpawnPacket; private Object cachedSpawnPacket;
private Object cachedMinimizedSpawnPacket; private Object cachedMinimizedSpawnPacket;
public LoadedFurniture(Entity baseEntity, public BukkitFurniture(Entity baseEntity,
CustomFurniture furniture, CustomFurniture furniture,
FurnitureExtraData extraData) { FurnitureExtraData extraData) {
this.id = furniture.id(); this.id = furniture.id();
@@ -66,8 +70,8 @@ public class LoadedFurniture implements Furniture {
this.baseEntity = new WeakReference<>(baseEntity); this.baseEntity = new WeakReference<>(baseEntity);
this.furniture = furniture; this.furniture = furniture;
this.minimized = furniture.settings().minimized(); this.minimized = furniture.settings().minimized();
List<Integer> fakeEntityIds = new ArrayList<>(); List<Integer> fakeEntityIds = new IntArrayList();
List<Integer> mainEntityIds = new ArrayList<>(); List<Integer> mainEntityIds = new IntArrayList();
mainEntityIds.add(this.baseEntityId); mainEntityIds.add(this.baseEntityId);
CustomFurniture.Placement placement = furniture.getPlacement(anchorType); CustomFurniture.Placement placement = furniture.getPlacement(anchorType);
@@ -84,19 +88,11 @@ public class LoadedFurniture implements Furniture {
this.hasExternalModel = false; this.hasExternalModel = false;
} }
float yaw = this.location.getYaw(); Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate();
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - yaw), 0).conjugate();
double x = location.getX();
double y = location.getY();
double z = location.getZ();
List<Object> packets = new ArrayList<>(); List<Object> packets = new ArrayList<>();
List<Object> minimizedPackets = new ArrayList<>(); List<Object> minimizedPackets = new ArrayList<>();
List<Collider> colliders = new ArrayList<>(); List<Collider> colliders = new ArrayList<>();
WorldPosition position = position();
World world = world();
WorldPosition position = new WorldPosition(world, x, y, z, yaw, 0);
Integer dyedColor = this.extraData.dyedColor().orElse(null); Integer dyedColor = this.extraData.dyedColor().orElse(null);
for (FurnitureElement element : placement.elements()) { for (FurnitureElement element : placement.elements()) {
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
@@ -154,13 +150,8 @@ public class LoadedFurniture implements Furniture {
} }
@Override @Override
public Vec3d position() { public WorldPosition position() {
return new Vec3d(location.getX(), location.getY(), location.getZ()); return LocationUtils.toWorldPosition(this.location);
}
@Override
public World world() {
return new BukkitWorld(this.location.getWorld());
} }
@NotNull @NotNull
@@ -170,7 +161,7 @@ public class LoadedFurniture implements Furniture {
@NotNull @NotNull
public Entity baseEntity() { public Entity baseEntity() {
Entity entity = baseEntity.get(); Entity entity = this.baseEntity.get();
if (entity == null) { if (entity == null) {
throw new RuntimeException("Base entity not found. It might be unloaded."); throw new RuntimeException("Base entity not found. It might be unloaded.");
} }

View File

@@ -7,6 +7,7 @@ import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.entity.Billboard; import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext; import net.momirealms.craftengine.core.entity.ItemDisplayContext;
import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement; import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement;
import net.momirealms.craftengine.core.entity.furniture.FurnitureElement;
import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
@@ -30,10 +31,10 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement {
ItemDisplayContext transform, ItemDisplayContext transform,
Vector3f scale, Vector3f scale,
Vector3f translation, Vector3f translation,
Vector3f offset, Vector3f position,
Quaternionf rotation, Quaternionf rotation,
boolean applyDyedColor) { boolean applyDyedColor) {
super(item, billboard, transform, scale, translation, offset, rotation, applyDyedColor); super(item, billboard, transform, scale, translation, position, rotation, applyDyedColor);
this.commonValues = new ArrayList<>(); this.commonValues = new ArrayList<>();
ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.commonValues); ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.commonValues);
ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.commonValues); ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.commonValues);
@@ -67,4 +68,72 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement {
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), cachedValues); ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), cachedValues);
return 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;
@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 FurnitureElement build() {
return new BukkitFurnitureElement(item, billboard, transform, scale, translation, position, rotation, applyDyedColor);
}
}
} }

View File

@@ -6,58 +6,45 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler; import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler;
import net.momirealms.craftengine.bukkit.util.EntityUtils; 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.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
import net.momirealms.craftengine.core.entity.furniture.*; import net.momirealms.craftengine.core.entity.furniture.*;
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.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
import net.momirealms.craftengine.core.plugin.context.function.Function;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.WorldPosition;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.entity.*; import org.bukkit.entity.*;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.joml.Vector3f; import org.joml.Vector3f;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.util.Collection;
import java.util.*; import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class BukkitFurnitureManager extends AbstractFurnitureManager { public class BukkitFurnitureManager extends AbstractFurnitureManager {
public static final NamespacedKey FURNITURE_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_id")); public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY);
// DEPRECATED public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_EXTRA_DATA_KEY);
// public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type")); public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY);
public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_extra_data")); public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY);
public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity")); public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION);
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_vector"));
public static final NamespacedKey FURNITURE_COLLISION = Objects.requireNonNull(NamespacedKey.fromString("craftengine:collision"));
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class; public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
public static Object NMS_COLLISION_ENTITY_TYPE = Reflections.instance$EntityType$INTERACTION; public static Object NMS_COLLISION_ENTITY_TYPE = Reflections.instance$EntityType$INTERACTION;
public static ColliderType COLLISION_ENTITY_TYPE = ColliderType.INTERACTION; public static ColliderType COLLISION_ENTITY_TYPE = ColliderType.INTERACTION;
private static BukkitFurnitureManager instance; private static BukkitFurnitureManager instance;
private final BukkitCraftEngine plugin; private final BukkitCraftEngine plugin;
private final FurnitureParser furnitureParser; private final Map<Integer, BukkitFurniture> furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f);
private final Map<Integer, LoadedFurniture> furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f); private final Map<Integer, BukkitFurniture> furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f);
private final Map<Integer, LoadedFurniture> furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f);
// Event listeners // Event listeners
private final Listener dismountListener; private final Listener dismountListener;
private final FurnitureEventListener furnitureEventListener; private final FurnitureEventListener furnitureEventListener;
@@ -67,9 +54,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
} }
public BukkitFurnitureManager(BukkitCraftEngine plugin) { public BukkitFurnitureManager(BukkitCraftEngine plugin) {
super(plugin);
instance = this; instance = this;
this.plugin = plugin; this.plugin = plugin;
this.furnitureParser = new FurnitureParser();
this.furnitureEventListener = new FurnitureEventListener(this); this.furnitureEventListener = new FurnitureEventListener(this);
this.dismountListener = VersionHelper.isOrAbove1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount); this.dismountListener = VersionHelper.isOrAbove1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount);
} }
@@ -79,7 +66,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
return this.place(LocationUtils.toLocation(position), furniture, extraData, playSound); return this.place(LocationUtils.toLocation(position), furniture, extraData, playSound);
} }
public LoadedFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { public BukkitFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
Optional<AnchorType> optionalAnchorType = extraData.anchorType(); Optional<AnchorType> optionalAnchorType = extraData.anchorType();
if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) { if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) {
extraData.anchorType(furniture.getAnyPlacement()); extraData.anchorType(furniture.getAnyPlacement());
@@ -101,128 +88,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId()); return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId());
} }
@Override
public ConfigParser parser() {
return this.furnitureParser;
}
public class FurnitureParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] { "furniture" };
@Override
public String[] sectionId() {
return CONFIG_SECTION_NAME;
}
@Override
public int loadingSequence() {
return LoadingSequence.FURNITURE;
}
@SuppressWarnings("unchecked")
@Override
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
if (byId.containsKey(id)) {
throw new LocalizedResourceConfigException("warning.config.furniture.duplicate", path, id);
}
Map<String, Object> lootMap = MiscUtils.castToMap(section.get("loot"), true);
Map<String, Object> settingsMap = MiscUtils.castToMap(section.get("settings"), true);
Map<String, Object> placementMap = MiscUtils.castToMap(section.get("placement"), true);
if (placementMap == null) {
throw new LocalizedResourceConfigException("warning.config.furniture.missing_placement", path, id);
}
EnumMap<AnchorType, CustomFurniture.Placement> placements = new EnumMap<>(AnchorType.class);
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(), true);
Optional<Vector3f> optionalLootSpawnOffset = Optional.ofNullable(placementArguments.get("loot-spawn-offset")).map(it -> MiscUtils.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) {
String key = (String) element.get("item");
if (key == null) {
throw new LocalizedResourceConfigException("warning.config.furniture.element.missing_item", path, id);
}
ItemDisplayContext transform = ItemDisplayContext.valueOf(element.getOrDefault("transform", "NONE").toString().toUpperCase(Locale.ENGLISH));
Billboard billboard = Billboard.valueOf(element.getOrDefault("billboard", "FIXED").toString().toUpperCase(Locale.ENGLISH));
FurnitureElement furnitureElement = new BukkitFurnitureElement(Key.of(key), billboard, transform,
MiscUtils.getAsVector3f(element.getOrDefault("scale", "1"), "scale"),
MiscUtils.getAsVector3f(element.getOrDefault("translation", "0"), "translation"),
MiscUtils.getAsVector3f(element.getOrDefault("position", "0"), "position"),
MiscUtils.getAsQuaternionf(element.getOrDefault("rotation", "0"), "rotation"),
(boolean) element.getOrDefault("apply-dyed-color", true)
);
elements.add(furnitureElement);
}
// external model providers
Optional<ExternalModel> externalModel;
if (placementArguments.containsKey("model-engine")) {
externalModel = Optional.of(plugin.compatibilityManager().createModelEngineModel(placementArguments.get("model-engine").toString()));
} else if (placementArguments.containsKey("better-model")) {
externalModel = Optional.of(plugin.compatibilityManager().createBetterModelModel(placementArguments.get("better-model").toString()));
} else {
externalModel = Optional.empty();
}
// add hitboxes
List<Map<String, Object>> hitboxConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("hitboxes", List.of());
List<HitBox> hitboxes = new ArrayList<>();
for (Map<String, Object> config : hitboxConfigs) {
HitBox hitBox = HitBoxTypes.fromMap(config);
hitboxes.add(hitBox);
}
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
hitboxes.add(InteractionHitBox.DEFAULT);
}
// rules
Map<String, Object> ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true);
if (ruleSection != null) {
RotationRule rotationRule = Optional.ofNullable((String) ruleSection.get("rotation"))
.map(it -> RotationRule.valueOf(it.toUpperCase(Locale.ENGLISH)))
.orElse(RotationRule.ANY);
AlignmentRule alignmentRule = Optional.ofNullable((String) ruleSection.get("alignment"))
.map(it -> AlignmentRule.valueOf(it.toUpperCase(Locale.ENGLISH)))
.orElse(AlignmentRule.CENTER);
placements.put(anchorType, new CustomFurniture.Placement(
elements.toArray(new FurnitureElement[0]),
hitboxes.toArray(new HitBox[0]),
rotationRule,
alignmentRule,
externalModel,
optionalLootSpawnOffset
));
} else {
placements.put(anchorType, new CustomFurniture.Placement(
elements.toArray(new FurnitureElement[0]),
hitboxes.toArray(new HitBox[0]),
RotationRule.ANY,
AlignmentRule.CENTER,
externalModel,
optionalLootSpawnOffset
));
}
}
// get furniture settings
FurnitureSettings settings = FurnitureSettings.fromMap(settingsMap);
// get loot table
LootTable<ItemStack> lootTable = lootMap == null ? null : LootTable.fromMap(lootMap);
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events = EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event"));
CustomFurniture furniture = new CustomFurniture(id, settings, placements, events, lootTable);
byId.put(id, furniture);
}
}
@Override @Override
public void delayedInit() { public void delayedInit() {
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class; COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
@@ -264,19 +129,29 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
@Nullable @Nullable
@Override @Override
public LoadedFurniture loadedFurnitureByRealEntityId(int entityId) { public BukkitFurniture loadedFurnitureByRealEntityId(int entityId) {
return this.furnitureByRealEntityId.get(entityId); return this.furnitureByRealEntityId.get(entityId);
} }
@Override @Override
@Nullable @Nullable
public LoadedFurniture loadedFurnitureByEntityId(int entityId) { public BukkitFurniture loadedFurnitureByEntityId(int entityId) {
return this.furnitureByEntityId.get(entityId); 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) { protected void handleBaseEntityUnload(Entity entity) {
int id = entity.getEntityId(); int id = entity.getEntityId();
LoadedFurniture furniture = this.furnitureByRealEntityId.remove(id); BukkitFurniture furniture = this.furnitureByRealEntityId.remove(id);
if (furniture != null) { if (furniture != null) {
Location location = entity.getLocation(); Location location = entity.getLocation();
boolean isPreventing = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); boolean isPreventing = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
@@ -305,7 +180,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
if (optionalFurniture.isEmpty()) return; if (optionalFurniture.isEmpty()) return;
CustomFurniture customFurniture = optionalFurniture.get(); CustomFurniture customFurniture = optionalFurniture.get();
LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
if (previous != null) return; if (previous != null) return;
Location location = display.getLocation(); Location location = display.getLocation();
@@ -313,7 +188,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
boolean preventChange = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); boolean preventChange = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
if (above1_20_1) { if (above1_20_1) {
if (!preventChange) { if (!preventChange) {
LoadedFurniture furniture = addNewFurniture(display, customFurniture); BukkitFurniture furniture = addNewFurniture(display, customFurniture);
furniture.initializeColliders(); furniture.initializeColliders();
for (Player player : display.getTrackedPlayers()) { for (Player player : display.getTrackedPlayers()) {
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
@@ -321,7 +196,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
} }
} }
} else { } else {
LoadedFurniture furniture = addNewFurniture(display, customFurniture); BukkitFurniture furniture = addNewFurniture(display, customFurniture);
for (Player player : display.getTrackedPlayers()) { for (Player player : display.getTrackedPlayers()) {
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player)); this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player));
@@ -383,9 +258,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
Optional<CustomFurniture> optionalFurniture = furnitureById(key); Optional<CustomFurniture> optionalFurniture = furnitureById(key);
if (optionalFurniture.isPresent()) { if (optionalFurniture.isPresent()) {
CustomFurniture customFurniture = optionalFurniture.get(); CustomFurniture customFurniture = optionalFurniture.get();
LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
if (previous != null) return; if (previous != null) return;
LoadedFurniture furniture = addNewFurniture(display, customFurniture); BukkitFurniture furniture = addNewFurniture(display, customFurniture);
furniture.initializeColliders(); // safely do it here furniture.initializeColliders(); // safely do it here
} }
} }
@@ -412,23 +287,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
return FurnitureExtraData.fromBytes(extraData); return FurnitureExtraData.fromBytes(extraData);
} }
// private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) { private synchronized BukkitFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture) {
// String anchorType = baseEntity.getPersistentDataContainer().get(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING);
// if (anchorType != null) {
// try {
// AnchorType unverified = AnchorType.valueOf(anchorType);
// if (furniture.isAllowedPlacement(unverified)) {
// return unverified;
// }
// } catch (IllegalArgumentException ignored) {
// }
// }
// AnchorType anchorTypeEnum = furniture.getAnyPlacement();
// baseEntity.getPersistentDataContainer().set(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, anchorTypeEnum.name());
// return anchorTypeEnum;
// }
private synchronized LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture) {
FurnitureExtraData extraData; FurnitureExtraData extraData;
try { try {
extraData = getFurnitureExtraData(display); extraData = getFurnitureExtraData(display);
@@ -436,16 +295,21 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
extraData = FurnitureExtraData.builder().build(); extraData = FurnitureExtraData.builder().build();
plugin.logger().warn("Furniture extra data could not be loaded", e); plugin.logger().warn("Furniture extra data could not be loaded", e);
} }
LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, extraData); BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, extraData);
this.furnitureByRealEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture); this.furnitureByRealEntityId.put(bukkitFurniture.baseEntityId(), bukkitFurniture);
for (int entityId : loadedFurniture.entityIds()) { for (int entityId : bukkitFurniture.entityIds()) {
this.furnitureByEntityId.put(entityId, loadedFurniture); this.furnitureByEntityId.put(entityId, bukkitFurniture);
} }
for (Collider collisionEntity : loadedFurniture.collisionEntities()) { for (Collider collisionEntity : bukkitFurniture.collisionEntities()) {
int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle()); int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle());
this.furnitureByRealEntityId.put(collisionEntityId, loadedFurniture); this.furnitureByRealEntityId.put(collisionEntityId, bukkitFurniture);
} }
return loadedFurniture; return bukkitFurniture;
}
@Override
protected HitBox defaultHitBox() {
return InteractionHitBox.DEFAULT;
} }
protected void handleDismount(Player player, Entity entity) { protected void handleDismount(Player player, Entity entity) {
@@ -458,7 +322,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER); Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
if (baseFurniture == null) return; if (baseFurniture == null) return;
vehicle.remove(); vehicle.remove();
LoadedFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture); BukkitFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture);
if (furniture == null) { if (furniture == null) {
return; return;
} }

View File

@@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.item.behavior;
import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptPlaceEvent; import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptPlaceEvent;
import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent; import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent;
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.util.DirectionUtils; import net.momirealms.craftengine.bukkit.util.DirectionUtils;
@@ -134,7 +134,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
Item<?> item = context.getItem(); Item<?> item = context.getItem();
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().place( BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place(
furnitureLocation.clone(), customFurniture, furnitureLocation.clone(), customFurniture,
FurnitureExtraData.builder() FurnitureExtraData.builder()
.item(item.copyWithCount(1)) .item(item.copyWithCount(1))
@@ -142,15 +142,15 @@ public class FurnitureItemBehavior extends ItemBehavior {
.dyedColor(item.dyedColor().orElse(null)) .dyedColor(item.dyedColor().orElse(null))
.build(), false); .build(), false);
FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, loadedFurniture, furnitureLocation, context.getHand()); FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand());
if (EventUtils.fireAndCheckCancel(placeEvent)) { if (EventUtils.fireAndCheckCancel(placeEvent)) {
loadedFurniture.destroy(); bukkitFurniture.destroy();
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
Cancellable dummy = Cancellable.dummy(); Cancellable dummy = Cancellable.dummy();
PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder() PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder()
.withParameter(DirectContextParameters.FURNITURE, loadedFurniture) .withParameter(DirectContextParameters.FURNITURE, bukkitFurniture)
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation)) .withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation))
.withParameter(DirectContextParameters.EVENT, dummy) .withParameter(DirectContextParameters.EVENT, dummy)
.withParameter(DirectContextParameters.HAND, context.getHand()) .withParameter(DirectContextParameters.HAND, context.getHand())

View File

@@ -121,7 +121,14 @@ public class ItemEventListener implements Listener {
// interact block with items // interact block with items
if (hasItem && action == Action.RIGHT_CLICK_BLOCK) { if (hasItem && action == Action.RIGHT_CLICK_BLOCK) {
Location interactionPoint = Objects.requireNonNull(event.getInteractionPoint(), "interaction point should not be null"); Location interactionPoint = event.getInteractionPoint();
// some plugins would trigger this event without interaction point
if (interactionPoint == null) {
if (hasCustomItem) {
event.setCancelled(true);
}
return;
}
Direction direction = DirectionUtils.toDirection(event.getBlockFace()); Direction direction = DirectionUtils.toDirection(event.getBlockFace());
BlockPos pos = LocationUtils.toBlockPos(block.getLocation()); BlockPos pos = LocationUtils.toBlockPos(block.getLocation());
Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ()); Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ());

View File

@@ -11,7 +11,7 @@ import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent; import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture;
import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager; import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager;
import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior; import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior;
import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.nms.FastNMS;
@@ -1489,7 +1489,7 @@ public class PacketConsumers {
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> {
try { try {
int entityId = (int) Reflections.field$ServerboundPickItemFromEntityPacket$id.get(packet); int entityId = (int) Reflections.field$ServerboundPickItemFromEntityPacket$id.get(packet);
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
if (furniture == null) return; if (furniture == null) return;
Player player = (Player) user.platformPlayer(); Player player = (Player) user.platformPlayer();
if (player == null) return; if (player == null) return;
@@ -1518,7 +1518,7 @@ public class PacketConsumers {
} }
}; };
private static void handlePickItemFromEntityOnMainThread(Player player, LoadedFurniture furniture) throws Exception { private static void handlePickItemFromEntityOnMainThread(Player player, BukkitFurniture furniture) throws Exception {
Key itemId = furniture.config().settings().itemId(); Key itemId = furniture.config().settings().itemId();
if (itemId == null) return; if (itemId == null) return;
pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity())); pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity()));
@@ -1596,7 +1596,7 @@ public class PacketConsumers {
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
if (entityType == Reflections.instance$EntityType$ITEM_DISPLAY) { if (entityType == Reflections.instance$EntityType$ITEM_DISPLAY) {
// Furniture // Furniture
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
if (furniture != null) { if (furniture != null) {
user.entityPacketHandlers().computeIfAbsent(entityId, k -> new FurniturePacketHandler(furniture.fakeEntityIds())); user.entityPacketHandlers().computeIfAbsent(entityId, k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
user.sendPacket(furniture.spawnPacket((Player) user.platformPlayer()), false); user.sendPacket(furniture.spawnPacket((Player) user.platformPlayer()), false);
@@ -1606,7 +1606,7 @@ public class PacketConsumers {
} }
} else if (entityType == BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE) { } else if (entityType == BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE) {
// Cancel collider entity packet // Cancel collider entity packet
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
if (furniture != null) { if (furniture != null) {
event.setCancelled(true); event.setCancelled(true);
user.entityPacketHandlers().put(entityId, FurnitureCollisionPacketHandler.INSTANCE); user.entityPacketHandlers().put(entityId, FurnitureCollisionPacketHandler.INSTANCE);
@@ -1670,7 +1670,7 @@ public class PacketConsumers {
} else { } else {
entityId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet); entityId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
} }
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
if (furniture == null) return; if (furniture == null) return;
Object action = Reflections.field$ServerboundInteractPacket$action.get(packet); Object action = Reflections.field$ServerboundInteractPacket$action.get(packet);
Object actionType = Reflections.method$ServerboundInteractPacket$Action$getType.invoke(action); Object actionType = Reflections.method$ServerboundInteractPacket$Action$getType.invoke(action);
@@ -1694,7 +1694,7 @@ public class PacketConsumers {
// execute functions // execute functions
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
.withParameter(DirectContextParameters.FURNITURE, furniture) .withParameter(DirectContextParameters.FURNITURE, furniture)
.withParameter(DirectContextParameters.POSITION, new WorldPosition(furniture.world(), furniture.position())) .withParameter(DirectContextParameters.POSITION, furniture.position())
); );
furniture.config().execute(context, EventTrigger.LEFT_CLICK); furniture.config().execute(context, EventTrigger.LEFT_CLICK);
furniture.config().execute(context, EventTrigger.BREAK); furniture.config().execute(context, EventTrigger.BREAK);
@@ -1724,7 +1724,7 @@ public class PacketConsumers {
// execute functions // execute functions
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
.withParameter(DirectContextParameters.FURNITURE, furniture) .withParameter(DirectContextParameters.FURNITURE, furniture)
.withParameter(DirectContextParameters.POSITION, new WorldPosition(furniture.world(), furniture.position())) .withParameter(DirectContextParameters.POSITION, furniture.position())
); );
furniture.config().execute(context, EventTrigger.RIGHT_CLICK);; furniture.config().execute(context, EventTrigger.RIGHT_CLICK);;

View File

@@ -0,0 +1,80 @@
package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
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<PlayerOptionalContext>>> 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<PlayerOptionalContext>>> 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(PlayerOptionalContext context, EventTrigger trigger) {
for (Function<PlayerOptionalContext> 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 getAnyPlacement() {
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);
}
}

View File

@@ -12,7 +12,7 @@ public abstract class AbstractFurnitureElement implements FurnitureElement {
private final ItemDisplayContext transform; private final ItemDisplayContext transform;
private final Vector3f scale; private final Vector3f scale;
private final Vector3f translation; private final Vector3f translation;
private final Vector3f offset; private final Vector3f position;
private final Quaternionf rotation; private final Quaternionf rotation;
private final boolean applyDyedColor; private final boolean applyDyedColor;
@@ -21,7 +21,7 @@ public abstract class AbstractFurnitureElement implements FurnitureElement {
ItemDisplayContext transform, ItemDisplayContext transform,
Vector3f scale, Vector3f scale,
Vector3f translation, Vector3f translation,
Vector3f offset, Vector3f position,
Quaternionf rotation, Quaternionf rotation,
boolean applyDyedColor) { boolean applyDyedColor) {
this.billboard = billboard; this.billboard = billboard;
@@ -30,7 +30,7 @@ public abstract class AbstractFurnitureElement implements FurnitureElement {
this.translation = translation; this.translation = translation;
this.item = item; this.item = item;
this.rotation = rotation; this.rotation = rotation;
this.offset = offset; this.position = position;
this.applyDyedColor = applyDyedColor; this.applyDyedColor = applyDyedColor;
} }
@@ -71,6 +71,6 @@ public abstract class AbstractFurnitureElement implements FurnitureElement {
@Override @Override
public Vector3f position() { public Vector3f position() {
return offset; return position;
} }
} }

View File

@@ -1,15 +1,40 @@
package net.momirealms.craftengine.core.entity.furniture; 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.loot.LootTable;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.Suggestion;
import org.joml.Vector3f;
import java.nio.file.Path;
import java.util.*; import java.util.*;
public abstract class AbstractFurnitureManager implements FurnitureManager { public abstract class AbstractFurnitureManager implements FurnitureManager {
protected final Map<Key, CustomFurniture> byId = new HashMap<>(); protected final Map<Key, CustomFurniture> byId = new HashMap<>();
private final CraftEngine plugin;
private final FurnitureParser furnitureParser;
// Cached command suggestions // Cached command suggestions
private final List<Suggestion> cachedSuggestions = new ArrayList<>(); private final List<Suggestion> cachedSuggestions = new ArrayList<>();
public AbstractFurnitureManager(CraftEngine plugin) {
this.plugin = plugin;
this.furnitureParser = new FurnitureParser();
}
@Override
public ConfigParser parser() {
return this.furnitureParser;
}
@Override @Override
public void delayedLoad() { public void delayedLoad() {
this.initSuggestions(); this.initSuggestions();
@@ -37,4 +62,104 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
public void unload() { public void unload() {
this.byId.clear(); this.byId.clear();
} }
protected abstract HitBox defaultHitBox();
protected abstract FurnitureElement.Builder furnitureElementBuilder();
protected abstract CustomFurniture.Builder furnitureBuilder();
public class FurnitureParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] { "furniture" };
@Override
public String[] sectionId() {
return CONFIG_SECTION_NAME;
}
@Override
public int loadingSequence() {
return LoadingSequence.FURNITURE;
}
@SuppressWarnings("unchecked")
@Override
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
if (byId.containsKey(id)) {
throw new LocalizedResourceConfigException("warning.config.furniture.duplicate", path, id);
}
EnumMap<AnchorType, CustomFurniture.Placement> placements = new EnumMap<>(AnchorType.class);
Map<String, Object> placementMap = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(section.get("placement"), "warning.config.furniture.missing_placement"), false);
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 -> MiscUtils.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((boolean) element.getOrDefault("apply-dyed-color", true))
.billboard(ResourceConfigUtils.getOrDefault(element.get("billboard"), o -> Billboard.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), Billboard.FIXED))
.transform(ResourceConfigUtils.getOrDefault(element.get("transform"), o -> ItemDisplayContext.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), ItemDisplayContext.NONE))
.scale(MiscUtils.getAsVector3f(element.getOrDefault("scale", "1"), "scale"))
.position(MiscUtils.getAsVector3f(element.getOrDefault("position", "0"), "position"))
.translation(MiscUtils.getAsVector3f(element.getOrDefault("translation", "0"), "translation"))
.rotation(MiscUtils.getAsQuaternionf(element.getOrDefault("rotation", "0"), "rotation"))
.build();
elements.add(furnitureElement);
}
// external model providers
Optional<ExternalModel> externalModel;
if (placementArguments.containsKey("model-engine")) {
externalModel = Optional.of(plugin.compatibilityManager().createModelEngineModel(placementArguments.get("model-engine").toString()));
} else if (placementArguments.containsKey("better-model")) {
externalModel = Optional.of(plugin.compatibilityManager().createBetterModelModel(placementArguments.get("better-model").toString()));
} else {
externalModel = Optional.empty();
}
// add hitboxes
List<HitBox> hitboxes = ResourceConfigUtils.parseConfigAsList(placementArguments.get("hitboxes"), HitBoxTypes::fromMap);
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
hitboxes.add(defaultHitBox());
}
// rules
Map<String, Object> ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true);
if (ruleSection != null) {
placements.put(anchorType, new CustomFurniture.Placement(
elements.toArray(new FurnitureElement[0]),
hitboxes.toArray(new HitBox[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(
elements.toArray(new FurnitureElement[0]),
hitboxes.toArray(new HitBox[0]),
RotationRule.ANY,
AlignmentRule.CENTER,
externalModel,
optionalLootSpawnOffset
));
}
}
CustomFurniture furniture = furnitureBuilder()
.id(id)
.settings(FurnitureSettings.fromMap(MiscUtils.castToMap(section.get("settings"), true)))
.placement(placements)
.events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")))
.lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true)))
.build();
AbstractFurnitureManager.this.byId.put(id, furniture);
}
}
} }

View File

@@ -5,74 +5,53 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
import net.momirealms.craftengine.core.plugin.context.function.Function; import net.momirealms.craftengine.core.plugin.context.function.Function;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f; import org.joml.Vector3f;
import java.util.*; import java.util.List;
import java.util.Map;
import java.util.Optional;
public class CustomFurniture { // TODO 家具的设计存在问题。家具也应该存在不同的状态,而不是根据放置规则直接决定状态类型
private final Key id; public interface CustomFurniture {
private final FurnitureSettings settings;
private final EnumMap<AnchorType, Placement> placements;
private final AnchorType anyType;
private final Map<EventTrigger, List<Function<PlayerOptionalContext>>> events;
@Nullable
private final LootTable<?> lootTable;
public CustomFurniture(@NotNull Key id, void execute(PlayerOptionalContext context, EventTrigger trigger);
@NotNull FurnitureSettings settings,
@NotNull EnumMap<AnchorType, Placement> placements,
@NotNull Map<EventTrigger, List<Function<PlayerOptionalContext>>> 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);
}
public void execute(PlayerOptionalContext context, EventTrigger trigger) { Key id();
for (Function<PlayerOptionalContext> function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) {
function.run(context);
}
}
public Key id() { Map<AnchorType, Placement> placements();
return id;
}
public EnumMap<AnchorType, Placement> placements() { FurnitureSettings settings();
return placements;
}
public FurnitureSettings settings() {
return settings;
}
@Nullable @Nullable
public LootTable<?> lootTable() { LootTable<?> lootTable();
return lootTable;
AnchorType getAnyPlacement();
boolean isAllowedPlacement(AnchorType anchorType);
Placement getPlacement(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<PlayerOptionalContext>>> events);
CustomFurniture build();
} }
public AnchorType getAnyPlacement() { record Placement(FurnitureElement[] elements,
return this.anyType; HitBox[] hitBoxes,
} RotationRule rotationRule,
AlignmentRule alignmentRule,
public boolean isAllowedPlacement(AnchorType anchorType) { Optional<ExternalModel> externalModel,
return placements.containsKey(anchorType); Optional<Vector3f> dropOffset) {
}
public Placement getPlacement(AnchorType anchorType) {
return placements.get(anchorType);
}
public record Placement(FurnitureElement[] elements,
HitBox[] hitBoxes,
RotationRule rotationRule,
AlignmentRule alignmentRule,
Optional<ExternalModel> externalModel,
Optional<Vector3f> dropOffset) {
} }
} }

View File

@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.joml.Vector3f; import org.joml.Vector3f;
@@ -13,9 +14,7 @@ import java.util.UUID;
public interface Furniture { public interface Furniture {
void initializeColliders(); void initializeColliders();
Vec3d position(); WorldPosition position();
World world();
boolean isValid(); boolean isValid();

View File

@@ -29,4 +29,25 @@ public interface FurnitureElement {
Vector3f position(); Vector3f position();
void initPackets(int entityId, @NotNull WorldPosition position, @NotNull Quaternionf conjugated, @Nullable Integer dyedColor, Consumer<Object> packets); void initPackets(int entityId, @NotNull WorldPosition position, @NotNull Quaternionf conjugated, @Nullable Integer dyedColor, 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);
FurnitureElement build();
}
} }

View File

@@ -12,6 +12,12 @@ import java.util.Collection;
import java.util.Optional; import java.util.Optional;
public interface FurnitureManager extends Manageable { public interface FurnitureManager extends Manageable {
Key FURNITURE_KEY = Key.of("craftengine:furniture_id");
Key FURNITURE_EXTRA_DATA_KEY = Key.of("craftengine:furniture_extra_data");
Key FURNITURE_SEAT_BASE_ENTITY_KEY = Key.of("craftengine:seat_to_base_entity");
Key FURNITURE_SEAT_VECTOR_3F_KEY = Key.of("craftengine:seat_vector");
Key FURNITURE_COLLISION = Key.of("craftengine:collision");
String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin"; String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin";
ConfigParser parser(); ConfigParser parser();

View File

@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.util;
import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Either;
import net.momirealms.craftengine.core.plugin.locale.LocalizedException; import net.momirealms.craftengine.core.plugin.locale.LocalizedException;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -15,6 +16,10 @@ public final class ResourceConfigUtils {
private ResourceConfigUtils() {} private ResourceConfigUtils() {}
public static <T, O> T getOrDefault(@Nullable O raw, Function<O, T> function, T defaultValue) {
return raw != null ? function.apply(raw) : defaultValue;
}
public static <T> T requireNonNullOrThrow(T obj, String node) { public static <T> T requireNonNullOrThrow(T obj, String node) {
if (obj == null) if (obj == null)
throw new LocalizedResourceConfigException(node); throw new LocalizedResourceConfigException(node);

View File

@@ -71,9 +71,9 @@ modmenu_version=13.0.3
cloth_version=17.0.144 cloth_version=17.0.144
# Proxy settings # Proxy settings
#systemProp.socks.proxyHost=127.0.0.1 systemProp.socks.proxyHost=127.0.0.1
#systemProp.socks.proxyPort=7890 systemProp.socks.proxyPort=7890
#systemProp.http.proxyHost=127.0.0.1 systemProp.http.proxyHost=127.0.0.1
#systemProp.http.proxyPort=7890 systemProp.http.proxyPort=7890
#systemProp.https.proxyHost=127.0.0.1 systemProp.https.proxyHost=127.0.0.1
#systemProp.https.proxyPort=7890 systemProp.https.proxyPort=7890

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
networkTimeout=10000 networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -1,7 +1,7 @@
plugins { plugins {
id("java-library") id("java-library")
id("com.gradleup.shadow") version "9.0.0-beta13" id("com.gradleup.shadow") version "9.0.0-beta13"
id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" id("io.papermc.paperweight.userdev") version "2.0.0-beta.17"
} }
repositories { repositories {

View File

@@ -1,7 +1,7 @@
plugins { plugins {
id("java-library") id("java-library")
id("com.gradleup.shadow") version "9.0.0-beta13" id("com.gradleup.shadow") version "9.0.0-beta13"
id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" id("io.papermc.paperweight.userdev") version "2.0.0-beta.17"
} }
repositories { repositories {

View File

@@ -1,7 +1,7 @@
plugins { plugins {
id("java-library") id("java-library")
id("com.gradleup.shadow") version "9.0.0-beta13" id("com.gradleup.shadow") version "9.0.0-beta13"
id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" id("io.papermc.paperweight.userdev") version "2.0.0-beta.17"
} }
repositories { repositories {