From 15f1f00356fc06a7cfd4ab41f01f315c6e7cf742 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 26 Mar 2025 17:12:04 +0800 Subject: [PATCH] add new furniture place command --- bukkit/loader/src/main/resources/commands.yml | 7 ++ .../bukkit/api/CraftEngineFurniture.java | 14 ++++ .../furniture/BukkitFurnitureManager.java | 27 +++++++- .../plugin/command/BukkitCommandManager.java | 1 + .../feature/DebugSpawnFurnitureCommand.java | 67 +++++++++++++++++++ .../plugin/injector/BukkitInjector.java | 10 --- .../bukkit/util/OptimizedReflections.java | 6 ++ .../entity/furniture/FurnitureManager.java | 8 +++ .../craftengine/core/plugin/CraftEngine.java | 1 + .../core/util/ReflectionUtils.java | 21 ++++++ gradle.properties | 2 +- 11 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/OptimizedReflections.java diff --git a/bukkit/loader/src/main/resources/commands.yml b/bukkit/loader/src/main/resources/commands.yml index 58f61982f..1e4acc716 100644 --- a/bukkit/loader/src/main/resources/commands.yml +++ b/bukkit/loader/src/main/resources/commands.yml @@ -77,6 +77,13 @@ debug_set_block: - /craftengine debug setblock - /ce debug setblock +debug_spawn_furniture: + enable: true + permission: ce.command.debug.spawn_furniture + usage: + - /craftengine debug spawn-furniture + - /ce debug spawn-furniture + debug_get_block_state_registry_id: enable: true permission: ce.command.debug.get_block_state_registry_id diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java index ddef57af8..10c928c92 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java @@ -37,6 +37,20 @@ public class CraftEngineFurniture { return BukkitFurnitureManager.instance().getFurniture(id).orElse(null); } + /** + * Places furniture at the certain location + * + * @param location location + * @param furnitureId furniture to place + * @return the loaded furniture + */ + @Nullable + public static LoadedFurniture place(Location location, Key furnitureId) { + CustomFurniture furniture = byId(furnitureId); + if (furniture == null) return null; + return place(location, furnitureId, furniture.getAnyPlacement()); + } + /** * Places furniture at the certain location * diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index 7614ca1f9..96129b367 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -16,6 +16,7 @@ import org.bukkit.entity.*; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.persistence.PersistentDataType; +import org.incendo.cloud.suggestion.Suggestion; import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; @@ -41,6 +42,8 @@ public class BukkitFurnitureManager implements FurnitureManager { private final FurnitureEventListener furnitureEventListener; // tick task private SchedulerTask tickTask; + // Cached command suggestions + private final List cachedSuggestions = new ArrayList<>(); public static BukkitFurnitureManager instance() { return instance; @@ -54,10 +57,14 @@ public class BukkitFurnitureManager implements FurnitureManager { } public LoadedFurniture place(CustomFurniture furniture, Location location, AnchorType anchorType, boolean playSound) { + if (furniture.isAllowedPlacement(anchorType)) { + anchorType = furniture.getAnyPlacement(); + } + AnchorType finalAnchorType = anchorType; 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()); - display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, anchorType.name()); + display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, finalAnchorType.name()); handleEntityLoadEarly(display); }); if (playSound) { @@ -67,6 +74,24 @@ public class BukkitFurnitureManager implements FurnitureManager { return getLoadedFurnitureByBaseEntityId(furnitureEntity.getEntityId()); } + @Override + public void delayedLoad() { + this.initSuggestions(); + } + + @Override + public void initSuggestions() { + this.cachedSuggestions.clear(); + for (Key key : this.byId.keySet()) { + this.cachedSuggestions.add(Suggestion.suggestion(key.toString())); + } + } + + @Override + public Collection cachedSuggestions() { + return Collections.unmodifiableCollection(this.cachedSuggestions); + } + @SuppressWarnings("unchecked") @Override public void parseSection(Pack pack, Path path, Key id, Map section) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitCommandManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitCommandManager.java index 1c859475f..ec38a6f81 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitCommandManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitCommandManager.java @@ -44,6 +44,7 @@ public class BukkitCommandManager extends AbstractCommandManager new DebugRealStateUsageCommand(this, plugin), new DebugItemDataCommand(this, plugin), new DebugSetBlockCommand(this, plugin), + new DebugSpawnFurnitureCommand(this, plugin), new DebugTargetBlockCommand(this, plugin) )); final LegacyPaperCommandManager manager = (LegacyPaperCommandManager) getCommandManager(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java new file mode 100644 index 000000000..612688718 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java @@ -0,0 +1,67 @@ +package net.momirealms.craftengine.bukkit.plugin.command.feature; + +import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; +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.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; +import net.momirealms.craftengine.core.plugin.command.FlagKeys; +import net.momirealms.craftengine.core.util.Key; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.command.CommandSender; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.Command; +import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; +import org.incendo.cloud.bukkit.parser.location.LocationParser; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.parser.standard.EnumParser; +import org.incendo.cloud.suggestion.Suggestion; +import org.incendo.cloud.suggestion.SuggestionProvider; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public class DebugSpawnFurnitureCommand extends BukkitCommandFeature { + + public DebugSpawnFurnitureCommand(CraftEngineCommandManager commandManager, CraftEngine plugin) { + super(commandManager, plugin); + } + + @Override + public Command.Builder assembleCommand(org.incendo.cloud.CommandManager manager, Command.Builder builder) { + return builder + .required("location", LocationParser.locationParser()) + .required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() { + @Override + public @NonNull CompletableFuture> suggestionsFuture(@NonNull CommandContext context, @NonNull CommandInput input) { + return CompletableFuture.completedFuture(plugin().furnitureManager().cachedSuggestions()); + } + })) + .optional("anchor-type", 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 optionalCustomFurniture = furnitureManager.getFurniture(id); + if (optionalCustomFurniture.isEmpty()) { + return; + } + Location location = context.get("location"); + CustomFurniture customFurniture = optionalCustomFurniture.get(); + AnchorType anchorType = (AnchorType) context.optional("anchor-type").orElse(customFurniture.getAnyPlacement()); + boolean playSound = context.flags().hasFlag("silent"); + furnitureManager.place(customFurniture, location, anchorType, !playSound); + }); + } + + @Override + public String getFeatureID() { + return "debug_spawn_furniture"; + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index d30c22073..b70bfacc7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -589,16 +589,6 @@ public class BukkitInjector { } } - public static class PalettedContainerMethodInterceptor { - public static final PalettedContainerMethodInterceptor INSTANCE = new PalettedContainerMethodInterceptor(); - - @RuntimeType - public Object intercept(@This Object thisObj, @AllArguments Object[] args, @Origin Method method) throws Throwable { - InjectedPalettedContainerHolder holder = (InjectedPalettedContainerHolder) thisObj; - return method.invoke(holder.target(), args); - } - } - public static class GetAndSetInterceptor { public static final GetAndSetInterceptor INSTANCE = new GetAndSetInterceptor(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/OptimizedReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/OptimizedReflections.java new file mode 100644 index 000000000..211da4037 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/OptimizedReflections.java @@ -0,0 +1,6 @@ +package net.momirealms.craftengine.bukkit.util; + +public class OptimizedReflections { + + +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java index ada46b3c4..5cb3f595d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java @@ -4,12 +4,20 @@ import net.momirealms.craftengine.core.pack.LoadingSequence; import net.momirealms.craftengine.core.plugin.Reloadable; import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser; import net.momirealms.craftengine.core.util.Key; +import org.incendo.cloud.suggestion.Suggestion; +import java.util.Collection; import java.util.Optional; public interface FurnitureManager extends Reloadable, ConfigSectionParser { String CONFIG_SECTION_NAME = "furniture"; + void delayedLoad(); + + void initSuggestions(); + + Collection cachedSuggestions(); + void delayedInit(); @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 7937e1da9..906751b4e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -103,6 +103,7 @@ public abstract class CraftEngine implements Plugin { // load at last this.guiManager.reload(); this.blockManager.delayedLoad(); + this.furnitureManager.delayedLoad(); this.itemBrowserManager.delayedLoad(); this.soundManager.delayedLoad(); this.imageManager.delayedLoad(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java index 77b5c2d1e..28f2b5822 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java @@ -3,12 +3,15 @@ package net.momirealms.craftengine.core.util; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.reflect.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ReflectionUtils { + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private ReflectionUtils() {} @@ -446,4 +449,22 @@ public class ReflectionUtils { } return constructors[0]; } + + public static MethodHandle unreflectGetter(Field field) throws IllegalAccessException { + try { + return LOOKUP.unreflectGetter(field); + } catch (IllegalAccessException e) { + field.setAccessible(true); + return LOOKUP.unreflectGetter(field); + } + } + + public static MethodHandle unreflectMethod(Method method) throws IllegalAccessException { + try { + return LOOKUP.unreflect(method); + } catch (IllegalAccessException e) { + method.setAccessible(true); + return LOOKUP.unreflect(method); + } + } } diff --git a/gradle.properties b/gradle.properties index 3f90eae1f..70e7e59b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,7 +40,7 @@ geantyref_version=1.3.16 zstd_version=1.5.6-9 commons_io_version=2.17.0 sparrow_nbt_version=0.3 -sparrow_util_version=0.32 +sparrow_util_version=0.33 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8