From eaf8d3663b15419507146389f354375871849d81 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 20 May 2025 04:10:35 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=96=B9=E5=9D=97?= =?UTF-8?q?=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/BukkitBlockManager.java | 338 ++++++------------ .../bukkit/block/BukkitCustomBlock.java | 62 +++- .../bukkit/item/BukkitCustomItem.java | 4 +- .../bukkit/item/BukkitItemManager.java | 1 - .../DebugAppearanceStateUsageCommand.java | 2 +- .../feature/TotemAnimationCommand.java | 8 +- .../bukkit/util/BlockStateUtils.java | 4 +- .../bukkit/util/InteractUtils.java | 2 +- .../core/block/AbstractBlockManager.java | 77 +++- .../core/block/AbstractCustomBlock.java | 195 ++++++++++ .../craftengine/core/block/BlockManager.java | 14 + .../craftengine/core/block/BlockSettings.java | 1 + .../core/block/BlockStateMatcher.java | 2 +- .../craftengine/core/block/CustomBlock.java | 240 ++----------- .../craftengine/core/block/EmptyBlock.java | 6 +- .../core/block/ImmutableBlockState.java | 14 +- .../core/block/InactiveCustomBlock.java | 6 +- .../core/block/UnsafeBlockStateMatcher.java | 2 +- .../craftengine/core/block/VanillaBlock.java | 6 + .../core/block/behavior/BlockBehaviors.java | 2 +- .../core/pack/model/LegacyItemModel.java | 6 +- .../context/function/OpenWindowFunction.java | 5 +- .../plugin/context/function/RunFunction.java | 6 +- .../craftengine/core/util/GsonHelper.java | 13 + .../core/util/IntIdentityList.java | 1 - .../craftengine/core/util/ListUtils.java | 16 + .../core/util/ResourceConfigUtils.java | 49 +++ 27 files changed, 598 insertions(+), 484 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/util/ListUtils.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 6f0b2a94d..5308d06ee 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -3,12 +3,10 @@ package net.momirealms.craftengine.bukkit.block; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dejvokep.boostedyaml.YamlDocument; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -28,12 +26,8 @@ import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration; import net.momirealms.craftengine.core.plugin.CraftEngine; 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.function.Function; import net.momirealms.craftengine.core.plugin.event.EventFunctions; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.plugin.locale.TranslationManager; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.registry.WritableRegistry; @@ -45,7 +39,6 @@ import org.bukkit.Registry; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; @@ -58,50 +51,34 @@ public class BukkitBlockManager extends AbstractBlockManager { private static BukkitBlockManager instance; private final BukkitCraftEngine plugin; private final BlockParser blockParser; - - // A temporary map used to detect whether the same block state corresponds to multiple models. - private final Map tempRegistryIdConflictMap = new Int2ObjectOpenHashMap<>(); - // A temporary map that converts the custom block registered on the server to the vanilla block ID. - private final Map tempBlockAppearanceConvertor = new Int2IntOpenHashMap(); - // A temporary map that stores the model path of a certain vanilla block state - private final Map tempVanillaBlockStateModels = new Int2ObjectOpenHashMap<>(); - // The total amount of blocks registered private int customBlockCount; protected final ImmutableBlockState[] stateId2ImmutableBlockStates; // Minecraft objects // Cached new blocks $ holders - private ImmutableMap internalId2StateId; - private ImmutableMap stateId2BlockHolder; + private Map internalId2StateId; + private Map stateId2BlockHolder; // This map is used to change the block states that are not necessarily needed into a certain block state - private ImmutableMap blockAppearanceMapper; + private Map blockAppearanceMapper; // Used to automatically arrange block states for strings such as minecraft:note_block:0 - private ImmutableMap> blockAppearanceArranger; - private ImmutableMap> realBlockArranger; + private Map> blockAppearanceArranger; + private Map> realBlockArranger; // Record the amount of real blocks by block type - private LinkedHashMap registeredRealBlockSlots; + private Map registeredRealBlockSlots; // A set of blocks that sounds have been removed - private ImmutableSet affectedSoundBlocks; - private ImmutableMap soundMapper; + private Set affectedSoundBlocks; + private Map soundMapper; // A list to record the order of registration private List blockRegisterOrder = new ObjectArrayList<>(); - - // a reverted mapper - private final Map> appearanceToRealState = new Int2ObjectOpenHashMap<>(); - // Used to store override information of json files - private final Map> blockStateOverrides = new HashMap<>(); - // for mod, real block id -> state models - private final Map modBlockStates = new HashMap<>(); // Event listeners private final BlockEventListener blockEventListener; private final FallingBlockRemoveListener fallingBlockRemoveListener; - - private Map> clientBoundTags = Map.of(); - private Map> previousTags = Map.of(); + // cached tag packet protected Object cachedUpdateTagsPacket; public BukkitBlockManager(BukkitCraftEngine plugin) { super(plugin); + instance = this; this.plugin = plugin; this.blockParser = new BlockParser(); this.initVanillaRegistry(); @@ -120,42 +97,33 @@ public class BukkitBlockManager extends AbstractBlockManager { if (enableNoteBlocks) { this.recordVanillaNoteBlocks(); } - if (VersionHelper.isOrAbove1_20_3()) { - this.fallingBlockRemoveListener = new FallingBlockRemoveListener(); - } else this.fallingBlockRemoveListener = null; - this.stateId2ImmutableBlockStates = new ImmutableBlockState[customBlockCount]; + this.fallingBlockRemoveListener = VersionHelper.isOrAbove1_20_3() ? new FallingBlockRemoveListener() : null; + this.stateId2ImmutableBlockStates = new ImmutableBlockState[this.customBlockCount]; Arrays.fill(this.stateId2ImmutableBlockStates, EmptyBlock.INSTANCE.defaultState()); - instance = this; this.resetPacketConsumers(); } - public List blockRegisterOrder() { - return Collections.unmodifiableList(this.blockRegisterOrder); - } - public static BukkitBlockManager instance() { return instance; } + public List blockRegisterOrder() { + return Collections.unmodifiableList(this.blockRegisterOrder); + } + @Override public void delayedInit() { - Bukkit.getPluginManager().registerEvents(this.blockEventListener, plugin.bootstrap()); + Bukkit.getPluginManager().registerEvents(this.blockEventListener, this.plugin.bootstrap()); if (this.fallingBlockRemoveListener != null) { - Bukkit.getPluginManager().registerEvents(this.fallingBlockRemoveListener, plugin.bootstrap()); + Bukkit.getPluginManager().registerEvents(this.fallingBlockRemoveListener, this.plugin.bootstrap()); } } @Override public void unload() { super.unload(); - this.clearCache(); - this.appearanceToRealState.clear(); - this.blockStateOverrides.clear(); - this.modBlockStates.clear(); if (EmptyBlock.STATE != null) Arrays.fill(this.stateId2ImmutableBlockStates, EmptyBlock.STATE); - this.previousTags = this.clientBoundTags; - this.clientBoundTags = new HashMap<>(); } @Override @@ -172,15 +140,14 @@ public class BukkitBlockManager extends AbstractBlockManager { @Override public void delayedLoad() { - initSuggestions(); - resetPacketConsumers(); - clearCache(); - resendTags(); + this.resetPacketConsumers(); + super.delayedLoad(); } - private void resendTags() { + @Override + protected void resendTags() { // if there's no change - if (this.clientBoundTags.equals(this.previousTags)) return; + if (this.clientBoundTags.equals(this.previousClientBoundTags)) return; List list = new ArrayList<>(); for (Map.Entry> entry : this.clientBoundTags.entrySet()) { list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue())); @@ -197,23 +164,19 @@ public class BukkitBlockManager extends AbstractBlockManager { } } - private void clearCache() { - this.tempRegistryIdConflictMap.clear(); - this.tempBlockAppearanceConvertor.clear(); - this.tempVanillaBlockStateModels.clear(); - } - @Nullable public Object getMinecraftBlockHolder(int stateId) { return stateId2BlockHolder.get(stateId); } @NotNull + @Override public ImmutableBlockState getImmutableBlockStateUnsafe(int stateId) { return this.stateId2ImmutableBlockStates[stateId - BlockStateUtils.vanillaStateSize()]; } @Nullable + @Override public ImmutableBlockState getImmutableBlockState(int stateId) { if (!BlockStateUtils.isVanillaBlock(stateId)) { return this.stateId2ImmutableBlockStates[stateId - BlockStateUtils.vanillaStateSize()]; @@ -221,34 +184,46 @@ public class BukkitBlockManager extends AbstractBlockManager { return null; } - @Override - public Map modBlockStates() { - return Collections.unmodifiableMap(this.modBlockStates); - } - @Override public ConfigParser parser() { return this.blockParser; } @Override - public Map> blockOverrides() { - return Collections.unmodifiableMap(this.blockStateOverrides); + public void addBlock(Key id, CustomBlock customBlock) { + // bind appearance and real state + for (ImmutableBlockState state : customBlock.variantProvider().states()) { + ImmutableBlockState previous = this.stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()]; + if (previous != null && !previous.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.block.state.bind_failed", state.toString(), previous.toString()); + } + this.stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()] = state; + this.tempBlockAppearanceConvertor.put(state.customBlockState().registryId(), state.vanillaBlockState().registryId()); + this.appearanceToRealState.computeIfAbsent(state.vanillaBlockState().registryId(), k -> new IntArrayList()).add(state.customBlockState().registryId()); + } + super.addBlock(id, customBlock); } - public ImmutableMap> blockAppearanceArranger() { + @Override + public Key getBlockOwnerId(PackedBlockState state) { + return BlockStateUtils.getBlockOwnerIdFromState(state.handle()); + } + + @Override + public int availableAppearances(Key blockType) { + return Optional.ofNullable(this.registeredRealBlockSlots.get(blockType)).orElse(0); + } + + @NotNull + public Map> blockAppearanceArranger() { return this.blockAppearanceArranger; } - public ImmutableMap> realBlockArranger() { + @NotNull + public Map> realBlockArranger() { return this.realBlockArranger; } - @Nullable - public List appearanceToRealStates(int appearanceStateId) { - return this.appearanceToRealState.get(appearanceStateId); - } - private void initMirrorRegistry() { int size = RegistryUtils.currentBlockRegistrySize(); PackedBlockState[] states = new PackedBlockState[size]; @@ -276,25 +251,25 @@ public class BukkitBlockManager extends AbstractBlockManager { private void initVanillaRegistry() { int vanillaStateCount; - if (plugin.hasMod()) { + if (this.plugin.hasMod()) { try { Class modClass = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS); Field amountField = ReflectionUtils.getDeclaredField(modClass, "vanillaRegistrySize"); vanillaStateCount = amountField.getInt(null); } catch (Exception e) { vanillaStateCount = RegistryUtils.currentBlockRegistrySize(); - plugin.logger().severe("Fatal error", e); + this.plugin.logger().severe("Fatal error", e); } } else { vanillaStateCount = RegistryUtils.currentBlockRegistrySize(); } - plugin.logger().info("Vanilla block count: " + vanillaStateCount); + this.plugin.logger().info("Vanilla block count: " + vanillaStateCount); BlockStateUtils.init(vanillaStateCount); } @SuppressWarnings("unchecked") private void registerBlocks() { - plugin.logger().info("Registering blocks. Please wait..."); + this.plugin.logger().info("Registering blocks. Please wait..."); try { ImmutableMap.Builder builder1 = ImmutableMap.builder(); ImmutableMap.Builder builder2 = ImmutableMap.builder(); @@ -367,7 +342,7 @@ public class BukkitBlockManager extends AbstractBlockManager { parseVanillaBlock(pack, path, id, section); } else { // check duplicated config - if (byId.containsKey(id)) { + if (BukkitBlockManager.this.byId.containsKey(id)) { throw new LocalizedResourceConfigException("warning.config.block.duplicate"); } parseCustomBlock(pack, path, id, section); @@ -376,128 +351,73 @@ public class BukkitBlockManager extends AbstractBlockManager { private void parseCustomBlock(Pack pack, Path path, Key id, Map section) { // read block settings - BlockSettings settings = BlockSettings.fromMap(MiscUtils.castToMap(section.getOrDefault("settings", Map.of()), false)); - - // read loot table - LootTable lootTable = LootTable.fromMap(MiscUtils.castToMap(section.getOrDefault("loot", Map.of()), false)); - + BlockSettings settings = BlockSettings.fromMap(MiscUtils.castToMap(section.get("settings"), true)); // read states Map> properties; Map appearances; Map variants; - Object stateObj = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "state", "states"), "warning.config.block.missing_state"); - Map stateSection = MiscUtils.castToMap(stateObj, true); + Map stateSection = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "state", "states"), "warning.config.block.missing_state"), true); + boolean singleState = !stateSection.containsKey("properties"); // single state - if (!stateSection.containsKey("properties")) { + if (singleState) { properties = Map.of(); - int internalId = ResourceConfigUtils.getAsInt(stateSection.getOrDefault("id", -1), "id"); - if (internalId < 0) { - throw new LocalizedResourceConfigException("warning.config.block.state.missing_real_id"); - } - - Pair pair = parseAppearanceSection(id, stateSection); - if (pair == null) return; - - appearances = Map.of("default", pair.right()); - String internalBlock = pair.left().value() + "_" + internalId; - Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, internalBlock); + int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("id"), "warning.config.block.state.missing_real_id"), "id"); + VanillaBlock vanillaBlock = getVanillaBlock(id, stateSection); + appearances = Map.of("", vanillaBlock.registryId()); + Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, vanillaBlock.type().value() + "_" + internalId); int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1); if (internalBlockRegistryId == -1) { - throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", - internalBlock, - String.valueOf(registeredRealBlockSlots.get(pair.left()) - 1)); + throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", internalBlockId.toString(), String.valueOf(availableAppearances(vanillaBlock.type()) - 1)); } - variants = Map.of("", new VariantState("default", settings, internalBlockRegistryId)); + variants = Map.of("", new VariantState("", settings, internalBlockRegistryId)); } else { // properties - Map propertySection = MiscUtils.castToMap(stateSection.get("properties"), true); - if (propertySection == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.missing_properties"); - } - properties = parseProperties(propertySection); + properties = getProperties(MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("properties"), "warning.config.block.state.missing_properties"), true)); // appearance - Map appearancesSection = MiscUtils.castToMap(stateSection.get("appearances"), true); - if (appearancesSection == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.missing_appearances"); - } appearances = new HashMap<>(); - Map tempTypeMap = new HashMap<>(); - for (Map.Entry appearanceEntry : appearancesSection.entrySet()) { - if (appearanceEntry.getValue() instanceof Map appearanceSection) { - Pair pair = parseAppearanceSection(id, MiscUtils.castToMap(appearanceSection, false)); - if (pair == null) return; - appearances.put(appearanceEntry.getKey(), pair.right()); - tempTypeMap.put(appearanceEntry.getKey(), pair.left()); + Map appearance2BlockType = new HashMap<>(); + for (Map.Entry appearanceEntry : MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("appearances"), "warning.config.block.state.missing_appearances"), false).entrySet()) { + if (appearanceEntry.getValue() instanceof Map) { + VanillaBlock vanillaBlock = getVanillaBlock(id, MiscUtils.castToMap(appearanceEntry.getValue(), false)); + appearances.put(appearanceEntry.getKey(), vanillaBlock.registryId()); + appearance2BlockType.put(appearanceEntry.getKey(), vanillaBlock.type()); } } // variants - Map variantsSection = MiscUtils.castToMap(stateSection.get("variants"), true); - if (variantsSection == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.missing_variants"); - } variants = new HashMap<>(); - for (Map.Entry variantEntry : variantsSection.entrySet()) { - if (variantEntry.getValue() instanceof Map variantSection0) { - Map variantSection = MiscUtils.castToMap(variantSection0, false); - String variantName = variantEntry.getKey(); - String appearance = (String) variantSection.get("appearance"); - if (appearance == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.variant.missing_appearance", variantName); - } + for (Map.Entry variantEntry : MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("variants"), "warning.config.block.state.missing_variants"), false).entrySet()) { + if (variantEntry.getValue() instanceof Map) { + Map variantSection = MiscUtils.castToMap(variantEntry.getValue(), false); + String variantNBT = variantEntry.getKey(); + String appearance = ResourceConfigUtils.requireNonEmptyStringOrThrow(variantSection.get("appearance"), "warning.config.block.state.variant.missing_appearance"); if (!appearances.containsKey(appearance)) { - throw new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantName, appearance); + throw new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantNBT, appearance); } - int internalId = ResourceConfigUtils.getAsInt(variantSection.getOrDefault("id", -1), "id"); - Key baseBlock = tempTypeMap.get(appearance); + int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(variantSection.get("id"), "warning.config.block.state.missing_real_id"), "id"); + Key baseBlock = appearance2BlockType.get(appearance); Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, baseBlock.value() + "_" + internalId); int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1); if (internalBlockRegistryId == -1) { - throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", - internalBlockId.toString(), - String.valueOf(registeredRealBlockSlots.getOrDefault(baseBlock, 1) - 1)); + throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", internalBlockId.toString(), String.valueOf(availableAppearances(baseBlock) - 1)); } Map anotherSetting = MiscUtils.castToMap(variantSection.get("settings"), true); - variants.put(variantName, new VariantState(appearance, anotherSetting == null ? settings : BlockSettings.ofFullCopy(settings, anotherSetting), internalBlockRegistryId)); + variants.put(variantNBT, new VariantState(appearance, anotherSetting == null ? settings : BlockSettings.ofFullCopy(settings, anotherSetting), internalBlockRegistryId)); } } } - Object eventsObj = ResourceConfigUtils.get(section, "events", "event"); - EnumMap>> events = EventFunctions.parseEvents(eventsObj); - - Map behaviors = MiscUtils.castToMap(section.getOrDefault("behavior", Map.of()), false); CustomBlock block = BukkitCustomBlock.builder(id) .appearances(appearances) .variantMapper(variants) - .lootTable(lootTable) .properties(properties) .settings(settings) - .behavior(behaviors) - .events(events) + .lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true))) + .behavior(MiscUtils.castToMap(section.get("behavior"), true)) + .events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event"))) .build(); - // bind appearance and real state - for (ImmutableBlockState state : block.variantProvider().states()) { - ImmutableBlockState previous = stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()]; - if (previous != null && !previous.isEmpty()) { - TranslationManager.instance().log("warning.config.block.state.bind_failed", path.toString(), id.toString(), state.toString(), previous.toString()); - continue; - } - stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()] = state; - tempBlockAppearanceConvertor.put(state.customBlockState().registryId(), state.vanillaBlockState().registryId()); - appearanceToRealState.computeIfAbsent(state.vanillaBlockState().registryId(), k -> new IntArrayList()).add(state.customBlockState().registryId()); - } - - BukkitBlockManager.this.byId.put(id, block); - - // generate mod assets - if (Config.generateModAssets()) { - for (ImmutableBlockState state : block.variantProvider().states()) { - Key realBlockId = BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState()); - modBlockStates.put(realBlockId, tempVanillaBlockStateModels.get(state.vanillaBlockState().registryId())); - } - } + addBlock(id, block); } private void parseVanillaBlock(Pack pack, Path path, Key id, Map section) { @@ -518,7 +438,8 @@ public class BukkitBlockManager extends AbstractBlockManager { } } - private Map> parseProperties(Map propertiesSection) { + @NotNull + private Map> getProperties(Map propertiesSection) { Map> properties = new HashMap<>(); for (Map.Entry entry : propertiesSection.entrySet()) { Property property = Properties.fromMap(entry.getKey(), MiscUtils.castToMap(entry.getValue(), false)); @@ -527,69 +448,40 @@ public class BukkitBlockManager extends AbstractBlockManager { return properties; } - @Nullable - private Pair parseAppearanceSection(Key id, Map section) { + @NotNull + private VanillaBlock getVanillaBlock(Key id, Map section) { // require state non null - Object vanillaStateString = section.get("state"); - if (vanillaStateString == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.missing_state"); - } - + String vanillaBlockStateTag = ResourceConfigUtils.requireNonEmptyStringOrThrow(section.get("state"), "warning.config.block.state.missing_state"); // get its registry id - int vanillaStateRegistryId = parseVanillaStateRegistryId(vanillaStateString.toString()); - - // check conflict - Key ifAny = this.tempRegistryIdConflictMap.get(vanillaStateRegistryId); + int vanillaBlockStateRegistryId = getVanillaBlockStateRegistryId(vanillaBlockStateTag); + // check if another block has occupied the appearance + // TODO blocks share the same look + Key ifAny = this.tempRegistryIdConflictMap.get(vanillaBlockStateRegistryId); if (ifAny != null && !ifAny.equals(id)) { - throw new LocalizedResourceConfigException("warning.config.block.state.conflict", BlockStateUtils.fromBlockData(BlockStateUtils.idToBlockState(vanillaStateRegistryId)).getAsString(), ifAny.toString()); + throw new LocalizedResourceConfigException("warning.config.block.state.conflict", BlockStateUtils.fromBlockData(BlockStateUtils.idToBlockState(vanillaBlockStateRegistryId)).getAsString(), ifAny.toString()); } - // require models not to be null - Object models = section.get("models"); - if (models == null) { - models = section.get("model"); - } - if (models == null) { + Object models = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "models", "model"), "warning.config.block.state.missing_model"); + List variants = ResourceConfigUtils.parseConfigAsList(models, this::getVariantModel); + if (variants.isEmpty()) { throw new LocalizedResourceConfigException("warning.config.block.state.missing_model"); } - - List variants = new ArrayList<>(); - if (models instanceof Map singleModelSection) { - loadVariantModel(variants, MiscUtils.castToMap(singleModelSection, false)); - } else if (models instanceof List modelList) { - for (Object model : modelList) { - if (model instanceof Map singleModelMap) { - loadVariantModel(variants, MiscUtils.castToMap(singleModelMap, false)); - } - } - } - if (variants.isEmpty()) return null; - - this.tempRegistryIdConflictMap.put(vanillaStateRegistryId, id); - String blockState = BlockStateUtils.idToBlockState(vanillaStateRegistryId).toString(); - Key block = Key.of(blockState.substring(blockState.indexOf('{') + 1, blockState.lastIndexOf('}'))); - String propertyData = blockState.substring(blockState.indexOf('[') + 1, blockState.lastIndexOf(']')); - Map paths = this.blockStateOverrides.computeIfAbsent(block, k -> new HashMap<>()); - if (variants.size() == 1) { - paths.put(propertyData, variants.get(0)); - this.tempVanillaBlockStateModels.put(vanillaStateRegistryId, variants.get(0)); - } else { - JsonArray array = new JsonArray(); - for (JsonObject object : variants) { - array.add(object); - } - paths.put(propertyData, array); - this.tempVanillaBlockStateModels.put(vanillaStateRegistryId, array); - } - return Pair.of(block, vanillaStateRegistryId); + // TODO blocks share the same look + this.tempRegistryIdConflictMap.put(vanillaBlockStateRegistryId, id); + // gets the full block state + String blockState = BlockStateUtils.idToBlockState(vanillaBlockStateRegistryId).toString(); + Key blockId = Key.of(blockState.substring(blockState.indexOf('{') + 1, blockState.lastIndexOf('}'))); + String propertyNBT = blockState.substring(blockState.indexOf('[') + 1, blockState.lastIndexOf(']')); + // for generating assets + JsonElement combinedVariant = GsonHelper.combine(variants); + this.blockStateOverrides.computeIfAbsent(blockId, k -> new HashMap<>()).put(propertyNBT, combinedVariant); + this.tempVanillaBlockStateModels.put(vanillaBlockStateRegistryId, combinedVariant); + return new VanillaBlock(blockId, propertyNBT, vanillaBlockStateRegistryId); } - private void loadVariantModel(List variants, Map singleModelMap) { + private JsonObject getVariantModel(Map singleModelMap) { JsonObject json = new JsonObject(); - String modelPath = (String) singleModelMap.get("path"); - if (modelPath == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.model.missing_path"); - } + String modelPath = ResourceConfigUtils.requireNonEmptyStringOrThrow(singleModelMap.get("path"), "warning.config.block.state.model.missing_path"); if (!ResourceLocation.isValid(modelPath)) { throw new LocalizedResourceConfigException("warning.config.block.state.model.invalid_path", modelPath); } @@ -602,10 +494,10 @@ public class BukkitBlockManager extends AbstractBlockManager { if (generationMap != null) { prepareModelGeneration(ModelGeneration.of(Key.of(modelPath), generationMap)); } - variants.add(json); + return json; } - private int parseVanillaStateRegistryId(String blockState) { + private int getVanillaBlockStateRegistryId(String blockState) { String[] split = blockState.split(":", 3); if (split.length >= 4) { throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index 17891cded..c9897a727 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.*; -public class BukkitCustomBlock extends CustomBlock { +public class BukkitCustomBlock extends AbstractCustomBlock { protected BukkitCustomBlock( Key id, @@ -147,17 +147,67 @@ public class BukkitCustomBlock extends CustomBlock { } public static Builder builder(Key id) { - return new Builder(id); + return new BuilderImpl(id); } - public static class Builder extends CustomBlock.Builder { + public static class BuilderImpl implements Builder { + protected final Key id; + protected Map> properties; + protected Map appearances; + protected Map variantMapper; + protected BlockSettings settings; + protected Map behavior; + protected LootTable lootTable; + protected EnumMap>> events; - protected Builder(Key id) { - super(id); + public BuilderImpl(Key id) { + this.id = id; } @Override - public CustomBlock build() { + public Builder events(EnumMap>> events) { + this.events = events; + return this; + } + + @Override + public Builder appearances(Map appearances) { + this.appearances = appearances; + return this; + } + + @Override + public Builder behavior(Map behavior) { + this.behavior = behavior; + return this; + } + + @Override + public Builder lootTable(LootTable lootTable) { + this.lootTable = lootTable; + return this; + } + + @Override + public Builder properties(Map> properties) { + this.properties = properties; + return this; + } + + @Override + public Builder settings(BlockSettings settings) { + this.settings = settings; + return this; + } + + @Override + public Builder variantMapper(Map variantMapper) { + this.variantMapper = variantMapper; + return this; + } + + @Override + public @NotNull CustomBlock build() { // create or get block holder Holder.Reference holder = BuiltInRegistries.BLOCK.get(id).orElseGet(() -> ((WritableRegistry) BuiltInRegistries.BLOCK).registerForHolder(new ResourceKey<>(BuiltInRegistries.BLOCK.key().location(), id))); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java index a0438f38c..fd7c32143 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java @@ -13,7 +13,9 @@ import net.momirealms.craftengine.core.util.Key; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; public class BukkitCustomItem extends AbstractCustomItem { private final Material material; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 57fa33974..f51b4ee82 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -36,7 +36,6 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugAppearanceStateUsageCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugAppearanceStateUsageCommand.java index 2aad44aad..f47eb842e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugAppearanceStateUsageCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugAppearanceStateUsageCommand.java @@ -51,7 +51,7 @@ public class DebugAppearanceStateUsageCommand extends BukkitCommandFeature reals = blockManager.appearanceToRealStates(appearance); - if (reals == null) { + if (reals == null || reals.isEmpty()) { Component hover = Component.text(baseBlockId.value() + ":" + i).color(NamedTextColor.GREEN); hover = hover.append(Component.newline()).append(Component.text(BlockStateUtils.fromBlockData(BlockStateUtils.idToBlockState(appearance)).getAsString()).color(NamedTextColor.GREEN)); text = text.color(NamedTextColor.GREEN).hoverEvent(HoverEvent.showText(hover)); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java index e0381d921..63f72aaca 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java @@ -3,16 +3,17 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.item.ComponentTypes; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; -import net.momirealms.craftengine.bukkit.util.MaterialUtils; import net.momirealms.craftengine.bukkit.util.PlayerUtils; -import net.momirealms.craftengine.core.item.*; +import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.item.ItemKeys; 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.plugin.locale.MessageConstants; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; -import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -26,7 +27,6 @@ import org.incendo.cloud.bukkit.parser.selector.MultiplePlayerSelectorParser; import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandInput; import org.incendo.cloud.parser.flag.CommandFlag; -import org.incendo.cloud.parser.standard.StringParser; import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.SuggestionProvider; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java index 81163c601..a5d8d4446 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java @@ -101,10 +101,10 @@ public class BlockStateUtils { } public static Key getBlockOwnerId(Block block) { - return getBlockOwnerId(block.getBlockData()); + return getBlockOwnerIdFromData(block.getBlockData()); } - public static Key getBlockOwnerId(BlockData block) { + public static Key getBlockOwnerIdFromData(BlockData block) { Object blockState = blockDataToBlockState(block); return getBlockOwnerIdFromState(blockState); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java index 7152b3f98..fa6c73e44 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java @@ -274,7 +274,7 @@ public class InteractUtils { } public static boolean isInteractable(Player player, BlockData state, BlockHitResult hit, Item item) { - Key blockType = BlockStateUtils.getBlockOwnerId(state); + Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state); if (INTERACTIONS.containsKey(blockType)) { return INTERACTIONS.get(blockType).apply(player, item, state, hit); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java index ba3e03d8f..48bde480b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java @@ -1,9 +1,14 @@ package net.momirealms.craftengine.core.block; +import com.google.gson.JsonElement; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.momirealms.craftengine.core.pack.model.generation.AbstractModelGenerator; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.util.Key; import org.incendo.cloud.suggestion.Suggestion; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -14,11 +19,46 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem protected final List cachedSuggestions = new ArrayList<>(); // Cached Namespace protected final Set namespacesInUse = new HashSet<>(); + // for mod, real block id -> state models + protected final Map modBlockStates = new HashMap<>(); + // A temporary map that stores the model path of a certain vanilla block state + protected final Map tempVanillaBlockStateModels = new Int2ObjectOpenHashMap<>(); + // A temporary map used to detect whether the same block state corresponds to multiple models. + protected final Map tempRegistryIdConflictMap = new Int2ObjectOpenHashMap<>(); + // A temporary map that converts the custom block registered on the server to the vanilla block ID. + protected final Map tempBlockAppearanceConvertor = new Int2IntOpenHashMap(); + // Used to store override information of json files + protected final Map> blockStateOverrides = new HashMap<>(); + // a reverted mapper + protected final Map> appearanceToRealState = new Int2ObjectOpenHashMap<>(); + // client side block tags + protected Map> clientBoundTags = Map.of(); + protected Map> previousClientBoundTags = Map.of(); - public AbstractBlockManager(CraftEngine plugin) { + protected AbstractBlockManager(CraftEngine plugin) { super(plugin); } + @Override + public void unload() { + super.clearModelsToGenerate(); + this.clearCache(); + this.cachedSuggestions.clear(); + this.blockStateOverrides.clear(); + this.modBlockStates.clear(); + this.byId.clear(); + this.previousClientBoundTags = this.clientBoundTags; + this.clientBoundTags = new HashMap<>(); + this.appearanceToRealState.clear(); + } + + @Override + public void delayedLoad() { + this.initSuggestions(); + this.clearCache(); + this.resendTags(); + } + @Override public Map blocks() { return Collections.unmodifiableMap(this.byId); @@ -30,10 +70,24 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem } @Override - public void unload() { - super.clearModelsToGenerate(); - this.cachedSuggestions.clear(); - this.byId.clear(); + public void addBlock(Key id, CustomBlock customBlock) { + this.byId.put(id, customBlock); + // generate mod assets + if (Config.generateModAssets()) { + for (ImmutableBlockState state : customBlock.variantProvider().states()) { + this.modBlockStates.put(getBlockOwnerId(state.customBlockState()), this.tempVanillaBlockStateModels.get(state.vanillaBlockState().registryId())); + } + } + } + + @Override + public Map modBlockStates() { + return Collections.unmodifiableMap(this.modBlockStates); + } + + @Override + public Map> blockOverrides() { + return Collections.unmodifiableMap(this.blockStateOverrides); } @Override @@ -45,6 +99,12 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem return Collections.unmodifiableSet(this.namespacesInUse); } + protected void clearCache() { + this.tempRegistryIdConflictMap.clear(); + this.tempBlockAppearanceConvertor.clear(); + this.tempVanillaBlockStateModels.clear(); + } + protected void initSuggestions() { this.cachedSuggestions.clear(); this.namespacesInUse.clear(); @@ -60,4 +120,11 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem this.cachedSuggestions.add(Suggestion.suggestion(state)); } } + + @NotNull + public List appearanceToRealStates(int appearanceStateId) { + return Optional.ofNullable(this.appearanceToRealState.get(appearanceStateId)).orElse(List.of()); + } + + protected abstract void resendTags(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java new file mode 100644 index 000000000..cb3efd929 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java @@ -0,0 +1,195 @@ +package net.momirealms.craftengine.core.block; + +import com.google.common.collect.ImmutableMap; +import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviors; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.item.context.BlockPlaceContext; +import net.momirealms.craftengine.core.loot.LootTable; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; +import net.momirealms.craftengine.core.plugin.context.function.Function; +import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.shared.block.BlockBehavior; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.Tag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.BiFunction; + +public abstract class AbstractCustomBlock implements CustomBlock { + protected final Holder holder; + protected final Key id; + protected final BlockStateVariantProvider variantProvider; + protected final Map> properties; + protected final BlockBehavior behavior; + protected final BiFunction placementFunction; + protected final ImmutableBlockState defaultState; + protected final Map>> events; + @Nullable + protected final LootTable lootTable; + + protected AbstractCustomBlock( + @NotNull Key id, + @NotNull Holder.Reference holder, + @NotNull Map> properties, + @NotNull Map appearances, + @NotNull Map variantMapper, + @NotNull BlockSettings settings, + @NotNull Map>> events, + @Nullable Map behavior, + @Nullable LootTable lootTable + ) { + holder.bindValue(this); + this.holder = holder; + this.id = id; + this.lootTable = lootTable; + this.properties = ImmutableMap.copyOf(properties); + this.events = events; + this.variantProvider = new BlockStateVariantProvider(holder, ImmutableBlockState::new, properties); + this.defaultState = this.variantProvider.getDefaultState(); + this.behavior = BlockBehaviors.fromMap(this, behavior); + List> placements = new ArrayList<>(4); + for (Map.Entry> propertyEntry : this.properties.entrySet()) { + placements.add(Property.createStateForPlacement(propertyEntry.getKey(), propertyEntry.getValue())); + } + this.placementFunction = composite(placements); + for (Map.Entry entry : variantMapper.entrySet()) { + String nbtString = entry.getKey(); + CompoundTag tag = BlockNbtParser.deserialize(this, nbtString); + if (tag == null) { + throw new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", nbtString); + } + VariantState variantState = entry.getValue(); + int vanillaStateRegistryId = appearances.getOrDefault(variantState.appearance(), -1); + // This should never happen + if (vanillaStateRegistryId == -1) { + vanillaStateRegistryId = appearances.values().iterator().next(); + } + // Late init states + for (ImmutableBlockState state : this.getPossibleStates(tag)) { + state.setBehavior(this.behavior); + state.setSettings(variantState.settings()); + state.setVanillaBlockState(BlockRegistryMirror.stateByRegistryId(vanillaStateRegistryId)); + state.setCustomBlockState(BlockRegistryMirror.stateByRegistryId(variantState.internalRegistryId())); + } + } + // double check if there's any invalid state + for (ImmutableBlockState state : this.variantProvider().states()) { + if (state.settings() == null) { + state.setSettings(settings); + } + } + this.applyPlatformSettings(); + } + + private static BiFunction composite(List> placements) { + return switch (placements.size()) { + case 0 -> (c, i) -> i; + case 1 -> placements.get(0); + case 2 -> { + BiFunction f1 = placements.get(0); + BiFunction f2 = placements.get(1); + yield (c, i) -> f2.apply(c, f1.apply(c, i)); + } + default -> (c, i) -> { + for (BiFunction f : placements) { + i = f.apply(c, i); + } + return i; + }; + }; + } + + protected abstract void applyPlatformSettings(); + + @Override + public @Nullable LootTable lootTable() { + return this.lootTable; + } + + @Override + public void execute(PlayerOptionalContext context, EventTrigger trigger) { + for (Function function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) { + function.run(context); + } + } + + @NotNull + @Override + public BlockStateVariantProvider variantProvider() { + return this.variantProvider; + } + + @NotNull + @Override + public final Key id() { + return this.id; + } + + @Override + public List getPossibleStates(CompoundTag nbt) { + List tempStates = new ArrayList<>(); + tempStates.add(defaultState()); + for (Property property : this.variantProvider.getDefaultState().getProperties()) { + Tag value = nbt.get(property.name()); + if (value != null) { + tempStates.replaceAll(immutableBlockState -> ImmutableBlockState.with(immutableBlockState, property, property.unpack(value))); + } else { + List newStates = new ArrayList<>(); + for (ImmutableBlockState state : tempStates) { + for (Object possibleValue : property.possibleValues()) { + newStates.add(ImmutableBlockState.with(state, property, possibleValue)); + } + } + tempStates = newStates; + } + } + return tempStates; + } + + @Override + public ImmutableBlockState getBlockState(CompoundTag nbt) { + ImmutableBlockState state = defaultState(); + for (Map.Entry entry : nbt.tags.entrySet()) { + Property property = this.variantProvider.getProperty(entry.getKey()); + if (property != null) { + try { + state = ImmutableBlockState.with(state, property, property.unpack(entry.getValue())); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to parse block state: " + entry.getKey(), e); + } + } + } + return state; + } + + @Override + public @Nullable Property getProperty(String name) { + return this.properties.get(name); + } + + @Override + public @NotNull Collection> properties() { + return this.properties.values(); + } + + @Override + public final ImmutableBlockState defaultState() { + return this.defaultState; + } + + @Override + public ImmutableBlockState getStateForPlacement(BlockPlaceContext context) { + ImmutableBlockState state = this.placementFunction.apply(context, defaultState()); + if (this.behavior instanceof AbstractBlockBehavior blockBehavior) { + state = blockBehavior.updateStateForPlacement(context, state); + } + return state; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java index 8cbeb5a5a..208355f1a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java @@ -7,7 +7,9 @@ import net.momirealms.craftengine.core.plugin.Manageable; import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.util.Key; import org.incendo.cloud.suggestion.Suggestion; +import org.jetbrains.annotations.NotNull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.Map; import java.util.Optional; @@ -26,7 +28,19 @@ public interface BlockManager extends Manageable, ModelGenerator { Optional blockById(Key key); + void addBlock(Key id, CustomBlock customBlock); + Collection cachedSuggestions(); Map soundMapper(); + + int availableAppearances(Key blockType); + + Key getBlockOwnerId(PackedBlockState state); + + @NotNull + ImmutableBlockState getImmutableBlockStateUnsafe(int stateId); + + @Nullable + ImmutableBlockState getImmutableBlockState(int stateId); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java index cfcfd042c..79e268a99 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java @@ -42,6 +42,7 @@ public class BlockSettings { } public static BlockSettings fromMap(Map map) { + if (map == null || map.isEmpty()) return BlockSettings.of(); return applyModifiers(BlockSettings.of(), map); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java index 3886220dc..87678487c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java @@ -24,7 +24,7 @@ public class BlockStateMatcher { } public boolean matches(ImmutableBlockState state) { - if (!state.owner().value().id.equals(this.id)) { + if (!state.owner().value().id().equals(this.id)) { return false; } for (Pair, Comparable> pair : this.properties) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java index 73c324414..2e3fb29a7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java @@ -1,251 +1,59 @@ package net.momirealms.craftengine.core.block; -import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; -import net.momirealms.craftengine.core.block.behavior.BlockBehaviors; import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.loot.LootTable; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; import net.momirealms.craftengine.core.plugin.event.EventTrigger; -import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.shared.block.BlockBehavior; import net.momirealms.sparrow.nbt.CompoundTag; -import net.momirealms.sparrow.nbt.Tag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.function.BiFunction; +import java.util.Collection; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; -public abstract class CustomBlock { - protected final Holder holder; - protected final Key id; - protected final BlockStateVariantProvider variantProvider; - protected final Map> properties; - protected final BlockBehavior behavior; - protected final List> placements; - protected final ImmutableBlockState defaultState; - protected final EnumMap>> events; - @Nullable - protected final LootTable lootTable; +public interface CustomBlock { - protected CustomBlock( - @NotNull Key id, - @NotNull Holder.Reference holder, - @NotNull Map> properties, - @NotNull Map appearances, - @NotNull Map variantMapper, - @NotNull BlockSettings settings, - @NotNull EnumMap>> events, - @Nullable Map behavior, - @Nullable LootTable lootTable - ) { - holder.bindValue(this); - this.holder = holder; - this.id = id; - this.lootTable = lootTable; - this.properties = properties; - this.placements = new ArrayList<>(); - this.events = events; - this.variantProvider = new BlockStateVariantProvider(holder, ImmutableBlockState::new, properties); - this.defaultState = this.variantProvider.getDefaultState(); - this.behavior = BlockBehaviors.fromMap(this, behavior); - for (Map.Entry entry : variantMapper.entrySet()) { - String nbtString = entry.getKey(); - CompoundTag tag = BlockNbtParser.deserialize(this, nbtString); - if (tag == null) { - throw new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", nbtString); - } - VariantState variantState = entry.getValue(); - int vanillaStateRegistryId = appearances.getOrDefault(variantState.appearance(), -1); - // This should never happen - if (vanillaStateRegistryId == -1) { - vanillaStateRegistryId = appearances.values().iterator().next(); - } - // Late init states - for (ImmutableBlockState state : this.getPossibleStates(tag)) { - state.setBehavior(this.behavior); - state.setSettings(variantState.settings()); - state.setVanillaBlockState(BlockRegistryMirror.stateByRegistryId(vanillaStateRegistryId)); - state.setCustomBlockState(BlockRegistryMirror.stateByRegistryId(variantState.internalRegistryId())); - } - } - // double check if there's any invalid state - for (ImmutableBlockState state : this.variantProvider().states()) { - if (state.settings() == null) { - state.setSettings(settings); - } - } - this.applyPlatformSettings(); - for (Map.Entry> propertyEntry : this.properties.entrySet()) { - this.placements.add(Property.createStateForPlacement(propertyEntry.getKey(), propertyEntry.getValue())); - } - } + Key id(); - protected abstract void applyPlatformSettings(); + @Nullable LootTable lootTable(); - @Nullable - public LootTable lootTable() { - return lootTable; - } + void execute(PlayerOptionalContext context, EventTrigger trigger); - public void execute(PlayerOptionalContext context, EventTrigger trigger) { - for (Function function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) { - function.run(context); - } - } + @NotNull BlockStateVariantProvider variantProvider(); - @NotNull - public BlockStateVariantProvider variantProvider() { - return variantProvider; - } + List getPossibleStates(CompoundTag nbt); - @NotNull - public final Key id() { - return id; - } + ImmutableBlockState getBlockState(CompoundTag nbt); - private List getPossibleStates(CompoundTag nbt) { - List tempStates = new ArrayList<>(); - tempStates.add(defaultState()); - for (Property property : variantProvider.getDefaultState().getProperties()) { - Tag value = nbt.get(property.name()); - if (value != null) { - tempStates.replaceAll(immutableBlockState -> ImmutableBlockState.with(immutableBlockState, property, property.unpack(value))); - } else { - List newStates = new ArrayList<>(); - for (ImmutableBlockState state : tempStates) { - for (Object possibleValue : property.possibleValues()) { - newStates.add(ImmutableBlockState.with(state, property, possibleValue)); - } - } - tempStates = newStates; - } - } - return tempStates; - } + @Nullable Property getProperty(String name); - public ImmutableBlockState getBlockState(CompoundTag nbt) { - ImmutableBlockState state = defaultState(); - for (Map.Entry entry : nbt.tags.entrySet()) { - Property property = this.variantProvider.getProperty(entry.getKey()); - if (property != null) { - try { - state = ImmutableBlockState.with(state, property, property.unpack(entry.getValue())); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to parse block state: " + entry.getKey(), e); - } - } - } - return state; - } + @NotNull Collection> properties(); - @Nullable - public Property getProperty(String name) { - return this.properties.get(name); - } + ImmutableBlockState defaultState(); - @NotNull - public Collection> properties() { - return this.properties.values(); - } + ImmutableBlockState getStateForPlacement(BlockPlaceContext context); - public final ImmutableBlockState defaultState() { - return this.defaultState; - } + interface Builder { - public ImmutableBlockState getStateForPlacement(BlockPlaceContext context) { - ImmutableBlockState state = defaultState(); - for (BiFunction placement : this.placements) { - state = placement.apply(context, state); - } - if (this.behavior instanceof AbstractBlockBehavior blockBehavior) { - state = blockBehavior.updateStateForPlacement(context, state); - } - return state; - } + Builder events(EnumMap>> events); - public abstract static class Builder { - protected final Key id; - protected Map> properties; - protected Map appearances; - protected Map variantMapper; - protected BlockSettings settings; - protected Map behavior; - protected LootTable lootTable; - protected EnumMap>> events; + Builder appearances(Map appearances); - protected Builder(Key id) { - this.id = id; - } + Builder behavior(Map behavior); - public Builder events(EnumMap>> events) { - this.events = events; - return this; - } + Builder lootTable(LootTable lootTable); - public Builder appearances(Map appearances) { - this.appearances = appearances; - return this; - } + Builder properties(Map> properties); - public Builder behavior(Map behavior) { - this.behavior = behavior; - return this; - } + Builder settings(BlockSettings settings); - public Builder lootTable(LootTable lootTable) { - this.lootTable = lootTable; - return this; - } + Builder variantMapper(Map variantMapper); - public Builder properties(Map> properties) { - this.properties = properties; - return this; - } - - public Builder settings(BlockSettings settings) { - this.settings = settings; - return this; - } - - public Builder variantMapper(Map variantMapper) { - this.variantMapper = variantMapper; - return this; - } - - public Map appearances() { - return appearances; - } - - public Map behavior() { - return behavior; - } - - public Key id() { - return id; - } - - public LootTable lootTable() { - return lootTable; - } - - public Map> properties() { - return properties; - } - - public BlockSettings settings() { - return settings; - } - - public Map variantMapper() { - return variantMapper; - } - - public abstract CustomBlock build(); + @NotNull CustomBlock build(); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlock.java index 4e5cca009..1e24acdc0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlock.java @@ -1,18 +1,16 @@ package net.momirealms.craftengine.core.block; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; -import java.util.EnumMap; import java.util.Map; -public class EmptyBlock extends CustomBlock { +public class EmptyBlock extends AbstractCustomBlock { public static EmptyBlock INSTANCE; public static ImmutableBlockState STATE; public EmptyBlock(Key id, Holder.Reference holder) { - super(id, holder, Map.of(), Map.of(), Map.of(), BlockSettings.of(), new EnumMap<>(EventTrigger.class), null, null); + super(id, holder, Map.of(), Map.of(), Map.of(), BlockSettings.of(), Map.of(), null, null); INSTANCE = this; STATE = defaultState(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java b/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java index 772468379..32c5890a9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java @@ -35,7 +35,7 @@ public class ImmutableBlockState extends BlockStateHolder { } public BlockBehavior behavior() { - return behavior; + return this.behavior; } public void setBehavior(BlockBehavior behavior) { @@ -43,7 +43,7 @@ public class ImmutableBlockState extends BlockStateHolder { } public BlockSettings settings() { - return settings; + return this.settings; } public void setSettings(BlockSettings settings) { @@ -116,16 +116,16 @@ public class ImmutableBlockState extends BlockStateHolder { } public CompoundTag getNbtToSave() { - if (tag == null) { - tag = toNbtToSave(propertiesNbt()); + if (this.tag == null) { + this.tag = toNbtToSave(propertiesNbt()); } - return tag; + return this.tag; } public CompoundTag toNbtToSave(CompoundTag properties) { CompoundTag tag = new CompoundTag(); tag.put("properties", properties); - tag.put("id", NBT.createString(owner.value().id().toString())); + tag.put("id", NBT.createString(this.owner.value().id().asString())); return tag; } @@ -140,7 +140,7 @@ public class ImmutableBlockState extends BlockStateHolder { @SuppressWarnings("unchecked") public List> getDrops(@NotNull ContextHolder.Builder builder, @NotNull World world, @Nullable Player player) { - CustomBlock block = owner.value(); + CustomBlock block = this.owner.value(); if (block == null) return List.of(); LootTable lootTable = (LootTable) block.lootTable(); if (lootTable == null) return List.of(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/InactiveCustomBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/InactiveCustomBlock.java index a733f2bfd..29ee6e7a0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/InactiveCustomBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/InactiveCustomBlock.java @@ -1,20 +1,18 @@ package net.momirealms.craftengine.core.block; import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import net.momirealms.sparrow.nbt.CompoundTag; -import java.util.EnumMap; import java.util.HashMap; import java.util.Map; -public class InactiveCustomBlock extends CustomBlock { +public class InactiveCustomBlock extends AbstractCustomBlock { private final Map cachedData = new HashMap<>(); public InactiveCustomBlock(Key id, Holder.Reference holder) { - super(id, holder, Map.of(), Map.of(), Map.of(), BlockSettings.of(), new EnumMap<>(EventTrigger.class), null, null); + super(id, holder, Map.of(), Map.of(), Map.of(), BlockSettings.of(), Map.of(), null, null); } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java b/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java index 00b9d4b49..f0174a4ad 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java @@ -24,7 +24,7 @@ public class UnsafeBlockStateMatcher { } public boolean matches(ImmutableBlockState state) { - if (!state.owner().value().id.equals(this.id)) { + if (!state.owner().value().id().equals(this.id)) { return false; } CustomBlock customBlock = state.owner().value(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java new file mode 100644 index 000000000..1ce3a53ef --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java @@ -0,0 +1,6 @@ +package net.momirealms.craftengine.core.block; + +import net.momirealms.craftengine.core.util.Key; + +public record VanillaBlock(Key type, String properties, int registryId) { +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/BlockBehaviors.java b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/BlockBehaviors.java index d75ffc494..610dbb221 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/BlockBehaviors.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/BlockBehaviors.java @@ -30,7 +30,7 @@ public class BlockBehaviors { Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE); BlockBehaviorFactory factory = BuiltInRegistries.BLOCK_BEHAVIOR_FACTORY.getValue(key); if (factory == null) { - throw new LocalizedResourceConfigException("warning.config.block.behavior.invalid_type", type.toString()); + throw new LocalizedResourceConfigException("warning.config.block.behavior.invalid_type", type); } return factory.create(block, map); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java index aa1cdf921..925b2bb87 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java @@ -5,9 +5,11 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; -import software.amazon.awssdk.services.s3.endpoints.internal.Value; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class LegacyItemModel { private final List modelsToGenerate; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java index 242149a45..010098123 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java @@ -10,7 +10,10 @@ import net.momirealms.craftengine.core.plugin.context.text.TextProvider; import net.momirealms.craftengine.core.plugin.context.text.TextProviders; import net.momirealms.craftengine.core.plugin.gui.GuiType; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.util.*; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.EnumUtils; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; import javax.annotation.Nullable; import java.util.List; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java index 1cc08eb6c..801e13667 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java @@ -6,8 +6,10 @@ import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.plugin.event.EventFunctions; -import net.momirealms.craftengine.core.util.*; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.WorldPosition; import java.util.ArrayList; diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/GsonHelper.java b/core/src/main/java/net/momirealms/craftengine/core/util/GsonHelper.java index 7dcb40ce1..6245e85d6 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/GsonHelper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/GsonHelper.java @@ -8,6 +8,7 @@ import java.io.BufferedWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.Map; public class GsonHelper { @@ -101,4 +102,16 @@ public class GsonHelper { throw new RuntimeException("Invalid JSON response: " + json, e); } } + + public static JsonElement combine(List jo) { + if (jo.size() == 1) { + return jo.get(0); + } else { + JsonArray ja = new JsonArray(); + for (JsonElement je : jo) { + ja.add(je); + } + return ja; + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java b/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java index fcceb235b..a60be053e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java @@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ListUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ListUtils.java new file mode 100644 index 000000000..7c8ef0ae0 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ListUtils.java @@ -0,0 +1,16 @@ +package net.momirealms.craftengine.core.util; + +import java.util.Collections; +import java.util.List; + +public final class ListUtils { + + private ListUtils() {} + + public static List compact(final List list) { + if (list.isEmpty()) return Collections.emptyList(); + if (list.size() == 1) return List.of(list.get(0)); + if (list.size() == 2) return List.of(list.get(0), list.get(1)); + return list; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java index b81e56ca0..0c0407385 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java @@ -1,9 +1,14 @@ package net.momirealms.craftengine.core.util; +import com.mojang.datafixers.util.Either; import net.momirealms.craftengine.core.plugin.locale.LocalizedException; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.function.Supplier; public final class ResourceConfigUtils { @@ -36,6 +41,50 @@ public final class ResourceConfigUtils { return s; } + @SuppressWarnings("unchecked") + public static Either> parseConfigAsEither(Object config, Function, T> converter) { + if (config instanceof Map) { + return Either.left(converter.apply((Map) config)); + } else if (config instanceof List list) { + return switch (list.size()) { + case 0 -> Either.right(Collections.emptyList()); + case 1 -> Either.left(converter.apply((Map) list.get(0))); + case 2 -> Either.right(List.of(converter.apply((Map) list.get(0)), converter.apply((Map) list.get(1)))); + default -> { + List result = new ArrayList<>(list.size()); + for (Object o : list) { + result.add(converter.apply((Map) o)); + } + yield Either.right(result); + } + }; + } else { + return Either.right(Collections.emptyList()); + } + } + + @SuppressWarnings("unchecked") + public static List parseConfigAsList(Object config, Function, T> converter) { + if (config instanceof Map) { + return List.of(converter.apply((Map) config)); + } else if (config instanceof List list) { + return switch (list.size()) { + case 0 -> Collections.emptyList(); + case 1 -> List.of(converter.apply((Map) list.get(0))); + case 2 -> List.of(converter.apply((Map) list.get(0)), converter.apply((Map) list.get(1))); + default -> { + List result = new ArrayList<>(list.size()); + for (Object o : list) { + result.add(converter.apply((Map) o)); + } + yield result; + } + }; + } else { + return Collections.emptyList(); + } + } + public static Object get(Map arguments, String... keys) { for (String key : keys) { Object value = arguments.get(key); From c6a0c0ae5d922903ef3748c73fbe53412b9d0466 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 20 May 2025 04:26:38 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E6=8F=90=E9=AB=98=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/configuration/blocks.yml | 14 +++--- .../bukkit/block/BlockEventListener.java | 2 +- .../bukkit/block/BukkitBlockManager.java | 2 +- .../bukkit/block/BukkitCustomBlock.java | 20 ++++----- .../furniture/BukkitFurnitureManager.java | 6 +-- .../bukkit/item/BukkitCustomItem.java | 9 ++-- .../item/behavior/BlockItemBehavior.java | 2 +- .../item/behavior/FurnitureItemBehavior.java | 2 +- .../item/listener/ItemEventListener.java | 2 +- .../plugin/network/PacketConsumers.java | 2 +- .../core/block/AbstractCustomBlock.java | 2 +- .../craftengine/core/block/CustomBlock.java | 4 +- .../entity/furniture/CustomFurniture.java | 11 ++--- .../core/item/AbstractCustomItem.java | 6 +-- .../core/item/AbstractItemManager.java | 2 +- .../craftengine/core/item/CustomItem.java | 4 +- .../{ => context}/event/EventConditions.java | 2 +- .../{ => context}/event/EventFunctions.java | 44 ++++--------------- .../{ => context}/event/EventTrigger.java | 2 +- 19 files changed, 54 insertions(+), 84 deletions(-) rename core/src/main/java/net/momirealms/craftengine/core/plugin/{ => context}/event/EventConditions.java (98%) rename core/src/main/java/net/momirealms/craftengine/core/plugin/{ => context}/event/EventFunctions.java (64%) rename core/src/main/java/net/momirealms/craftengine/core/plugin/{ => context}/event/EventTrigger.java (93%) diff --git a/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml b/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml index 4baf0dd0b..b979b00a7 100644 --- a/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml +++ b/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml @@ -64,14 +64,12 @@ items#misc: events: - on: right_click functions: - - type: run - functions: - - type: open_window - gui-type: anvil - - type: cancel_event - conditions: - - type: expression - expression: "!" + - type: open_window + gui-type: anvil + - type: cancel_event + conditions: + - type: expression + expression: "!" settings: template: - default:pickaxe_power/level_4 diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index 31b16f093..bc80b371d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -18,7 +18,7 @@ import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 5308d06ee..542b9b38e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -26,7 +26,7 @@ import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.ConfigParser; -import net.momirealms.craftengine.core.plugin.event.EventFunctions; +import net.momirealms.craftengine.core.plugin.context.event.EventFunctions; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index c9897a727..b6d0d7441 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -11,7 +11,7 @@ import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.registry.WritableRegistry; @@ -31,13 +31,13 @@ import java.util.*; public class BukkitCustomBlock extends AbstractCustomBlock { protected BukkitCustomBlock( - Key id, - Holder.Reference holder, - Map> properties, - Map appearances, - Map variantMapper, - BlockSettings settings, - @NotNull EnumMap>> events, + @NotNull Key id, + @NotNull Holder.Reference holder, + @NotNull Map> properties, + @NotNull Map appearances, + @NotNull Map variantMapper, + @NotNull BlockSettings settings, + @NotNull Map>> events, @Nullable Map behavior, @Nullable LootTable lootTable ) { @@ -158,14 +158,14 @@ public class BukkitCustomBlock extends AbstractCustomBlock { protected BlockSettings settings; protected Map behavior; protected LootTable lootTable; - protected EnumMap>> events; + protected Map>> events; public BuilderImpl(Key id) { this.id = id; } @Override - public Builder events(EnumMap>> events) { + public Builder events(Map>> events) { this.events = events; return this; } 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 5d35be647..621a03733 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 @@ -18,8 +18,8 @@ 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.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventFunctions; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventFunctions; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Key; @@ -217,7 +217,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { // get loot table LootTable lootTable = lootMap == null ? null : LootTable.fromMap(lootMap); - EnumMap>> events = EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")); + Map>> events = EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")); CustomFurniture furniture = new CustomFurniture(id, settings, placements, events, lootTable); byId.put(id, furniture); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java index fd7c32143..f117a6990 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java @@ -7,7 +7,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import org.bukkit.Material; @@ -16,6 +16,7 @@ import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; +import java.util.Map; public class BukkitCustomItem extends AbstractCustomItem { private final Material material; @@ -24,7 +25,7 @@ public class BukkitCustomItem extends AbstractCustomItem { List behaviors, List> modifiers, List> clientBoundModifiers, ItemSettings settings, - EnumMap>> events) { + Map>> events) { super(id, materialKey, behaviors, modifiers, clientBoundModifiers, settings, events); this.material = material; } @@ -58,7 +59,7 @@ public class BukkitCustomItem extends AbstractCustomItem { private Holder id; private Key materialKey; private final Material material; - private final EnumMap>> events = new EnumMap<>(EventTrigger.class); + private final Map>> events = new EnumMap<>(EventTrigger.class); private final List behaviors = new ArrayList<>(4); private final List> modifiers = new ArrayList<>(4); private final List> clientBoundModifiers = new ArrayList<>(4); @@ -124,7 +125,7 @@ public class BukkitCustomItem extends AbstractCustomItem { } @Override - public Builder events(EnumMap>> events) { + public Builder events(Map>> events) { this.events.putAll(events); return this; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java index 00fbf33cc..05edf3460 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java @@ -26,7 +26,7 @@ import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.Direction; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index 20773f4f1..4e8238e2d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -24,7 +24,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.Vec3d; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java index 183db3a06..f602e34e1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java @@ -17,7 +17,7 @@ import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.world.BlockHitResult; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index abd76f731..cb633c860 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -36,7 +36,7 @@ import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.network.*; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.*; diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java index cb3efd929..6c74b4ee9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractCustomBlock.java @@ -9,7 +9,7 @@ import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java index 2e3fb29a7..bbe3d21e7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java @@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.util.Key; import net.momirealms.sparrow.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; @@ -40,7 +40,7 @@ public interface CustomBlock { interface Builder { - Builder events(EnumMap>> events); + Builder events(Map>> events); Builder appearances(Map appearances); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java index 8d2d93885..e1602fd58 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java @@ -3,30 +3,27 @@ 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.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Optional; +import java.util.*; public class CustomFurniture { private final Key id; private final FurnitureSettings settings; private final EnumMap placements; private final AnchorType anyType; - private final EnumMap>> events; + private final Map>> events; @Nullable private final LootTable lootTable; public CustomFurniture(@NotNull Key id, @NotNull FurnitureSettings settings, @NotNull EnumMap placements, - @NotNull EnumMap>> events, + @NotNull Map>> events, @Nullable LootTable lootTable) { this.id = id; this.settings = settings; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java index 7d88df3ad..76e5c0d31 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java @@ -6,7 +6,7 @@ import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; @@ -23,7 +23,7 @@ public abstract class AbstractCustomItem implements CustomItem { protected final NetworkItemDataProcessor[] networkItemDataProcessors; protected final List behaviors; protected final ItemSettings settings; - protected final EnumMap>> events; + protected final Map>> events; protected final Item base; @SuppressWarnings("unchecked") @@ -32,7 +32,7 @@ public abstract class AbstractCustomItem implements CustomItem { List> modifiers, List> clientBoundModifiers, ItemSettings settings, - EnumMap>> events) { + Map>> events) { this.id = id; this.material = material; this.events = events; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index 2d746bd2b..9b0b5be71 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -15,7 +15,7 @@ import net.momirealms.craftengine.core.pack.model.select.TrimMaterialSelectPrope import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.ConfigParser; -import net.momirealms.craftengine.core.plugin.event.EventFunctions; +import net.momirealms.craftengine.core.plugin.context.event.EventFunctions; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.plugin.locale.TranslationManager; import net.momirealms.craftengine.core.registry.BuiltInRegistries; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java index 783506671..d21ff5693 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java @@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; @@ -70,7 +70,7 @@ public interface CustomItem extends BuildableItem { Builder settings(ItemSettings settings); - Builder events(EnumMap>> events); + Builder events(Map>> events); CustomItem build(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java similarity index 98% rename from core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java rename to core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java index b1c578046..5b6adc177 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.plugin.event; +package net.momirealms.craftengine.core.plugin.context.event; import net.momirealms.craftengine.core.plugin.context.Condition; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java similarity index 64% rename from core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java rename to core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java index 001d58f81..169593072 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.plugin.event; +package net.momirealms.craftengine.core.plugin.context.event; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.function.*; @@ -12,10 +12,7 @@ import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.ResourceKey; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class EventFunctions { @@ -45,31 +42,15 @@ public class EventFunctions { return factory.create(map); } - public static EnumMap>> parseEvents(Object eventsObj) { + public static Map>> parseEvents(Object eventsObj) { + if (eventsObj == null) return Map.of(); EnumMap>> events = new EnumMap<>(EventTrigger.class); if (eventsObj instanceof Map eventsSection) { Map eventsSectionMap = MiscUtils.castToMap(eventsSection, false); for (Map.Entry eventEntry : eventsSectionMap.entrySet()) { try { EventTrigger eventTrigger = EventTrigger.byName(eventEntry.getKey()); - if (eventEntry.getValue() instanceof List list) { - if (list.size() == 1) { - events.put(eventTrigger, List.of(EventFunctions.fromMap(MiscUtils.castToMap(list.get(0), false)))); - } else if (list.size() == 2) { - events.put(eventTrigger, List.of( - EventFunctions.fromMap(MiscUtils.castToMap(list.get(0), false)), - EventFunctions.fromMap(MiscUtils.castToMap(list.get(1), false)) - )); - } else { - List> eventsList = new ArrayList<>(); - for (Object event : list) { - eventsList.add(EventFunctions.fromMap(MiscUtils.castToMap(event, false))); - } - events.put(eventTrigger, eventsList); - } - } else if (eventEntry.getValue() instanceof Map eventSection) { - events.put(eventTrigger, List.of(EventFunctions.fromMap(MiscUtils.castToMap(eventSection, false)))); - } + events.put(eventTrigger, ResourceConfigUtils.parseConfigAsList(eventEntry.getValue(), EventFunctions::fromMap)); } catch (IllegalArgumentException e) { throw new LocalizedResourceConfigException("warning.config.event.invalid_trigger", eventEntry.getKey()); } @@ -78,24 +59,17 @@ public class EventFunctions { @SuppressWarnings("unchecked") List> eventsList = (List>) list; for (Map eventSection : eventsList) { - Object onObj = eventSection.get("on"); - if (onObj == null) { - throw new LocalizedResourceConfigException("warning.config.event.missing_trigger"); - } + String on = ResourceConfigUtils.requireNonEmptyStringOrThrow(eventSection.get("on"), "warning.config.event.missing_trigger"); try { - EventTrigger eventTrigger = EventTrigger.byName(onObj.toString()); + EventTrigger eventTrigger = EventTrigger.byName(on); if (eventSection.containsKey("type")) { Function function = EventFunctions.fromMap(eventSection); events.computeIfAbsent(eventTrigger, k -> new ArrayList<>(4)).add(function); } else if (eventSection.containsKey("functions")) { - @SuppressWarnings("unchecked") - List> functionList = (List>) eventSection.get("functions"); - for (Map function : functionList) { - events.computeIfAbsent(eventTrigger, k -> new ArrayList<>(4)).add(EventFunctions.fromMap(function)); - } + events.computeIfAbsent(eventTrigger, k -> new ArrayList<>(4)).add(Objects.requireNonNull(BuiltInRegistries.EVENT_FUNCTION_FACTORY.getValue(CommonFunctions.RUN)).create(eventSection)); } } catch (IllegalArgumentException e) { - throw new LocalizedResourceConfigException("warning.config.event.invalid_trigger", onObj.toString()); + throw new LocalizedResourceConfigException("warning.config.event.invalid_trigger", on); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventTrigger.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventTrigger.java similarity index 93% rename from core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventTrigger.java rename to core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventTrigger.java index 8c7060079..7e5f3c882 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventTrigger.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventTrigger.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.plugin.event; +package net.momirealms.craftengine.core.plugin.context.event; import java.util.HashMap; import java.util.Map; From fb98450207dca5871f83c1952112c7e3bdddcd39 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 20 May 2025 04:34:30 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9B=B4=E5=8A=A0?= =?UTF-8?q?=E6=96=B9=E4=BE=BF=E7=9A=84shift=E7=82=B9=E5=87=BB=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E7=89=A9=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/plugin/gui/GuiElement.java | 2 +- .../gui/category/ItemBrowserManagerImpl.java | 27 ++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiElement.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiElement.java index ae89d0b8e..c48418575 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiElement.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiElement.java @@ -11,7 +11,7 @@ import java.util.function.Function; public interface GuiElement { - static GuiElement EMPTY = GuiElement.constant(null, (e, c) -> c.cancel()); + GuiElement EMPTY = GuiElement.constant(null, (e, c) -> c.cancel()); @Nullable Item item(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java index 024b294df..2e9d1e6d0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java @@ -24,9 +24,11 @@ import java.util.*; @SuppressWarnings("DuplicatedCode") public class ItemBrowserManagerImpl implements ItemBrowserManager { + private static final String SHIFT_LEFT = "SHIFT_LEFT"; + private static final String SHIFT_RIGHT = "SHIFT_RIGHT"; private static final Set MOVE_TO_OTHER_INV = Set.of("SHIFT_LEFT", "SHIFT_RIGHT"); - private static final Set LEFT_CLICK = Set.of("LEFT", "SHIFT_LEFT"); - private static final Set RIGHT_CLICK = Set.of("RIGHT", "SHIFT_RIGHT"); + private static final Set LEFT_CLICK = Set.of("LEFT", SHIFT_LEFT); + private static final Set RIGHT_CLICK = Set.of("RIGHT", SHIFT_RIGHT); private static final Set MIDDLE_CLICK = Set.of("MIDDLE"); private static final Set DOUBLE_CLICK = Set.of("DOUBLE_CLICK"); private final CraftEngine plugin; @@ -258,11 +260,22 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager { if (item == null) return null; return new ItemWithAction(item, (e, c) -> { c.cancel(); - if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { - Item newItem = this.plugin.itemManager().createWrappedItem(e.item().id(), player); - newItem.count(newItem.maxStackSize()); - c.setItemOnCursor(newItem); - return; + if (player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION)) { + if (MIDDLE_CLICK.contains(c.type()) && c.itemOnCursor() == null) { + Item newItem = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + newItem.count(newItem.maxStackSize()); + c.setItemOnCursor(newItem); + return; + } + if (SHIFT_LEFT.equals(c.type())) { + player.giveItem(this.plugin.itemManager().createWrappedItem(e.item().id(), player)); + return; + } else if (SHIFT_RIGHT.equals(c.type())) { + Item newItem = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + newItem.count(newItem.maxStackSize()); + player.giveItem(newItem); + return; + } } if (LEFT_CLICK.contains(c.type())) { List> inRecipes = this.plugin.recipeManager().recipeByResult(itemId); From f8be28c9335650fb44bc9a3479ce1986b94cf9c9 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 20 May 2025 04:51:05 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=B6=E5=85=B7?= =?UTF-8?q?=E7=A1=AC=E7=A2=B0=E6=92=9E=E7=AE=B1=E4=BA=A4=E4=BA=92=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a350543e3..2ee29d431 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.54.2 +project_version=0.0.54.3 config_version=33 lang_version=13 project_group=net.momirealms @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.17 -nms_helper_version=0.65.24 +nms_helper_version=0.65.25 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23 From 2f215e2140167e6bb278657e9895918179ed1259 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 20 May 2025 05:34:37 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=89=93=E5=8C=85?= =?UTF-8?q?=E8=BF=9B=E6=8F=92=E4=BB=B6=E6=9C=AC=E4=BD=93=E7=9A=84adventure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit/loader/build.gradle.kts | 1 - .../main/resources/craft-engine.properties | 7 +- .../bukkit/block/BlockEventListener.java | 2 +- .../bukkit/block/BukkitCustomBlock.java | 7 +- .../furniture/BukkitFurnitureManager.java | 2 +- .../bukkit/item/BukkitCustomItem.java | 2 +- .../item/behavior/BlockItemBehavior.java | 2 +- .../item/behavior/FurnitureItemBehavior.java | 2 +- .../item/listener/ItemEventListener.java | 2 +- .../plugin/command/BukkitSenderFactory.java | 20 +-- .../plugin/network/PacketConsumers.java | 2 +- .../bukkit/util/ComponentUtils.java | 4 + core/build.gradle.kts | 3 +- .../core/block/AbstractCustomBlock.java | 2 +- .../craftengine/core/block/CustomBlock.java | 3 +- .../entity/furniture/CustomFurniture.java | 2 +- .../core/item/AbstractCustomItem.java | 2 +- .../craftengine/core/item/CustomItem.java | 3 +- .../craftengine/core/plugin/CraftEngine.java | 5 +- .../plugin/command/sender/SenderFactory.java | 5 +- .../core/plugin/dependency/Dependencies.java | 134 ++++++++++++++++-- 21 files changed, 164 insertions(+), 48 deletions(-) diff --git a/bukkit/loader/build.gradle.kts b/bukkit/loader/build.gradle.kts index 5085f47dc..f90ee42e0 100644 --- a/bukkit/loader/build.gradle.kts +++ b/bukkit/loader/build.gradle.kts @@ -21,7 +21,6 @@ dependencies { implementation(project(":bukkit:compatibility")) implementation(project(":bukkit:compatibility:legacy")) - implementation("net.kyori:adventure-platform-bukkit:${rootProject.properties["adventure_platform_version"]}") implementation("com.saicone.rtag:rtag-item:${rootProject.properties["rtag_version"]}") implementation("net.momirealms:sparrow-util:${rootProject.properties["sparrow_util_version"]}") implementation("net.momirealms:antigrieflib:${rootProject.properties["anti_grief_version"]}") diff --git a/bukkit/loader/src/main/resources/craft-engine.properties b/bukkit/loader/src/main/resources/craft-engine.properties index 9e875e126..d8ee70d9f 100644 --- a/bukkit/loader/src/main/resources/craft-engine.properties +++ b/bukkit/loader/src/main/resources/craft-engine.properties @@ -23,10 +23,9 @@ commons-io=${commons_io_version} commons-imaging=${commons_imaging_version} byte-buddy=${byte_buddy_version} snake-yaml=${snake_yaml_version} -adventure-text-minimessage=${adventure_bundle_version} -adventure-text-serializer-gson=${adventure_bundle_version} -adventure-text-serializer-json=${adventure_bundle_version} -adventure-text-serializer-json-legacy-impl=${adventure_bundle_version} +examination-api=1.3.0 +option=1.1.0 +adventure-api=${adventure_bundle_version} netty-codec-http=${netty_version} ahocorasick=${ahocorasick_version} lz4=${lz4_version} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index bc80b371d..436a2d9df 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -17,8 +17,8 @@ import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index b6d0d7441..443c63c44 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -10,8 +10,8 @@ import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.function.Function; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.function.Function; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.registry.WritableRegistry; @@ -26,7 +26,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; public class BukkitCustomBlock extends AbstractCustomBlock { 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 621a03733..64ea33f4b 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 @@ -17,9 +17,9 @@ import net.momirealms.craftengine.core.pack.Pack; 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.function.Function; 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.util.Key; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java index f117a6990..241646d22 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java @@ -6,8 +6,8 @@ import net.momirealms.craftengine.core.item.*; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.function.Function; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.function.Function; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import org.bukkit.Material; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java index 05edf3460..4f4f19cf8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java @@ -25,8 +25,8 @@ import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.Direction; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index 4e8238e2d..f42317250 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -23,8 +23,8 @@ import net.momirealms.craftengine.core.pack.Pack; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.Vec3d; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java index f602e34e1..3ac9d8823 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java @@ -16,8 +16,8 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.world.BlockHitResult; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitSenderFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitSenderFactory.java index a9a2ba020..4725c79eb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitSenderFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/BukkitSenderFactory.java @@ -1,8 +1,7 @@ package net.momirealms.craftengine.bukkit.plugin.command; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.ComponentUtils; @@ -18,11 +17,9 @@ import org.bukkit.entity.Player; import java.util.UUID; public class BukkitSenderFactory extends SenderFactory { - private final BukkitAudiences audiences; public BukkitSenderFactory(BukkitCraftEngine plugin) { super(plugin); - this.audiences = BukkitAudiences.create(plugin.bootstrap()); } @Override @@ -41,20 +38,18 @@ public class BukkitSenderFactory extends SenderFactory audience(sender).sendMessage(message)); + String legacy = LegacyComponentSerializer.legacySection().serialize(message); + plugin().scheduler().sync().run(() -> sender.sendMessage(legacy)); } } @@ -93,6 +88,5 @@ public class BukkitSenderFactory extends SenderFactory { protected abstract String name(T sender); - protected abstract Audience audience(T sender); - protected abstract void sendMessage(T sender, Component message); protected abstract Tristate permissionState(T sender, String node); @@ -44,7 +41,7 @@ public abstract class SenderFactory

{ } public Sender console() { - return console; + return this.console; } public Sender wrap(C sender) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java index 2499f83d8..c5c54940d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java @@ -200,37 +200,155 @@ public class Dependencies { List.of(Relocation.of("snakeyaml", "org{}yaml{}snakeyaml")) ); + public static final Dependency OPTION = new Dependency( + "option", + "net{}kyori", + "option", + "option", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ); + + public static final Dependency ADVENTURE_API = new Dependency( + "adventure-api", + "net{}kyori", + "adventure-api", + "adventure-api", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ); + + public static final Dependency ADVENTURE_KEY = new Dependency( + "adventure-key", + "net{}kyori", + "adventure-key", + "adventure-key", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; + + public static final Dependency EXAMINATION_API = new Dependency( + "examination-api", + "net{}kyori", + "examination-api", + "examination-api", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ); + + public static final Dependency EXAMINATION_STRING = new Dependency( + "examination-string", + "net{}kyori", + "examination-string", + "examination-string", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return EXAMINATION_API.getVersion(); + } + }; + public static final Dependency MINIMESSAGE = new Dependency( "adventure-text-minimessage", "net{}kyori", "adventure-text-minimessage", "adventure-text-minimessage", - List.of(Relocation.of("adventure", "net{}kyori{}adventure")) - ); + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; + + public static final Dependency TEXT_SERIALIZER_COMMONS = new Dependency( + "adventure-text-serializer-commons", + "net{}kyori", + "adventure-text-serializer-commons", + "adventure-text-serializer-commons", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; public static final Dependency TEXT_SERIALIZER_GSON = new Dependency( "adventure-text-serializer-gson", "net{}kyori", "adventure-text-serializer-gson", "adventure-text-serializer-gson", - List.of(Relocation.of("adventure", "net{}kyori{}adventure")) - ); + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; public static final Dependency TEXT_SERIALIZER_GSON_LEGACY = new Dependency( "adventure-text-serializer-json-legacy-impl", "net{}kyori", "adventure-text-serializer-json-legacy-impl", "adventure-text-serializer-json-legacy-impl", - List.of(Relocation.of("adventure", "net{}kyori{}adventure")) - ); + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; + + public static final Dependency TEXT_SERIALIZER_LEGACY = new Dependency( + "adventure-text-serializer-legacy", + "net{}kyori", + "adventure-text-serializer-legacy", + "adventure-text-serializer-legacy", + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; public static final Dependency TEXT_SERIALIZER_JSON = new Dependency( "adventure-text-serializer-json", "net{}kyori", "adventure-text-serializer-json", "adventure-text-serializer-json", - List.of(Relocation.of("adventure", "net{}kyori{}adventure")) - ); + List.of(Relocation.of("option", "net{}kyori{}option"), + Relocation.of("examination", "net{}kyori{}examination"), + Relocation.of("adventure", "net{}kyori{}adventure")) + ) { + @Override + public String getVersion() { + return ADVENTURE_API.getVersion(); + } + }; public static final Dependency AHO_CORASICK = new Dependency( "ahocorasick", From c7886892779e3c2aee2e6363a7147ab85663e207 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 21 May 2025 17:08:26 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=AE=B6=E5=85=B7?= =?UTF-8?q?=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../skript/effect/EffRemoveFurniture.java | 9 +- .../bukkit/api/BukkitAdaptors.java | 7 + .../bukkit/api/CraftEngineFurniture.java | 82 ++++--- .../bukkit/api/event/FurnitureBreakEvent.java | 9 +- .../api/event/FurnitureInteractEvent.java | 9 +- .../bukkit/api/event/FurniturePlaceEvent.java | 9 +- .../furniture/BukkitCustomFurniture.java | 74 ++++++ ...dedFurniture.java => BukkitFurniture.java} | 39 ++- .../furniture/BukkitFurnitureElement.java | 73 +++++- .../furniture/BukkitFurnitureManager.java | 228 ++++-------------- .../item/behavior/FurnitureItemBehavior.java | 10 +- .../item/listener/ItemEventListener.java | 9 +- .../plugin/network/PacketConsumers.java | 16 +- .../furniture/AbstractCustomFurniture.java | 80 ++++++ .../furniture/AbstractFurnitureElement.java | 8 +- .../furniture/AbstractFurnitureManager.java | 125 ++++++++++ .../entity/furniture/CustomFurniture.java | 93 +++---- .../core/entity/furniture/Furniture.java | 5 +- .../entity/furniture/FurnitureElement.java | 21 ++ .../entity/furniture/FurnitureManager.java | 6 + .../core/util/ResourceConfigUtils.java | 5 + gradle.properties | 12 +- gradle/wrapper/gradle-wrapper.properties | 2 +- server-mod/v1_20_1/build.gradle.kts | 2 +- server-mod/v1_20_5/build.gradle.kts | 2 +- server-mod/v1_21_5/build.gradle.kts | 2 +- 26 files changed, 585 insertions(+), 352 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java rename bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/{LoadedFurniture.java => BukkitFurniture.java} (93%) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java index 750dd937c..0e5b8885a 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java @@ -6,7 +6,8 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser; import ch.njol.util.Kleenean; 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.event.Event; import org.jetbrains.annotations.Nullable; @@ -23,9 +24,9 @@ public class EffRemoveFurniture extends Effect { protected void execute(Event e) { for (Entity entity : entities.getArray(e)) { if (CraftEngineFurniture.isFurniture(entity)) { - LoadedFurniture loadedFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity); - if (loadedFurniture != null) { - loadedFurniture.destroy(); + Furniture bukkitFurniture = CraftEngineFurniture.getLoadedFurnitureByBaseEntity(entity); + if (bukkitFurniture != null) { + bukkitFurniture.destroy(); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/BukkitAdaptors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/BukkitAdaptors.java index f11ae4be3..3986509cf 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/BukkitAdaptors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/BukkitAdaptors.java @@ -3,8 +3,11 @@ package net.momirealms.craftengine.bukkit.api; import net.momirealms.craftengine.bukkit.entity.BukkitEntity; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; 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.BukkitWorld; +import net.momirealms.craftengine.core.world.WorldPosition; +import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.entity.Entity; @@ -29,4 +32,8 @@ public final class BukkitAdaptors { public static BukkitBlockInWorld adapt(final Block block) { return new BukkitBlockInWorld(block); } + + public static Location toLocation(WorldPosition position) { + return LocationUtils.toLocation(position); + } } 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 aa9616867..38fbf9f3a 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 @@ -1,13 +1,14 @@ package net.momirealms.craftengine.bukkit.api; 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.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.entity.furniture.AnchorType; import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; +import net.momirealms.craftengine.core.entity.furniture.Furniture; import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.LootTable; @@ -48,7 +49,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @Nullable - public static LoadedFurniture place(Location location, Key furnitureId) { + public static Furniture place(Location location, Key furnitureId) { CustomFurniture furniture = byId(furnitureId); if (furniture == null) return null; return place(location, furnitureId, furniture.getAnyPlacement()); @@ -63,7 +64,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @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); if (furniture == null) return null; return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); @@ -78,7 +79,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @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); } @@ -92,7 +93,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @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); if (furniture == null) return null; return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); @@ -108,7 +109,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @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); } @@ -152,7 +153,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @Nullable - public static LoadedFurniture getLoadedFurnitureByBaseEntity(@NotNull Entity baseEntity) { + public static Furniture getLoadedFurnitureByBaseEntity(@NotNull Entity baseEntity) { return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntity.getEntityId()); } @@ -163,7 +164,7 @@ public final class CraftEngineFurniture { * @return the loaded furniture */ @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); if (baseEntityId == null) return null; return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntityId); @@ -172,107 +173,108 @@ public final class CraftEngineFurniture { /** * Removes furniture * - * @param furniture furniture base entity + * @param entity furniture base entity * @return success or not */ - public static boolean remove(@NotNull Entity furniture) { - if (!isFurniture(furniture)) return false; - LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId()); - if (loadedFurniture == null) return false; - loadedFurniture.destroy(); + public static boolean remove(@NotNull Entity entity) { + if (!isFurniture(entity)) return false; + BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entity.getEntityId()); + if (furniture == null) return false; + furniture.destroy(); return true; } /** * Removes furniture, with more options * - * @param furniture furniture base entity + * @param entity furniture base entity * @param dropLoot whether to drop loots * @param playSound whether to play break sound * @return success or not */ - public static boolean remove(@NotNull Entity furniture, + public static boolean remove(@NotNull Entity entity, boolean dropLoot, boolean playSound) { - if (!isFurniture(furniture)) return false; - LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId()); - if (loadedFurniture == null) return false; - remove(loadedFurniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound); + if (!isFurniture(entity)) return false; + BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entity.getEntityId()); + if (furniture == null) return false; + remove(furniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound); return true; } /** * Removes furniture, with more options * - * @param furniture furniture base entity + * @param entity furniture base entity * @param player the player who removes the furniture * @param dropLoot whether to drop loots * @param playSound whether to play break sound * @return success or not */ - public static boolean remove(@NotNull Entity furniture, + public static boolean remove(@NotNull Entity entity, @Nullable Player player, boolean dropLoot, boolean playSound) { - if (!isFurniture(furniture)) return false; - LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId()); - if (loadedFurniture == null) return false; - remove(loadedFurniture, player, dropLoot, playSound); + if (!isFurniture(entity)) return false; + Furniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entity.getEntityId()); + if (furniture == null) return false; + remove(furniture, player, dropLoot, playSound); return true; } /** * Removes furniture by providing furniture instance * - * @param loadedFurniture loaded furniture + * @param furniture loaded furniture * @param dropLoot whether to drop loots * @param playSound whether to play break sound */ - public static void remove(@NotNull LoadedFurniture loadedFurniture, + public static void remove(@NotNull Furniture furniture, boolean dropLoot, 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 * - * @param loadedFurniture loaded furniture + * @param furniture loaded furniture * @param player the player who removes the furniture * @param dropLoot whether to drop loots * @param playSound whether to play break sound */ - public static void remove(@NotNull LoadedFurniture loadedFurniture, + public static void remove(@NotNull Furniture furniture, @Nullable Player player, boolean dropLoot, 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 * - * @param loadedFurniture loaded furniture + * @param furniture loaded furniture * @param player the player who removes the furniture * @param dropLoot whether to drop loots * @param playSound whether to play break sound */ @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, boolean dropLoot, boolean playSound) { - Location location = loadedFurniture.dropLocation(); - loadedFurniture.destroy(); - LootTable lootTable = (LootTable) loadedFurniture.config().lootTable(); + if (!furniture.isValid()) return; + Location location = ((BukkitFurniture) furniture).dropLocation(); + furniture.destroy(); + LootTable lootTable = (LootTable) furniture.config().lootTable(); World world = new BukkitWorld(location.getWorld()); WorldPosition position = new WorldPosition(world, location.getX(), location.getY(), location.getZ()); if (dropLoot && lootTable != null) { ContextHolder.Builder builder = ContextHolder.builder() .withParameter(DirectContextParameters.POSITION, position) - .withParameter(DirectContextParameters.FURNITURE, loadedFurniture) - .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, loadedFurniture.extraData().item().orElse(null)); + .withParameter(DirectContextParameters.FURNITURE, furniture) + .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.extraData().item().orElse(null)); if (player != null) { builder.withParameter(DirectContextParameters.PLAYER, player); } @@ -282,7 +284,7 @@ public final class CraftEngineFurniture { } } if (playSound) { - world.playBlockSound(position, loadedFurniture.config().settings().sounds().breakSound()); + world.playBlockSound(position, furniture.config().settings().sounds().breakSound()); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureBreakEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureBreakEvent.java index 013a25e7a..204a8d8c1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureBreakEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureBreakEvent.java @@ -1,6 +1,7 @@ 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.entity.Player; import org.bukkit.event.Cancellable; @@ -11,10 +12,10 @@ import org.jetbrains.annotations.NotNull; public class FurnitureBreakEvent extends PlayerEvent implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); private boolean cancelled; - private final LoadedFurniture furniture; + private final BukkitFurniture furniture; public FurnitureBreakEvent(@NotNull Player player, - @NotNull LoadedFurniture furniture) { + @NotNull BukkitFurniture furniture) { super(player); this.furniture = furniture; } @@ -25,7 +26,7 @@ public class FurnitureBreakEvent extends PlayerEvent implements Cancellable { } @NotNull - public LoadedFurniture furniture() { + public Furniture furniture() { return this.furniture; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java index 053fa45f6..3600e70fd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java @@ -1,6 +1,7 @@ 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 org.bukkit.Location; import org.bukkit.entity.Player; @@ -12,12 +13,12 @@ import org.jetbrains.annotations.NotNull; public class FurnitureInteractEvent extends PlayerEvent implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); private boolean cancelled; - private final LoadedFurniture furniture; + private final BukkitFurniture furniture; private final InteractionHand hand; private final Location interactionPoint; public FurnitureInteractEvent(@NotNull Player player, - @NotNull LoadedFurniture furniture, + @NotNull BukkitFurniture furniture, @NotNull InteractionHand hand, @NotNull Location interactionPoint) { super(player); @@ -42,7 +43,7 @@ public class FurnitureInteractEvent extends PlayerEvent implements Cancellable { } @NotNull - public LoadedFurniture furniture() { + public Furniture furniture() { return this.furniture; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurniturePlaceEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurniturePlaceEvent.java index 5c373aa03..35862abb1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurniturePlaceEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurniturePlaceEvent.java @@ -1,6 +1,7 @@ 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 org.bukkit.Location; import org.bukkit.entity.Player; @@ -12,12 +13,12 @@ import org.jetbrains.annotations.NotNull; public class FurniturePlaceEvent extends PlayerEvent implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); private final Location location; - private final LoadedFurniture furniture; + private final BukkitFurniture furniture; private final InteractionHand hand; private boolean cancelled; public FurniturePlaceEvent(@NotNull Player player, - @NotNull LoadedFurniture furniture, + @NotNull BukkitFurniture furniture, @NotNull Location location, @NotNull InteractionHand hand) { super(player); @@ -32,7 +33,7 @@ public class FurniturePlaceEvent extends PlayerEvent implements Cancellable { } @NotNull - public LoadedFurniture furniture() { + public Furniture furniture() { return this.furniture; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java new file mode 100644 index 000000000..5f2d30270 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java @@ -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 placements, + @NotNull Map>> 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 placements; + private FurnitureSettings settings; + private Map>> 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 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>> events) { + this.events = events; + return this; + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java similarity index 93% rename from bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java rename to bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index daaeddaf6..b26ef3651 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -1,9 +1,13 @@ 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.nms.FastNMS; import net.momirealms.craftengine.bukkit.util.EntityUtils; 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.world.BukkitWorld; import net.momirealms.craftengine.core.entity.furniture.*; @@ -29,7 +33,7 @@ import java.io.IOException; import java.lang.ref.WeakReference; import java.util.*; -public class LoadedFurniture implements Furniture { +public class BukkitFurniture implements Furniture { private final Key id; private final CustomFurniture furniture; private final AnchorType anchorType; @@ -44,8 +48,8 @@ public class LoadedFurniture implements Furniture { // cache private final List fakeEntityIds; private final List entityIds; - private final Map hitBoxes = new HashMap<>(); - private final Map aabb = new HashMap<>(); + private final Map hitBoxes = new Int2ObjectArrayMap<>(); + private final Map aabb = new Int2ObjectArrayMap<>(); private final boolean minimized; private final boolean hasExternalModel; // seats @@ -55,7 +59,7 @@ public class LoadedFurniture implements Furniture { private Object cachedSpawnPacket; private Object cachedMinimizedSpawnPacket; - public LoadedFurniture(Entity baseEntity, + public BukkitFurniture(Entity baseEntity, CustomFurniture furniture, FurnitureExtraData extraData) { this.id = furniture.id(); @@ -66,8 +70,8 @@ public class LoadedFurniture implements Furniture { this.baseEntity = new WeakReference<>(baseEntity); this.furniture = furniture; this.minimized = furniture.settings().minimized(); - List fakeEntityIds = new ArrayList<>(); - List mainEntityIds = new ArrayList<>(); + List fakeEntityIds = new IntArrayList(); + List mainEntityIds = new IntArrayList(); mainEntityIds.add(this.baseEntityId); CustomFurniture.Placement placement = furniture.getPlacement(anchorType); @@ -84,19 +88,11 @@ public class LoadedFurniture implements Furniture { this.hasExternalModel = false; } - float yaw = this.location.getYaw(); - Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - yaw), 0).conjugate(); - - double x = location.getX(); - double y = location.getY(); - double z = location.getZ(); - + Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate(); List packets = new ArrayList<>(); List minimizedPackets = new ArrayList<>(); List colliders = new ArrayList<>(); - - World world = world(); - WorldPosition position = new WorldPosition(world, x, y, z, yaw, 0); + WorldPosition position = position(); Integer dyedColor = this.extraData.dyedColor().orElse(null); for (FurnitureElement element : placement.elements()) { int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); @@ -154,13 +150,8 @@ public class LoadedFurniture implements Furniture { } @Override - public Vec3d position() { - return new Vec3d(location.getX(), location.getY(), location.getZ()); - } - - @Override - public World world() { - return new BukkitWorld(this.location.getWorld()); + public WorldPosition position() { + return LocationUtils.toWorldPosition(this.location); } @NotNull @@ -170,7 +161,7 @@ public class LoadedFurniture implements Furniture { @NotNull public Entity baseEntity() { - Entity entity = baseEntity.get(); + Entity entity = this.baseEntity.get(); if (entity == null) { throw new RuntimeException("Base entity not found. It might be unloaded."); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java index e2d2a29f8..ab6c56129 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java @@ -7,6 +7,7 @@ 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.AbstractFurnitureElement; +import net.momirealms.craftengine.core.entity.furniture.FurnitureElement; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.Key; @@ -30,10 +31,10 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement { ItemDisplayContext transform, Vector3f scale, Vector3f translation, - Vector3f offset, + Vector3f position, Quaternionf rotation, boolean applyDyedColor) { - super(item, billboard, transform, scale, translation, offset, rotation, applyDyedColor); + super(item, billboard, transform, scale, translation, position, rotation, applyDyedColor); this.commonValues = new ArrayList<>(); ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.commonValues); ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.commonValues); @@ -67,4 +68,72 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement { ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), cachedValues); return cachedValues; } + + public static Builder builder() { + return new BuilderImpl(); + } + + public static class BuilderImpl implements Builder { + private boolean applyDyedColor; + private Key item; + private Billboard billboard; + private ItemDisplayContext transform; + private Vector3f scale; + private Vector3f translation; + private Vector3f position; + private Quaternionf rotation; + + @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); + } + } } 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 64ea33f4b..1a70f53c0 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 @@ -6,58 +6,45 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler; import net.momirealms.craftengine.bukkit.util.EntityUtils; +import net.momirealms.craftengine.bukkit.util.KeyUtils; import net.momirealms.craftengine.bukkit.util.LocationUtils; 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.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.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.util.Key; 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.world.WorldPosition; import org.bukkit.*; import org.bukkit.entity.*; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; import javax.annotation.Nullable; import java.io.IOException; -import java.nio.file.Path; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; public class BukkitFurnitureManager extends AbstractFurnitureManager { - public static final NamespacedKey FURNITURE_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_id")); - // DEPRECATED - // public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type")); - public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_extra_data")); - public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity")); - 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 final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY); + public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_EXTRA_DATA_KEY); + public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY); + public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY); + public static final NamespacedKey FURNITURE_COLLISION = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_COLLISION); public static Class COLLISION_ENTITY_CLASS = Interaction.class; public static Object NMS_COLLISION_ENTITY_TYPE = Reflections.instance$EntityType$INTERACTION; public static ColliderType COLLISION_ENTITY_TYPE = ColliderType.INTERACTION; private static BukkitFurnitureManager instance; private final BukkitCraftEngine plugin; - private final FurnitureParser furnitureParser; - private final Map furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f); - private final Map furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f); + private final Map furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f); + private final Map furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f); // Event listeners private final Listener dismountListener; private final FurnitureEventListener furnitureEventListener; @@ -67,9 +54,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } public BukkitFurnitureManager(BukkitCraftEngine plugin) { + super(plugin); instance = this; this.plugin = plugin; - this.furnitureParser = new FurnitureParser(); this.furnitureEventListener = new FurnitureEventListener(this); 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); } - public LoadedFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { + public BukkitFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { Optional optionalAnchorType = extraData.anchorType(); if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) { extraData.anchorType(furniture.getAnyPlacement()); @@ -101,128 +88,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { 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 section) { - if (byId.containsKey(id)) { - throw new LocalizedResourceConfigException("warning.config.furniture.duplicate", path, id); - } - - Map lootMap = MiscUtils.castToMap(section.get("loot"), true); - Map settingsMap = MiscUtils.castToMap(section.get("settings"), true); - Map placementMap = MiscUtils.castToMap(section.get("placement"), true); - if (placementMap == null) { - throw new LocalizedResourceConfigException("warning.config.furniture.missing_placement", path, id); - } - - EnumMap placements = new EnumMap<>(AnchorType.class); - - for (Map.Entry entry : placementMap.entrySet()) { - // anchor type - AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)); - Map placementArguments = MiscUtils.castToMap(entry.getValue(), true); - - Optional optionalLootSpawnOffset = Optional.ofNullable(placementArguments.get("loot-spawn-offset")).map(it -> MiscUtils.getAsVector3f(it, "loot-spawn-offset")); - - // furniture display elements - List elements = new ArrayList<>(); - List> elementConfigs = (List>) placementArguments.getOrDefault("elements", List.of()); - for (Map 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; - 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> hitboxConfigs = (List>) placementArguments.getOrDefault("hitboxes", List.of()); - List hitboxes = new ArrayList<>(); - for (Map config : hitboxConfigs) { - HitBox hitBox = HitBoxTypes.fromMap(config); - hitboxes.add(hitBox); - } - if (hitboxes.isEmpty() && externalModel.isEmpty()) { - hitboxes.add(InteractionHitBox.DEFAULT); - } - - // rules - Map 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 lootTable = lootMap == null ? null : LootTable.fromMap(lootMap); - Map>> events = EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")); - CustomFurniture furniture = new CustomFurniture(id, settings, placements, events, lootTable); - byId.put(id, furniture); - } - } - @Override public void delayedInit() { COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class; @@ -264,19 +129,29 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { @Nullable @Override - public LoadedFurniture loadedFurnitureByRealEntityId(int entityId) { + public BukkitFurniture loadedFurnitureByRealEntityId(int entityId) { return this.furnitureByRealEntityId.get(entityId); } @Override @Nullable - public LoadedFurniture loadedFurnitureByEntityId(int entityId) { + public BukkitFurniture loadedFurnitureByEntityId(int 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) { int id = entity.getEntityId(); - LoadedFurniture furniture = this.furnitureByRealEntityId.remove(id); + BukkitFurniture furniture = this.furnitureByRealEntityId.remove(id); if (furniture != null) { Location location = entity.getLocation(); 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; CustomFurniture customFurniture = optionalFurniture.get(); - LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); + BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); if (previous != null) return; 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); if (above1_20_1) { if (!preventChange) { - LoadedFurniture furniture = addNewFurniture(display, customFurniture); + BukkitFurniture furniture = addNewFurniture(display, customFurniture); furniture.initializeColliders(); for (Player player : display.getTrackedPlayers()) { this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); @@ -321,7 +196,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } } } else { - LoadedFurniture furniture = addNewFurniture(display, customFurniture); + BukkitFurniture furniture = addNewFurniture(display, customFurniture); for (Player player : display.getTrackedPlayers()) { this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player)); @@ -383,9 +258,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { Optional optionalFurniture = furnitureById(key); if (optionalFurniture.isPresent()) { CustomFurniture customFurniture = optionalFurniture.get(); - LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); + BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); if (previous != null) return; - LoadedFurniture furniture = addNewFurniture(display, customFurniture); + BukkitFurniture furniture = addNewFurniture(display, customFurniture); furniture.initializeColliders(); // safely do it here } } @@ -412,23 +287,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { return FurnitureExtraData.fromBytes(extraData); } -// private AnchorType getAnchorType(Entity baseEntity, 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) { + private synchronized BukkitFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture) { FurnitureExtraData extraData; try { extraData = getFurnitureExtraData(display); @@ -436,16 +295,21 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { extraData = FurnitureExtraData.builder().build(); plugin.logger().warn("Furniture extra data could not be loaded", e); } - LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, extraData); - this.furnitureByRealEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture); - for (int entityId : loadedFurniture.entityIds()) { - this.furnitureByEntityId.put(entityId, loadedFurniture); + BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, extraData); + this.furnitureByRealEntityId.put(bukkitFurniture.baseEntityId(), bukkitFurniture); + for (int entityId : bukkitFurniture.entityIds()) { + this.furnitureByEntityId.put(entityId, bukkitFurniture); } - for (Collider collisionEntity : loadedFurniture.collisionEntities()) { + for (Collider collisionEntity : bukkitFurniture.collisionEntities()) { 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) { @@ -458,7 +322,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER); if (baseFurniture == null) return; vehicle.remove(); - LoadedFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture); + BukkitFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture); if (furniture == null) { return; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index f42317250..7ce7603f6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -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.FurniturePlaceEvent; 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.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.DirectionUtils; @@ -134,7 +134,7 @@ public class FurnitureItemBehavior extends ItemBehavior { Item item = context.getItem(); - LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().place( + BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place( furnitureLocation.clone(), customFurniture, FurnitureExtraData.builder() .item(item.copyWithCount(1)) @@ -142,15 +142,15 @@ public class FurnitureItemBehavior extends ItemBehavior { .dyedColor(item.dyedColor().orElse(null)) .build(), false); - FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, loadedFurniture, furnitureLocation, context.getHand()); + FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand()); if (EventUtils.fireAndCheckCancel(placeEvent)) { - loadedFurniture.destroy(); + bukkitFurniture.destroy(); return InteractionResult.FAIL; } Cancellable dummy = Cancellable.dummy(); PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder() - .withParameter(DirectContextParameters.FURNITURE, loadedFurniture) + .withParameter(DirectContextParameters.FURNITURE, bukkitFurniture) .withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation)) .withParameter(DirectContextParameters.EVENT, dummy) .withParameter(DirectContextParameters.HAND, context.getHand()) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java index 3ac9d8823..abaf50b8d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/ItemEventListener.java @@ -121,7 +121,14 @@ public class ItemEventListener implements Listener { // interact block with items 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()); BlockPos pos = LocationUtils.toBlockPos(block.getLocation()); Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 949b9ae16..de40cc956 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -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.block.BukkitBlockManager; 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.item.behavior.FurnitureItemBehavior; import net.momirealms.craftengine.bukkit.nms.FastNMS; @@ -1489,7 +1489,7 @@ public class PacketConsumers { public static final TriConsumer PICK_ITEM_FROM_ENTITY = (user, event, packet) -> { try { 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; Player player = (Player) user.platformPlayer(); 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(); if (itemId == null) return; 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); if (entityType == Reflections.instance$EntityType$ITEM_DISPLAY) { // Furniture - LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId); + BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId); if (furniture != null) { user.entityPacketHandlers().computeIfAbsent(entityId, k -> new FurniturePacketHandler(furniture.fakeEntityIds())); user.sendPacket(furniture.spawnPacket((Player) user.platformPlayer()), false); @@ -1606,7 +1606,7 @@ public class PacketConsumers { } } else if (entityType == BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE) { // Cancel collider entity packet - LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId); + BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId); if (furniture != null) { event.setCancelled(true); user.entityPacketHandlers().put(entityId, FurnitureCollisionPacketHandler.INSTANCE); @@ -1670,7 +1670,7 @@ public class PacketConsumers { } else { entityId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet); } - LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId); + BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId); if (furniture == null) return; Object action = Reflections.field$ServerboundInteractPacket$action.get(packet); Object actionType = Reflections.method$ServerboundInteractPacket$Action$getType.invoke(action); @@ -1694,7 +1694,7 @@ public class PacketConsumers { // execute functions PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() .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.BREAK); @@ -1724,7 +1724,7 @@ public class PacketConsumers { // execute functions PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() .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);; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java new file mode 100644 index 000000000..d617a91ac --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java @@ -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 placements; + private final Map>> events; + @Nullable + private final LootTable lootTable; + + private final AnchorType anyType; + + protected AbstractCustomFurniture(@NotNull Key id, + @NotNull FurnitureSettings settings, + @NotNull Map placements, + @NotNull Map>> 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 function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) { + function.run(context); + } + } + + @Override + public Key id() { + return this.id; + } + + @Override + public Map 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); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java index 18cc2fa80..3b4863b0f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java @@ -12,7 +12,7 @@ public abstract class AbstractFurnitureElement implements FurnitureElement { private final ItemDisplayContext transform; private final Vector3f scale; private final Vector3f translation; - private final Vector3f offset; + private final Vector3f position; private final Quaternionf rotation; private final boolean applyDyedColor; @@ -21,7 +21,7 @@ public abstract class AbstractFurnitureElement implements FurnitureElement { ItemDisplayContext transform, Vector3f scale, Vector3f translation, - Vector3f offset, + Vector3f position, Quaternionf rotation, boolean applyDyedColor) { this.billboard = billboard; @@ -30,7 +30,7 @@ public abstract class AbstractFurnitureElement implements FurnitureElement { this.translation = translation; this.item = item; this.rotation = rotation; - this.offset = offset; + this.position = position; this.applyDyedColor = applyDyedColor; } @@ -71,6 +71,6 @@ public abstract class AbstractFurnitureElement implements FurnitureElement { @Override public Vector3f position() { - return offset; + return position; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java index c9839cb60..bb5c88cf0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java @@ -1,15 +1,40 @@ 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.MiscUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; import org.incendo.cloud.suggestion.Suggestion; +import org.joml.Vector3f; +import java.nio.file.Path; import java.util.*; public abstract class AbstractFurnitureManager implements FurnitureManager { protected final Map byId = new HashMap<>(); + private final CraftEngine plugin; + private final FurnitureParser furnitureParser; // Cached command suggestions private final List cachedSuggestions = new ArrayList<>(); + public AbstractFurnitureManager(CraftEngine plugin) { + this.plugin = plugin; + this.furnitureParser = new FurnitureParser(); + } + + @Override + public ConfigParser parser() { + return this.furnitureParser; + } + @Override public void delayedLoad() { this.initSuggestions(); @@ -37,4 +62,104 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { public void unload() { 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 section) { + if (byId.containsKey(id)) { + throw new LocalizedResourceConfigException("warning.config.furniture.duplicate", path, id); + } + + EnumMap placements = new EnumMap<>(AnchorType.class); + Map placementMap = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(section.get("placement"), "warning.config.furniture.missing_placement"), false); + for (Map.Entry entry : placementMap.entrySet()) { + // anchor type + AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)); + Map placementArguments = MiscUtils.castToMap(entry.getValue(), false); + Optional optionalLootSpawnOffset = Optional.ofNullable(placementArguments.get("loot-spawn-offset")).map(it -> MiscUtils.getAsVector3f(it, "loot-spawn-offset")); + // furniture display elements + List elements = new ArrayList<>(); + List> elementConfigs = (List>) placementArguments.getOrDefault("elements", List.of()); + for (Map 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; + 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 hitboxes = ResourceConfigUtils.parseConfigAsList(placementArguments.get("hitboxes"), HitBoxTypes::fromMap); + if (hitboxes.isEmpty() && externalModel.isEmpty()) { + hitboxes.add(defaultHitBox()); + } + + // rules + Map 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); + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java index caf7c4281..5357caabb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java @@ -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.function.Function; import net.momirealms.craftengine.core.util.Key; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; -public class CustomFurniture { - private final Key id; - private final FurnitureSettings settings; - private final EnumMap placements; - private final AnchorType anyType; - private final Map>> events; - @Nullable - private final LootTable lootTable; +// TODO 家具的设计存在问题。家具也应该存在不同的状态,而不是根据放置规则直接决定状态类型 +public interface CustomFurniture { - public CustomFurniture(@NotNull Key id, - @NotNull FurnitureSettings settings, - @NotNull EnumMap placements, - @NotNull Map>> 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); - } + void execute(PlayerOptionalContext context, EventTrigger trigger); - public void execute(PlayerOptionalContext context, EventTrigger trigger) { - for (Function function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) { - function.run(context); - } - } + Key id(); - public Key id() { - return id; - } + Map placements(); - public EnumMap placements() { - return placements; - } - - public FurnitureSettings settings() { - return settings; - } + FurnitureSettings settings(); @Nullable - public LootTable lootTable() { - return lootTable; + LootTable lootTable(); + + AnchorType getAnyPlacement(); + + boolean isAllowedPlacement(AnchorType anchorType); + + Placement getPlacement(AnchorType anchorType); + + interface Builder { + + Builder id(Key id); + + Builder placement(Map placements); + + Builder settings(FurnitureSettings settings); + + Builder lootTable(LootTable lootTable); + + Builder events(Map>> events); + + CustomFurniture build(); } - public AnchorType getAnyPlacement() { - return this.anyType; - } - - public boolean isAllowedPlacement(AnchorType anchorType) { - return placements.containsKey(anchorType); - } - - public Placement getPlacement(AnchorType anchorType) { - return placements.get(anchorType); - } - - public record Placement(FurnitureElement[] elements, - HitBox[] hitBoxes, - RotationRule rotationRule, - AlignmentRule alignmentRule, - Optional externalModel, - Optional dropOffset) { + record Placement(FurnitureElement[] elements, + HitBox[] hitBoxes, + RotationRule rotationRule, + AlignmentRule alignmentRule, + Optional externalModel, + Optional dropOffset) { } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java index fea19d1e0..f843c3911 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; @@ -13,9 +14,7 @@ import java.util.UUID; public interface Furniture { void initializeColliders(); - Vec3d position(); - - World world(); + WorldPosition position(); boolean isValid(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java index c730621e8..f997ce0fe 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java @@ -29,4 +29,25 @@ public interface FurnitureElement { Vector3f position(); void initPackets(int entityId, @NotNull WorldPosition position, @NotNull Quaternionf conjugated, @Nullable Integer dyedColor, Consumer 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(); + } } 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 50d4787c1..51c33827e 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 @@ -12,6 +12,12 @@ import java.util.Collection; import java.util.Optional; 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"; ConfigParser parser(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java index 0c0407385..338ed70c0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.util; import com.mojang.datafixers.util.Either; import net.momirealms.craftengine.core.plugin.locale.LocalizedException; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -15,6 +16,10 @@ public final class ResourceConfigUtils { private ResourceConfigUtils() {} + public static T getOrDefault(@Nullable O raw, Function function, T defaultValue) { + return raw != null ? function.apply(raw) : defaultValue; + } + public static T requireNonNullOrThrow(T obj, String node) { if (obj == null) throw new LocalizedResourceConfigException(node); diff --git a/gradle.properties b/gradle.properties index 2ee29d431..70296301e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -71,9 +71,9 @@ modmenu_version=13.0.3 cloth_version=17.0.144 # Proxy settings -#systemProp.socks.proxyHost=127.0.0.1 -#systemProp.socks.proxyPort=7890 -#systemProp.http.proxyHost=127.0.0.1 -#systemProp.http.proxyPort=7890 -#systemProp.https.proxyHost=127.0.0.1 -#systemProp.https.proxyPort=7890 \ No newline at end of file +systemProp.socks.proxyHost=127.0.0.1 +systemProp.socks.proxyPort=7890 +systemProp.http.proxyHost=127.0.0.1 +systemProp.http.proxyPort=7890 +systemProp.https.proxyHost=127.0.0.1 +systemProp.https.proxyPort=7890 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c6f003026..3c44eb1b6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME 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 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/server-mod/v1_20_1/build.gradle.kts b/server-mod/v1_20_1/build.gradle.kts index 0266dd510..c6e5910ba 100644 --- a/server-mod/v1_20_1/build.gradle.kts +++ b/server-mod/v1_20_1/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("java-library") 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 { diff --git a/server-mod/v1_20_5/build.gradle.kts b/server-mod/v1_20_5/build.gradle.kts index db31453d2..38964e5ad 100644 --- a/server-mod/v1_20_5/build.gradle.kts +++ b/server-mod/v1_20_5/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("java-library") 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 { diff --git a/server-mod/v1_21_5/build.gradle.kts b/server-mod/v1_21_5/build.gradle.kts index 617f52ce2..ef78707c3 100644 --- a/server-mod/v1_21_5/build.gradle.kts +++ b/server-mod/v1_21_5/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("java-library") 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 { From 7bcfbf9cfefdf7cabbd495cfc8959ce3ab83d6e4 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 21 May 2025 21:09:02 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E7=B1=BB=E5=9E=8B=E5=92=8C=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../skript/effect/EffRemoveFurniture.java | 1 - .../src/main/resources/translations/en.yml | 2 + .../src/main/resources/translations/zh_cn.yml | 2 + .../bukkit/api/CraftEngineFurniture.java | 2 +- .../bukkit/block/BukkitBlockManager.java | 33 +++++-- .../entity/furniture/BukkitFurniture.java | 4 - .../furniture/BukkitFurnitureManager.java | 2 +- .../projectile/BukkitProjectileManager.java | 2 +- .../item/behavior/FurnitureItemBehavior.java | 2 +- .../item/listener/DebugStickListener.java | 2 +- .../plugin/network/PacketConsumers.java | 8 +- .../plugin/user/BukkitServerPlayer.java | 9 +- .../bukkit/util/BlockStateUtils.java | 6 ++ .../bukkit/util/MaterialUtils.java | 2 +- .../craftengine/bukkit/world/BukkitWorld.java | 8 ++ .../craftengine/core/block/BlockManager.java | 7 +- .../core/block/BlockRegistryMirror.java | 8 +- .../core/block/BlockStateWrapper.java | 67 ++++++++++++++ .../core/block/ImmutableBlockState.java | 14 +-- .../core/block/PackedBlockState.java | 4 - ...nillaBlock.java => VanillaBlockState.java} | 2 +- .../core/block/properties/Property.java | 2 +- .../core/entity/furniture/Furniture.java | 2 - .../entity/furniture/FurnitureManager.java | 2 +- .../core/entity/player/Player.java | 2 + .../craftengine/core/font/Emoji.java | 3 +- .../craftengine/core/item/ItemManager.java | 2 +- .../core/item/recipe/StackedContents.java | 2 +- .../craftengine/core/loot/LootConditions.java | 1 + .../craftengine/core/loot/LootContext.java | 3 +- .../core/pack/host/impl/AlistHost.java | 2 +- .../core/plugin/context/ContextHolder.java | 2 +- .../context/condition/CommonConditions.java | 1 + .../context/condition/IsNullCondition.java | 38 ++++++++ .../plugin/context/event/EventConditions.java | 1 + .../plugin/context/event/EventFunctions.java | 2 + .../context/function/ActionBarFunction.java | 2 +- .../context/function/BreakBlockFunction.java | 53 +++++++++++ .../context/function/CommandFunction.java | 2 +- .../context/function/CommonFunctions.java | 2 + .../context/function/MessageFunction.java | 2 +- .../context/function/OpenWindowFunction.java | 2 +- .../context/function/PlaceBlockFunction.java | 87 +++++++++++++++++++ .../context/function/TitleFunction.java | 2 +- .../number/ExpressionNumberProvider.java | 12 +++ .../context/number/FixedNumberProvider.java | 13 ++- .../plugin/context/number/NumberProvider.java | 2 + .../context/number/NumberProviders.java | 4 + .../context/number/UniformNumberProvider.java | 5 ++ .../craftengine/core/registry/Holder.java | 2 +- .../core/registry/MappedRegistry.java | 2 +- .../craftengine/core/registry/Registry.java | 2 +- .../craftengine/core/util/MCUtils.java | 2 +- .../craftengine/core/world/World.java | 3 + .../chunk/storage/CompressionMethod.java | 2 +- .../core/world/chunk/storage/RegionFile.java | 2 +- .../core/world/collision/AABB.java | 2 +- gradle.properties | 12 +-- 58 files changed, 393 insertions(+), 76 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java delete mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/PackedBlockState.java rename core/src/main/java/net/momirealms/craftengine/core/block/{VanillaBlock.java => VanillaBlockState.java} (55%) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java index 0e5b8885a..5996a8ae7 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java @@ -6,7 +6,6 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser; import ch.njol.util.Kleenean; import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; -import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; import net.momirealms.craftengine.core.entity.furniture.Furniture; import org.bukkit.entity.Entity; import org.bukkit.event.Event; diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index 39ec93ddc..985333fdd 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -94,6 +94,7 @@ warning.config.condition.permission.missing_permission: "Issue found in warning.config.condition.equals.missing_value1: "Issue found in file - The config '' is missing the required 'value1' argument for 'equals' condition." warning.config.condition.equals.missing_value2: "Issue found in file - The config '' is missing the required 'value2' argument for 'equals' condition." warning.config.condition.expression.missing_expression: "Issue found in file - The config '' is missing the required 'expression' argument for 'expression' condition." +warning.config.condition.is_null.missing_argument: "Issue found in file - The config '' is missing the required 'argument' argument for 'is_null' condition." warning.config.structure.not_section: "Issue found in file - The config '' is expected to be a config section while it's actually a(n) ''." warning.config.image.duplicate: "Issue found in file - Duplicated image ''. Please check if there is the same configuration in other files." warning.config.image.missing_height: "Issue found in file - The image '' is missing the required 'height' argument." @@ -317,6 +318,7 @@ warning.config.function.message.missing_message: "Issue found in file Issue found in file - The config '' is missing the required 'gui-type' argument for 'open_window' function." warning.config.function.open_window.invalid_gui_type: "Issue found in file - The config '' is using an invalid gui type for 'open_window' function. Allowed types: []." warning.config.function.run.missing_functions: "Issue found in file - The config '' is missing the required 'functions' argument for 'run' function." +warning.config.function.place_block.missing_block_state: "Issue found in file - The config '' is missing the required 'block-state' argument for 'place_block' function." warning.config.selector.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for selector." warning.config.selector.invalid_type: "Issue found in file - The config '' is using an invalid selector type ''." warning.config.selector.invalid_target: "Issue found in file - The config '' is using an invalid selector target ''." diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index a1d692f6e..ab9ca80ab 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -94,6 +94,7 @@ warning.config.condition.permission.missing_permission: "在文件 在文件 中发现问题 - 配置项 '' 缺少 'equals' 条件必需的 'value1' 参数" warning.config.condition.equals.missing_value2: "在文件 中发现问题 - 配置项 '' 缺少 'equals' 条件必需的 'value2' 参数" warning.config.condition.expression.missing_expression: "在文件 中发现问题 - 配置项 '' 缺少 'expression' 条件必需的 'expression' 参数" +warning.config.condition.is_null.missing_argument: "在文件 发现问题 - 配置项 '' 缺少 'is_null' 条件的必需的 'argument' 参数." warning.config.structure.not_section: "在文件 发现问题 - 配置项 '' 应为配置段落 但实际类型为 ''" warning.config.image.duplicate: "在文件 发现问题 - 重复的图片配置 '' 请检查其他文件中是否存在相同配置" warning.config.image.missing_height: "在文件 发现问题 - 图片 '' 缺少必需的 'height' 参数" @@ -317,6 +318,7 @@ warning.config.function.message.missing_message: "在文件 中 warning.config.function.open_window.missing_gui_type: "在文件 中发现问题 - 配置项 '' 缺少 'open_window' 函数必需的 'gui-type' 参数" warning.config.function.open_window.invalid_gui_type: "在文件 中发现问题 - 配置项 '' 为 'open_window' 函数使用了无效的 GUI 类型 . 允许的类型: []。" warning.config.function.run.missing_functions: "在文件 中发现问题 - 配置项 '' 缺少 'run' 函数必需的 'functions' 参数" +warning.config.function.place_block.missing_block_state: "在文件 中发现问题 - 配置项 '' 缺少 'place_block' 函数必需的 'block-state' 参数." warning.config.selector.missing_type: "在文件 中发现问题 - 配置项 '' 缺少选择器必需的 'type' 参数" warning.config.selector.invalid_type: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器类型 ''" warning.config.selector.invalid_target: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器目标 ''" 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 38fbf9f3a..62d1ef3f5 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 @@ -1,7 +1,7 @@ package net.momirealms.craftengine.bukkit.api; -import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.nms.CollisionEntity; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 542b9b38e..4f3b93ee7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -40,8 +40,8 @@ import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.io.File; import java.lang.reflect.Field; import java.nio.file.Path; @@ -164,6 +164,21 @@ public class BukkitBlockManager extends AbstractBlockManager { } } + @Nullable + @Override + public BlockStateWrapper createPackedBlockState(String blockState) { + ImmutableBlockState state = BlockStateParser.deserialize(blockState); + if (state != null) { + return state.customBlockState(); + } + try { + BlockData blockData = Bukkit.createBlockData(blockState); + return BlockStateUtils.toPackedBlockState(blockData); + } catch (IllegalArgumentException e) { + return null; + } + } + @Nullable public Object getMinecraftBlockHolder(int stateId) { return stateId2BlockHolder.get(stateId); @@ -205,7 +220,7 @@ public class BukkitBlockManager extends AbstractBlockManager { } @Override - public Key getBlockOwnerId(PackedBlockState state) { + public Key getBlockOwnerId(BlockStateWrapper state) { return BlockStateUtils.getBlockOwnerIdFromState(state.handle()); } @@ -226,11 +241,11 @@ public class BukkitBlockManager extends AbstractBlockManager { private void initMirrorRegistry() { int size = RegistryUtils.currentBlockRegistrySize(); - PackedBlockState[] states = new PackedBlockState[size]; + BlockStateWrapper[] states = new BlockStateWrapper[size]; for (int i = 0; i < size; i++) { - states[i] = new PackedBlockState(BlockStateUtils.idToBlockState(i), i); + states[i] = BlockStateWrapper.create(BlockStateUtils.idToBlockState(i), i, BlockStateUtils.isVanillaBlock(i)); } - BlockRegistryMirror.init(states, new PackedBlockState(Reflections.instance$Blocks$STONE$defaultState, BlockStateUtils.blockStateToId(Reflections.instance$Blocks$STONE$defaultState))); + BlockRegistryMirror.init(states, BlockStateWrapper.vanilla(Reflections.instance$Blocks$STONE$defaultState, BlockStateUtils.blockStateToId(Reflections.instance$Blocks$STONE$defaultState))); } private void registerEmptyBlock() { @@ -363,7 +378,7 @@ public class BukkitBlockManager extends AbstractBlockManager { if (singleState) { properties = Map.of(); int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("id"), "warning.config.block.state.missing_real_id"), "id"); - VanillaBlock vanillaBlock = getVanillaBlock(id, stateSection); + VanillaBlockState vanillaBlock = getVanillaBlock(id, stateSection); appearances = Map.of("", vanillaBlock.registryId()); Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, vanillaBlock.type().value() + "_" + internalId); int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1); @@ -379,7 +394,7 @@ public class BukkitBlockManager extends AbstractBlockManager { Map appearance2BlockType = new HashMap<>(); for (Map.Entry appearanceEntry : MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("appearances"), "warning.config.block.state.missing_appearances"), false).entrySet()) { if (appearanceEntry.getValue() instanceof Map) { - VanillaBlock vanillaBlock = getVanillaBlock(id, MiscUtils.castToMap(appearanceEntry.getValue(), false)); + VanillaBlockState vanillaBlock = getVanillaBlock(id, MiscUtils.castToMap(appearanceEntry.getValue(), false)); appearances.put(appearanceEntry.getKey(), vanillaBlock.registryId()); appearance2BlockType.put(appearanceEntry.getKey(), vanillaBlock.type()); } @@ -449,7 +464,7 @@ public class BukkitBlockManager extends AbstractBlockManager { } @NotNull - private VanillaBlock getVanillaBlock(Key id, Map section) { + private VanillaBlockState getVanillaBlock(Key id, Map section) { // require state non null String vanillaBlockStateTag = ResourceConfigUtils.requireNonEmptyStringOrThrow(section.get("state"), "warning.config.block.state.missing_state"); // get its registry id @@ -476,7 +491,7 @@ public class BukkitBlockManager extends AbstractBlockManager { JsonElement combinedVariant = GsonHelper.combine(variants); this.blockStateOverrides.computeIfAbsent(blockId, k -> new HashMap<>()).put(propertyNBT, combinedVariant); this.tempVanillaBlockStateModels.put(vanillaBlockStateRegistryId, combinedVariant); - return new VanillaBlock(blockId, propertyNBT, vanillaBlockStateRegistryId); + return new VanillaBlockState(blockId, propertyNBT, vanillaBlockStateRegistryId); } private JsonObject getVariantModel(Map singleModelMap) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index b26ef3651..fb5e908b8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -1,7 +1,6 @@ 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.nms.FastNMS; @@ -9,15 +8,12 @@ import net.momirealms.craftengine.bukkit.util.EntityUtils; 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.world.BukkitWorld; import net.momirealms.craftengine.core.entity.furniture.*; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.ArrayUtils; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuaternionUtils; import net.momirealms.craftengine.core.util.VersionHelper; -import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.collision.AABB; import org.bukkit.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 1a70f53c0..4f8927967 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 @@ -22,9 +22,9 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; -import javax.annotation.Nullable; import java.io.IOException; import java.util.Collection; import java.util.List; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java index 3d3ad8f87..6bef2fecf 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java @@ -25,8 +25,8 @@ import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.world.EntitiesLoadEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index 7ce7603f6..3c49d8c86 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -2,8 +2,8 @@ package net.momirealms.craftengine.bukkit.item.behavior; import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptPlaceEvent; import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent; -import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.DirectionUtils; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java index ff87989ed..59ef9e2dd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java @@ -25,8 +25,8 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Map; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index de40cc956..e110d229a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -10,8 +10,8 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent; import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; -import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager; import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior; import net.momirealms.craftengine.bukkit.nms.FastNMS; @@ -39,7 +39,10 @@ import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.network.*; import net.momirealms.craftengine.core.util.*; -import net.momirealms.craftengine.core.world.*; +import net.momirealms.craftengine.core.world.BlockHitResult; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.EntityHitResult; +import net.momirealms.craftengine.core.world.WorldEvents; import net.momirealms.craftengine.core.world.chunk.Palette; import net.momirealms.craftengine.core.world.chunk.PalettedContainer; import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData; @@ -47,7 +50,6 @@ import net.momirealms.craftengine.core.world.chunk.packet.MCSection; import net.momirealms.craftengine.core.world.collision.AABB; import net.momirealms.sparrow.nbt.Tag; import org.bukkit.*; -import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 5e045570f..00d219bd8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -11,8 +11,8 @@ import net.momirealms.craftengine.bukkit.plugin.gui.CraftEngineInventoryHolder; import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.BlockSettings; +import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.PackedBlockState; import net.momirealms.craftengine.core.entity.player.GameMode; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.Player; @@ -405,7 +405,7 @@ public class BukkitServerPlayer extends Player { // instant break boolean custom = immutableBlockState != null; if (custom && getDestroyProgress(state, pos) >= 1f) { - PackedBlockState vanillaBlockState = immutableBlockState.vanillaBlockState(); + BlockStateWrapper vanillaBlockState = immutableBlockState.vanillaBlockState(); // if it's not an instant break on client side, we should resend level event if (vanillaBlockState != null && getDestroyProgress(vanillaBlockState.handle(), pos) < 1f) { Object levelEventPacket = FastNMS.INSTANCE.constructor$ClientboundLevelEventPacket( @@ -613,6 +613,11 @@ public class BukkitServerPlayer extends Player { } } + @Override + public void breakBlock(int x, int y, int z) { + platformPlayer().breakBlock(new Location(platformPlayer().getWorld(), x, y, z).getBlock()); + } + private void broadcastDestroyProgress(org.bukkit.entity.Player player, BlockPos hitPos, Object blockPos, int stage) { Object packet = FastNMS.INSTANCE.constructor$ClientboundBlockDestructionPacket(Integer.MAX_VALUE - entityID(), blockPos, stage); for (org.bukkit.entity.Player other : player.getWorld().getPlayers()) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java index a5d8d4446..6e167553e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java @@ -33,6 +33,12 @@ public class BlockStateUtils { hasInit = true; } + public static BlockStateWrapper toPackedBlockState(BlockData blockData) { + Object state = blockDataToBlockState(blockData); + int id = blockStateToId(state); + return BlockStateWrapper.create(state, id, isVanillaBlock(id)); + } + public static boolean isCorrectTool(@NotNull ImmutableBlockState state, @Nullable Item itemInHand) { BlockSettings settings = state.settings(); if (settings.requireCorrectTool()) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MaterialUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MaterialUtils.java index f6cc84aa0..0ef3c5caf 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MaterialUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MaterialUtils.java @@ -4,8 +4,8 @@ import net.momirealms.craftengine.core.util.Key; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.Registry; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Locale; import java.util.Objects; import java.util.Optional; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java index 1554d3d79..4314a2fda 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.world; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.ItemUtils; +import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; @@ -95,4 +96,11 @@ public class BukkitWorld implements World { public long time() { return platformWorld().getTime(); } + + @Override + public void setBlockAt(int x, int y, int z, BlockStateWrapper blockState, int flags) { + Object worldServer = serverWorld(); + Object blockPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z); + FastNMS.INSTANCE.method$LevelWriter$setBlock(worldServer, blockPos, blockState.handle(), flags); + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java index 208355f1a..0319ecfd9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java @@ -8,8 +8,8 @@ import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.util.Key; import org.incendo.cloud.suggestion.Suggestion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Map; import java.util.Optional; @@ -36,11 +36,14 @@ public interface BlockManager extends Manageable, ModelGenerator { int availableAppearances(Key blockType); - Key getBlockOwnerId(PackedBlockState state); + Key getBlockOwnerId(BlockStateWrapper state); @NotNull ImmutableBlockState getImmutableBlockStateUnsafe(int stateId); @Nullable ImmutableBlockState getImmutableBlockState(int stateId); + + @Nullable + BlockStateWrapper createPackedBlockState(String blockState); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockRegistryMirror.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockRegistryMirror.java index f93bf3a57..72cb6de1c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockRegistryMirror.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockRegistryMirror.java @@ -1,15 +1,15 @@ package net.momirealms.craftengine.core.block; public class BlockRegistryMirror { - private static PackedBlockState[] customBlockStates; - private static PackedBlockState stoneState; + private static BlockStateWrapper[] customBlockStates; + private static BlockStateWrapper stoneState; - public static void init(PackedBlockState[] states, PackedBlockState state) { + public static void init(BlockStateWrapper[] states, BlockStateWrapper state) { customBlockStates = states; stoneState = state; } - public static PackedBlockState stateByRegistryId(int vanillaId) { + public static BlockStateWrapper stateByRegistryId(int vanillaId) { if (vanillaId < 0) return stoneState; return customBlockStates[vanillaId]; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java new file mode 100644 index 000000000..319a105af --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java @@ -0,0 +1,67 @@ +package net.momirealms.craftengine.core.block; + +public interface BlockStateWrapper { + + Object handle(); + + int registryId(); + + boolean isVanillaBlock(); + + static BlockStateWrapper vanilla(Object handle, int registryId) { + return new VanillaBlockState(handle, registryId); + } + + static BlockStateWrapper custom(Object handle, int registryId) { + return new CustomBlockState(handle, registryId); + } + + static BlockStateWrapper create(Object handle, int registryId, boolean isVanillaBlock) { + if (isVanillaBlock) return new VanillaBlockState(handle, registryId); + else return new CustomBlockState(handle, registryId); + } + + abstract class AbstractBlockState implements BlockStateWrapper { + protected final Object handle; + protected final int registryId; + + public AbstractBlockState(Object handle, int registryId) { + this.handle = handle; + this.registryId = registryId; + } + + @Override + public Object handle() { + return this.handle; + } + + @Override + public int registryId() { + return this.registryId; + } + } + + class VanillaBlockState extends AbstractBlockState { + + public VanillaBlockState(Object handle, int registryId) { + super(handle, registryId); + } + + @Override + public boolean isVanillaBlock() { + return true; + } + } + + class CustomBlockState extends AbstractBlockState { + + public CustomBlockState(Object handle, int registryId) { + super(handle, registryId); + } + + @Override + public boolean isVanillaBlock() { + return false; + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java b/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java index 32c5890a9..68747718d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java @@ -14,14 +14,14 @@ import net.momirealms.sparrow.nbt.CompoundTag; import net.momirealms.sparrow.nbt.NBT; import net.momirealms.sparrow.nbt.Tag; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; public class ImmutableBlockState extends BlockStateHolder { private CompoundTag tag; - private PackedBlockState customBlockState; - private PackedBlockState vanillaBlockState; + private BlockStateWrapper customBlockState; + private BlockStateWrapper vanillaBlockState; private BlockBehavior behavior; private Integer hashCode; @@ -81,19 +81,19 @@ public class ImmutableBlockState extends BlockStateHolder { return settings.pushReaction; } - public PackedBlockState customBlockState() { + public BlockStateWrapper customBlockState() { return this.customBlockState; } - public PackedBlockState vanillaBlockState() { + public BlockStateWrapper vanillaBlockState() { return this.vanillaBlockState; } - public void setCustomBlockState(@NotNull PackedBlockState customBlockState) { + public void setCustomBlockState(@NotNull BlockStateWrapper customBlockState) { this.customBlockState = customBlockState; } - public void setVanillaBlockState(@NotNull PackedBlockState vanillaBlockState) { + public void setVanillaBlockState(@NotNull BlockStateWrapper vanillaBlockState) { this.vanillaBlockState = vanillaBlockState; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/PackedBlockState.java b/core/src/main/java/net/momirealms/craftengine/core/block/PackedBlockState.java deleted file mode 100644 index 9abfb6db8..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/block/PackedBlockState.java +++ /dev/null @@ -1,4 +0,0 @@ -package net.momirealms.craftengine.core.block; - -public record PackedBlockState(Object handle, int registryId) { -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlockState.java similarity index 55% rename from core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java rename to core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlockState.java index 1ce3a53ef..9e811011f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/VanillaBlockState.java @@ -2,5 +2,5 @@ package net.momirealms.craftengine.core.block; import net.momirealms.craftengine.core.util.Key; -public record VanillaBlock(Key type, String properties, int registryId) { +public record VanillaBlockState(Key type, String properties, int registryId) { } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java index a61d33e00..84bbfda65 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java @@ -5,8 +5,8 @@ import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.HorizontalDirection; import net.momirealms.sparrow.nbt.Tag; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java index f843c3911..691092619 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java @@ -2,8 +2,6 @@ package net.momirealms.craftengine.core.entity.furniture; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; 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 51c33827e..2a31d46de 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 @@ -6,8 +6,8 @@ import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.world.WorldPosition; import org.incendo.cloud.suggestion.Suggestion; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Optional; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index bb50aec7d..70e614cd2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -36,6 +36,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract void abortMiningBlock(); + public abstract void breakBlock(int x, int y, int z); + public abstract double getCachedInteractionRange(); public abstract void onSwingHand(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/Emoji.java b/core/src/main/java/net/momirealms/craftengine/core/font/Emoji.java index 81a51429b..8ce6168d8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/Emoji.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/Emoji.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.core.font; -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; + import java.util.List; public class Emoji { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java index 655270533..8a100cc33 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java @@ -11,8 +11,8 @@ import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import org.incendo.cloud.suggestion.Suggestion; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.*; public interface ItemManager extends Manageable, ModelGenerator { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/StackedContents.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/StackedContents.java index c6a483ac6..15442f74c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/StackedContents.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/StackedContents.java @@ -4,8 +4,8 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Reference2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.BitSet; import java.util.List; diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java index 43ca9b0aa..9ea20df82 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java @@ -33,6 +33,7 @@ public class LootConditions { register(CommonConditions.PERMISSION, new PermissionCondition.FactoryImpl<>()); register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>()); register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>()); + register(CommonConditions.IS_NULL, new IsNullCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/LootContext.java b/core/src/main/java/net/momirealms/craftengine/core/loot/LootContext.java index 5e3c9092d..8ca3cf5e2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/LootContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/LootContext.java @@ -5,8 +5,7 @@ import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.world.World; import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; public class LootContext extends PlayerOptionalContext { private final World world; diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java index 2ae5335c1..26a20125b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java @@ -10,8 +10,8 @@ import net.momirealms.craftengine.core.pack.host.ResourcePackHosts; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.locale.LocalizedException; import net.momirealms.craftengine.core.util.*; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/ContextHolder.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/ContextHolder.java index 037b53e39..5e54f2ea8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/ContextHolder.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/ContextHolder.java @@ -1,8 +1,8 @@ package net.momirealms.craftengine.core.plugin.context; import com.google.common.collect.ImmutableMap; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java index 600d204c8..ad64b2ec5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java @@ -20,4 +20,5 @@ public final class CommonConditions { public static final Key PERMISSION = Key.from("craftengine:permission"); public static final Key EQUALS = Key.from("craftengine:equals"); public static final Key EXPRESSION = Key.from("craftengine:expression"); + public static final Key IS_NULL = Key.from("craftengine:is_null"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java new file mode 100644 index 000000000..7ea6d60cb --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java @@ -0,0 +1,38 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.ContextKey; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.Map; +import java.util.Optional; + +public class IsNullCondition implements Condition { + private final ContextKey key; + + public IsNullCondition(ContextKey key) { + this.key = key; + } + + @Override + public Key type() { + return CommonConditions.IS_NULL; + } + + @Override + public boolean test(CTX ctx) { + Optional optional = ctx.getOptionalParameter(this.key); + return optional.isPresent(); + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + String argument = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("argument"), "warning.config.condition.is_null.missing_argument"); + return new IsNullCondition<>(ContextKey.chain(argument)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java index 5b6adc177..e7eea8bc8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java @@ -31,6 +31,7 @@ public class EventConditions { register(CommonConditions.PERMISSION, new PermissionCondition.FactoryImpl<>()); register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>()); register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>()); + register(CommonConditions.IS_NULL, new IsNullCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java index 169593072..c056c1c7e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java @@ -24,6 +24,8 @@ public class EventFunctions { register(CommonFunctions.OPEN_WINDOW, new OpenWindowFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.CANCEL_EVENT, new CancelEventFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.RUN, new RunFunction.FactoryImpl<>(EventFunctions::fromMap, EventConditions::fromMap)); + register(CommonFunctions.PLACE_BLOCK, new PlaceBlockFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.BREAK_BLOCK, new BreakBlockFunction.FactoryImpl<>(EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java index 1db327924..4e04272f7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ActionBarFunction.java @@ -10,8 +10,8 @@ import net.momirealms.craftengine.core.plugin.context.text.TextProviders; import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java new file mode 100644 index 000000000..97d5fc4b4 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java @@ -0,0 +1,53 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MCUtils; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class BreakBlockFunction extends AbstractConditionalFunction { + private final NumberProvider x; + private final NumberProvider y; + private final NumberProvider z; + + public BreakBlockFunction(NumberProvider x, NumberProvider y, NumberProvider z, List> predicates) { + super(predicates); + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public void runInternal(CTX ctx) { + Optional optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + optionalPlayer.ifPresent(player -> player.breakBlock(MCUtils.fastFloor(x.getDouble(ctx)), MCUtils.fastFloor(y.getDouble(ctx)), MCUtils.fastFloor(z.getDouble(ctx)))); + } + + @Override + public Key type() { + return CommonFunctions.BREAK_BLOCK; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); + return new BreakBlockFunction<>(x, y, z, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java index 0b203a447..61a4137c4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommandFunction.java @@ -12,8 +12,8 @@ import net.momirealms.craftengine.core.plugin.context.text.TextProviders; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java index f0df7a51c..4e7b764b4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java @@ -16,9 +16,11 @@ public final class CommonFunctions { public static final Key POTION_EFFECT = Key.of("craftengine:potion_effect"); public static final Key BREAK_BLOCK = Key.of("craftengine:break_block"); public static final Key CANCEL_EVENT = Key.of("craftengine:cancel_event"); + public static final Key PLACE_BLOCK = Key.of("craftengine:place_block"); public static final Key FOOD = Key.of("craftengine:food"); public static final Key SATURATION = Key.of("craftengine:saturation"); public static final Key MONEY = Key.of("craftengine:money"); public static final Key OXYGEN = Key.of("craftengine:oxygen"); public static final Key MINE_RADIUS = Key.of("craftengine:mine_radius"); + public static final Key DROP_LOOT = Key.of("craftengine:drop_loot"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java index 1b4f2ddbd..eeee93a4f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/MessageFunction.java @@ -11,8 +11,8 @@ import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java index 010098123..53dd47587 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java @@ -14,8 +14,8 @@ import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.EnumUtils; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; import java.util.Locale; import java.util.Map; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java new file mode 100644 index 000000000..2c0daf916 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java @@ -0,0 +1,87 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.block.BlockStateWrapper; +import net.momirealms.craftengine.core.block.UpdateOption; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class PlaceBlockFunction extends AbstractConditionalFunction { + private final DelayedInitBlockState delayedInitBlockState; + private final NumberProvider x; + private final NumberProvider y; + private final NumberProvider z; + private final NumberProvider updateFlags; + + public PlaceBlockFunction(DelayedInitBlockState delayedInitBlockState, NumberProvider x, NumberProvider y, NumberProvider z, NumberProvider updateFlags, List> predicates) { + super(predicates); + this.delayedInitBlockState = delayedInitBlockState; + this.x = x; + this.y = y; + this.z = z; + this.updateFlags = updateFlags; + } + + @Override + public void runInternal(CTX ctx) { + Optional optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION); + if (optionalWorldPosition.isPresent()) { + World world = optionalWorldPosition.get().world(); + world.setBlockAt(MCUtils.fastFloor(this.x.getDouble(ctx)), MCUtils.fastFloor(this.y.getDouble(ctx)), MCUtils.fastFloor(this.z.getDouble(ctx)), this.delayedInitBlockState.getState(), this.updateFlags.getInt(ctx)); + } + } + + @Override + public Key type() { + return CommonFunctions.PLACE_BLOCK; + } + + public static class DelayedInitBlockState { + private final String state; + private BlockStateWrapper packedBlockState; + + public DelayedInitBlockState(String state) { + this.state = state; + } + + public BlockStateWrapper getState() { + if (this.packedBlockState == null) { + this.packedBlockState = CraftEngine.instance().blockManager().createPackedBlockState(state); + if (this.packedBlockState == null) { + CraftEngine.instance().logger().warn("Could not create block state: " + this.state); + } + } + return this.packedBlockState; + } + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + String state = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("block-state"), "warning.config.function.place_block.missing_block_state"); + DelayedInitBlockState delayedInitBlockState = new DelayedInitBlockState(state); + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); + NumberProvider flags = Optional.ofNullable(arguments.get("update-flags")).map(NumberProviders::fromObject).orElse(NumberProviders.direct(UpdateOption.UPDATE_ALL.flags())); + return new PlaceBlockFunction<>(delayedInitBlockState, x, y, z, flags, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java index 6d55589ae..28900c5a1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TitleFunction.java @@ -11,8 +11,8 @@ import net.momirealms.craftengine.core.plugin.context.text.TextProvider; import net.momirealms.craftengine.core.plugin.context.text.TextProviders; import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/ExpressionNumberProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/ExpressionNumberProvider.java index 6428df308..43bf33fcf 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/ExpressionNumberProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/ExpressionNumberProvider.java @@ -31,6 +31,18 @@ public class ExpressionNumberProvider implements NumberProvider { } } + @Override + public double getDouble(Context context) { + Component resultComponent = AdventureHelper.customMiniMessage().deserialize(this.expr, context.tagResolvers()); + String resultString = AdventureHelper.plainTextContent(resultComponent); + Expression expression = new Expression(resultString); + try { + return expression.evaluate().getNumberValue().doubleValue(); + } catch (EvaluationException | ParseException e) { + throw new RuntimeException("Invalid expression: " + this.expr + " -> " + resultString + " -> Cannot parse", e); + } + } + @Override public Key type() { return NumberProviders.EXPRESSION; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/FixedNumberProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/FixedNumberProvider.java index 3bbf7729f..b4662a547 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/FixedNumberProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/FixedNumberProvider.java @@ -10,14 +10,19 @@ import java.util.Map; public class FixedNumberProvider implements NumberProvider { public static final FactoryImpl FACTORY = new FactoryImpl(); - private final float value; + private final double value; - public FixedNumberProvider(float value) { + public FixedNumberProvider(double value) { this.value = value; } @Override public float getFloat(Context context) { + return (float) this.value; + } + + @Override + public double getDouble(Context context) { return this.value; } @@ -32,12 +37,12 @@ public class FixedNumberProvider implements NumberProvider { public NumberProvider create(Map arguments) { String plainOrExpression = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value"), "warning.config.number.fixed.missing_value"); try { - float value = Float.parseFloat(plainOrExpression); + double value = Double.parseDouble(plainOrExpression); return new FixedNumberProvider(value); } catch (NumberFormatException e) { Expression expression = new Expression(plainOrExpression); try { - return new FixedNumberProvider(expression.evaluate().getNumberValue().floatValue()); + return new FixedNumberProvider(expression.evaluate().getNumberValue().doubleValue()); } catch (Exception e1) { throw new LocalizedResourceConfigException("warning.config.number.fixed.invalid_value", e1, plainOrExpression); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProvider.java index 93cdd64a0..9ea8a03d1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProvider.java @@ -7,6 +7,8 @@ public interface NumberProvider { float getFloat(Context context); + double getDouble(Context context); + default int getInt(Context context) { return Math.round(this.getFloat(context)); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProviders.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProviders.java index 8baef2d0b..2d7fb1591 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProviders.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/NumberProviders.java @@ -41,6 +41,10 @@ public class NumberProviders { return functions; } + public static NumberProvider direct(double value) { + return new FixedNumberProvider(value); + } + public static NumberProvider fromMap(Map map) { String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.number.missing_type"); Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/UniformNumberProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/UniformNumberProvider.java index 62d7c4ddc..dca387d0e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/UniformNumberProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/number/UniformNumberProvider.java @@ -30,6 +30,11 @@ public class UniformNumberProvider implements NumberProvider { return RandomUtils.generateRandomInt(this.min.getInt(context), this.max.getInt(context) + 1); } + @Override + public double getDouble(Context context) { + return RandomUtils.generateRandomDouble(this.min.getDouble(context), this.max.getDouble(context)); + } + @Override public float getFloat(Context context) { return RandomUtils.generateRandomFloat(this.min.getFloat(context), this.max.getFloat(context)); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Holder.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Holder.java index 06e1c25f9..d4aae38ea 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Holder.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Holder.java @@ -3,8 +3,8 @@ package net.momirealms.craftengine.core.registry; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Optional; diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/MappedRegistry.java b/core/src/main/java/net/momirealms/craftengine/core/registry/MappedRegistry.java index 2a20fd589..219c1d5b7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/MappedRegistry.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/MappedRegistry.java @@ -3,8 +3,8 @@ package net.momirealms.craftengine.core.registry; import com.google.common.collect.Maps; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.*; public class MappedRegistry implements WritableRegistry { diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Registry.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Registry.java index 4540d9c19..970d47b15 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Registry.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Registry.java @@ -2,8 +2,8 @@ package net.momirealms.craftengine.core.registry; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Map; import java.util.Optional; import java.util.Set; diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java index 7886f0e0f..95e1621f7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java @@ -1,8 +1,8 @@ package net.momirealms.craftengine.core.util; import com.google.common.collect.Iterators; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import java.util.List; import java.util.function.Consumer; diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/World.java b/core/src/main/java/net/momirealms/craftengine/core/world/World.java index 565d93067..c48a66415 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/World.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/World.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.world; +import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Key; @@ -21,6 +22,8 @@ public interface World { return getBlockAt(pos.x(), pos.y(), pos.z()); } + void setBlockAt(int x, int y, int z, BlockStateWrapper blockState, int flags); + String name(); Path directory(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CompressionMethod.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CompressionMethod.java index bf9f74ecd..cfe5268c0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CompressionMethod.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/CompressionMethod.java @@ -5,8 +5,8 @@ import net.jpountz.lz4.LZ4BlockInputStream; import net.jpountz.lz4.LZ4BlockOutputStream; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.dependency.Dependencies; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java index b2e8ad51b..d1feed960 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/storage/RegionFile.java @@ -5,8 +5,8 @@ import net.momirealms.craftengine.core.plugin.logger.PluginLogger; import net.momirealms.craftengine.core.world.ChunkPos; import net.momirealms.sparrow.nbt.CompoundTag; import net.momirealms.sparrow.nbt.NBT; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.io.*; import java.nio.Buffer; import java.nio.ByteBuffer; diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java b/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java index faf6b5bc2..d0a02fd09 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java @@ -3,8 +3,8 @@ package net.momirealms.craftengine.core.world.collision; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.world.EntityHitResult; import net.momirealms.craftengine.core.world.Vec3d; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.Optional; public class AABB { diff --git a/gradle.properties b/gradle.properties index 70296301e..2ee29d431 100644 --- a/gradle.properties +++ b/gradle.properties @@ -71,9 +71,9 @@ modmenu_version=13.0.3 cloth_version=17.0.144 # Proxy settings -systemProp.socks.proxyHost=127.0.0.1 -systemProp.socks.proxyPort=7890 -systemProp.http.proxyHost=127.0.0.1 -systemProp.http.proxyPort=7890 -systemProp.https.proxyHost=127.0.0.1 -systemProp.https.proxyPort=7890 \ No newline at end of file +#systemProp.socks.proxyHost=127.0.0.1 +#systemProp.socks.proxyPort=7890 +#systemProp.http.proxyHost=127.0.0.1 +#systemProp.http.proxyPort=7890 +#systemProp.https.proxyHost=127.0.0.1 +#systemProp.https.proxyPort=7890 \ No newline at end of file From 454e778378037dafa212d9a3e98d192562ab95bf Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 21 May 2025 23:41:52 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E5=92=8C=E6=9D=A1=E4=BB=B6=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/translations/en.yml | 5 ++ .../src/main/resources/translations/zh_cn.yml | 5 ++ .../bukkit/entity/BukkitEntity.java | 4 +- .../bukkit/item/ComponentItemWrapper.java | 2 +- .../bukkit/item/LegacyItemWrapper.java | 2 +- .../item/behavior/FurnitureItemBehavior.java | 2 +- .../plugin/user/BukkitServerPlayer.java | 24 +++++- .../craftengine/bukkit/util/SoundUtils.java | 17 +++++ .../craftengine/bukkit/world/BukkitWorld.java | 7 ++ .../core/entity/AbstractEntity.java | 2 +- .../craftengine/core/entity/Entity.java | 6 +- .../core/entity/player/Player.java | 8 ++ .../core/item/context/UseOnContext.java | 2 +- .../craftengine/core/loot/LootConditions.java | 1 + .../craftengine/core/loot/LootTable.java | 6 +- .../context/condition/CommonConditions.java | 1 + .../context/condition/HandCondition.java | 49 +++++++++++++ .../context/condition/IsNullCondition.java | 2 +- .../plugin/context/event/EventConditions.java | 1 + .../plugin/context/event/EventFunctions.java | 7 ++ .../context/function/BreakBlockFunction.java | 6 +- .../context/function/CommonFunctions.java | 12 +-- .../context/function/DropLootFunction.java | 68 +++++++++++++++++ .../context/function/PlaceBlockFunction.java | 6 +- .../context/function/PlaySoundFunction.java | 73 +++++++++++++++++++ .../context/function/SetCountFunction.java | 57 +++++++++++++++ .../context/function/SetFoodFunction.java | 50 +++++++++++++ .../function/SetSaturationFunction.java | 50 +++++++++++++ .../context/function/SwingHandFunction.java | 52 +++++++++++++ .../function/UpdateInteractionFunction.java | 41 +++++++++++ .../parameter/DirectContextParameters.java | 4 + .../parameter/EntityParameterProvider.java | 2 + .../parameter/PlayerParameterProvider.java | 13 ++-- .../parameter/PositionParameterProvider.java | 2 + .../craftengine/core/sound/SoundSource.java | 27 +++++++ .../craftengine/core/util/Direction.java | 4 +- .../craftengine/core/world/World.java | 4 + 37 files changed, 589 insertions(+), 35 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HandCondition.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaySoundFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetCountFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetFoodFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetSaturationFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SwingHandFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateInteractionFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/sound/SoundSource.java diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index 985333fdd..26a9afbb3 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -95,6 +95,8 @@ warning.config.condition.equals.missing_value1: "Issue found in file Issue found in file - The config '' is missing the required 'value2' argument for 'equals' condition." warning.config.condition.expression.missing_expression: "Issue found in file - The config '' is missing the required 'expression' argument for 'expression' condition." warning.config.condition.is_null.missing_argument: "Issue found in file - The config '' is missing the required 'argument' argument for 'is_null' condition." +warning.config.condition.hand.missing_hand: "Issue found in file - The config '' is missing the required 'hand' argument for 'hand' condition." +warning.config.condition.hand.invalid_hand: "Issue found in file - The config '' is using an invalid 'hand' argument '' for 'hand' condition. Allowed hand types: []" warning.config.structure.not_section: "Issue found in file - The config '' is expected to be a config section while it's actually a(n) ''." warning.config.image.duplicate: "Issue found in file - Duplicated image ''. Please check if there is the same configuration in other files." warning.config.image.missing_height: "Issue found in file - The image '' is missing the required 'height' argument." @@ -319,6 +321,9 @@ warning.config.function.open_window.missing_gui_type: "Issue found in fi warning.config.function.open_window.invalid_gui_type: "Issue found in file - The config '' is using an invalid gui type for 'open_window' function. Allowed types: []." warning.config.function.run.missing_functions: "Issue found in file - The config '' is missing the required 'functions' argument for 'run' function." warning.config.function.place_block.missing_block_state: "Issue found in file - The config '' is missing the required 'block-state' argument for 'place_block' function." +warning.config.function.set_food.missing_food: "Issue found in file - The config '' is missing the required 'food' argument for 'set_food' function." +warning.config.function.set_saturation.missing_saturation: "Issue found in file - The config '' is missing the required 'saturation' argument for 'set_saturation' function." +warning.config.function.play_sound.missing_sound: "Issue found in file - The config '' is missing the required 'sound' argument for 'play_sound' function." warning.config.selector.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for selector." warning.config.selector.invalid_type: "Issue found in file - The config '' is using an invalid selector type ''." warning.config.selector.invalid_target: "Issue found in file - The config '' is using an invalid selector target ''." diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index ab9ca80ab..983dc9e9c 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -96,6 +96,8 @@ warning.config.condition.equals.missing_value2: "在文件 中 warning.config.condition.expression.missing_expression: "在文件 中发现问题 - 配置项 '' 缺少 'expression' 条件必需的 'expression' 参数" warning.config.condition.is_null.missing_argument: "在文件 发现问题 - 配置项 '' 缺少 'is_null' 条件的必需的 'argument' 参数." warning.config.structure.not_section: "在文件 发现问题 - 配置项 '' 应为配置段落 但实际类型为 ''" +warning.config.condition.hand.missing_hand: "Issue found in file - The config '' is missing the required 'hand' argument for 'hand' condition." +warning.config.condition.hand.invalid_hand: "Issue found in file - The config '' is using an invalid 'hand' argument '' for 'hand' condition. Allowed hand types: []" warning.config.image.duplicate: "在文件 发现问题 - 重复的图片配置 '' 请检查其他文件中是否存在相同配置" warning.config.image.missing_height: "在文件 发现问题 - 图片 '' 缺少必需的 'height' 参数" warning.config.image.height_ascent_conflict: "在文件 发现问题 - 图片 '' 违反位图规则: 'height' 参数 '' 必须不小于 'ascent' 参数 ''" @@ -319,6 +321,9 @@ warning.config.function.open_window.missing_gui_type: "在文件 warning.config.function.open_window.invalid_gui_type: "在文件 中发现问题 - 配置项 '' 为 'open_window' 函数使用了无效的 GUI 类型 . 允许的类型: []。" warning.config.function.run.missing_functions: "在文件 中发现问题 - 配置项 '' 缺少 'run' 函数必需的 'functions' 参数" warning.config.function.place_block.missing_block_state: "在文件 中发现问题 - 配置项 '' 缺少 'place_block' 函数必需的 'block-state' 参数." +warning.config.function.set_food.missing_food: "Issue found in file - The config '' is missing the required 'food' argument for 'set_food' function." +warning.config.function.set_saturation.missing_saturation: "Issue found in file - The config '' is missing the required 'saturation' argument for 'set_saturation' function." +warning.config.function.play_sound.missing_sound: "Issue found in file - The config '' is missing the required 'sound' argument for 'play_sound' function." warning.config.selector.missing_type: "在文件 中发现问题 - 配置项 '' 缺少选择器必需的 'type' 参数" warning.config.selector.invalid_type: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器类型 ''" warning.config.selector.invalid_target: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器目标 ''" diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java index ffe08c8fd..2193b86f9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitEntity.java @@ -42,12 +42,12 @@ public class BukkitEntity extends AbstractEntity { } @Override - public float getXRot() { + public float xRot() { return literalObject().getYaw(); } @Override - public float getYRot() { + public float yRot() { return literalObject().getPitch(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java index b7c1eb500..c4bdbc860 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java @@ -98,6 +98,6 @@ public class ComponentItemWrapper implements ItemWrapper { @Override public void count(int amount) { - this.item.setAmount(amount); + this.item.setAmount(Math.max(amount, 0)); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java index 5e58510c9..154e121e5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java @@ -60,7 +60,7 @@ public class LegacyItemWrapper implements ItemWrapper { @Override public ItemStack load() { ItemStack itemStack = this.rtagItem.load(); - itemStack.setAmount(this.count); + itemStack.setAmount(Math.max(this.count, 0)); return itemStack; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index 3c49d8c86..b604359e9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -105,7 +105,7 @@ public class FurnitureItemBehavior extends ItemBehavior { finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z()); } } else { - furnitureYaw = placement.rotationRule().apply(180 + player.getXRot()); + furnitureYaw = placement.rotationRule().apply(180 + player.xRot()); Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z())); finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right()); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 00d219bd8..3dce61b66 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -675,12 +675,12 @@ public class BukkitServerPlayer extends Player { } @Override - public float getYRot() { + public float yRot() { return platformPlayer().getPitch(); } @Override - public float getXRot() { + public float xRot() { return platformPlayer().getYaw(); } @@ -838,4 +838,24 @@ public class BukkitServerPlayer extends Player { public boolean isFlying() { return platformPlayer().isFlying(); } + + @Override + public int foodLevel() { + return platformPlayer().getFoodLevel(); + } + + @Override + public void setFoodLevel(int foodLevel) { + this.platformPlayer().setFoodLevel(Math.min(Math.max(0, foodLevel), 20)); + } + + @Override + public float saturation() { + return platformPlayer().getSaturation(); + } + + @Override + public void setSaturation(float saturation) { + this.platformPlayer().setSaturation(saturation); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/SoundUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/SoundUtils.java index a733074e5..de80480fa 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/SoundUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/SoundUtils.java @@ -1,7 +1,9 @@ package net.momirealms.craftengine.bukkit.util; import net.momirealms.craftengine.core.block.BlockSounds; +import net.momirealms.craftengine.core.sound.SoundSource; import net.momirealms.craftengine.core.util.Key; +import org.bukkit.SoundCategory; public class SoundUtils { @@ -21,4 +23,19 @@ public class SoundUtils { public static Object getOrRegisterSoundEvent(Key key) throws ReflectiveOperationException { return Reflections.method$SoundEvent$createVariableRangeEvent.invoke(null, KeyUtils.toResourceLocation(key)); } + + public static SoundCategory toBukkit(SoundSource source) { + return switch (source) { + case BLOCK -> SoundCategory.BLOCKS; + case MUSIC -> SoundCategory.MUSIC; + case VOICE -> SoundCategory.VOICE; + case MASTER -> SoundCategory.MASTER; + case PLAYER -> SoundCategory.PLAYERS; + case RECORD -> SoundCategory.RECORDS; + case AMBIENT -> SoundCategory.AMBIENT; + case HOSTILE -> SoundCategory.HOSTILE; + case NEUTRAL -> SoundCategory.NEUTRAL; + case WEATHER -> SoundCategory.WEATHER; + }; + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java index 4314a2fda..c1b6949a5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java @@ -3,8 +3,10 @@ package net.momirealms.craftengine.bukkit.world; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.ItemUtils; +import net.momirealms.craftengine.bukkit.util.SoundUtils; import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.sound.SoundSource; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockInWorld; @@ -87,6 +89,11 @@ public class BukkitWorld implements World { }); } + @Override + public void playSound(Position location, Key sound, float volume, float pitch, SoundSource source) { + platformWorld().playSound(new Location(null, location.x(), location.y(), location.z()), sound.toString(), SoundUtils.toBukkit(source), volume, pitch); + } + @Override public void playBlockSound(Position location, Key sound, float volume, float pitch) { platformWorld().playSound(new Location(null, location.x(), location.y(), location.z()), sound.toString(), SoundCategory.BLOCKS, volume, pitch); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/AbstractEntity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/AbstractEntity.java index c9eb5a247..fa9643892 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/AbstractEntity.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/AbstractEntity.java @@ -6,6 +6,6 @@ public abstract class AbstractEntity implements Entity { @Override public WorldPosition position() { - return new WorldPosition(world(), x(), y(), z(), getXRot(), getYRot()); + return new WorldPosition(world(), x(), y(), z(), xRot(), yRot()); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java index 15720fa5c..aac181c4b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/Entity.java @@ -20,12 +20,12 @@ public interface Entity { void tick(); - float getXRot(); + float xRot(); + + float yRot(); int entityID(); - float getYRot(); - World world(); Direction getDirection(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index 70e614cd2..c0132edf8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -116,4 +116,12 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public boolean isAdventureMode() { return gameMode() == GameMode.ADVENTURE; } + + public abstract int foodLevel(); + + public abstract void setFoodLevel(int foodLevel); + + public abstract float saturation(); + + public abstract void setSaturation(float saturation); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java b/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java index 5e6280e02..e07191478 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/context/UseOnContext.java @@ -73,6 +73,6 @@ public class UseOnContext { } public float getRotation() { - return this.player == null ? 0.0F : this.player.getYRot(); + return this.player == null ? 0.0F : this.player.yRot(); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java index 9ea20df82..26798ceb1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java @@ -34,6 +34,7 @@ public class LootConditions { register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>()); register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>()); register(CommonConditions.IS_NULL, new IsNullCondition.FactoryImpl<>()); + register(CommonConditions.HAND, new HandCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/LootTable.java b/core/src/main/java/net/momirealms/craftengine/core/loot/LootTable.java index 32d744ba0..662cefcea 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/LootTable.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/LootTable.java @@ -78,15 +78,15 @@ public class LootTable { ); } - public ArrayList> getRandomItems(ContextHolder parameters, World world) { + public List> getRandomItems(ContextHolder parameters, World world) { return this.getRandomItems(parameters, world, null); } - public ArrayList> getRandomItems(ContextHolder parameters, World world, @Nullable Player player) { + public List> getRandomItems(ContextHolder parameters, World world, @Nullable Player player) { return this.getRandomItems(new LootContext(world, player, player == null ? 1f : (float) player.luck(), parameters)); } - private ArrayList> getRandomItems(LootContext context) { + private List> getRandomItems(LootContext context) { ArrayList> list = new ArrayList<>(); this.getRandomItems(context, list::add); return list; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java index ad64b2ec5..44a588cb9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java @@ -21,4 +21,5 @@ public final class CommonConditions { public static final Key EQUALS = Key.from("craftengine:equals"); public static final Key EXPRESSION = Key.from("craftengine:expression"); public static final Key IS_NULL = Key.from("craftengine:is_null"); + public static final Key HAND = Key.from("craftengine:hand"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HandCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HandCondition.java new file mode 100644 index 000000000..8cc171076 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HandCondition.java @@ -0,0 +1,49 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class HandCondition implements Condition { + private final InteractionHand hand; + + public HandCondition(InteractionHand hand) { + this.hand = hand; + } + + @Override + public Key type() { + return CommonConditions.HAND; + } + + @Override + public boolean test(CTX ctx) { + Optional optional = ctx.getOptionalParameter(DirectContextParameters.HAND); + if (optional.isPresent()) { + InteractionHand hand = optional.get(); + return hand.equals(this.hand); + } + return false; + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + String hand = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("hand"), "warning.config.condition.hand.missing_hand"); + try { + return new HandCondition<>(InteractionHand.valueOf(hand.toUpperCase(Locale.ENGLISH))); + } catch (IllegalArgumentException e) { + throw new LocalizedResourceConfigException("warning.config.condition.hand.invalid_hand", hand); + } + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java index 7ea6d60cb..010221218 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/IsNullCondition.java @@ -24,7 +24,7 @@ public class IsNullCondition implements Condition { @Override public boolean test(CTX ctx) { Optional optional = ctx.getOptionalParameter(this.key); - return optional.isPresent(); + return optional.isEmpty(); } public static class FactoryImpl implements ConditionFactory { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java index e7eea8bc8..3c93dd0e0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java @@ -32,6 +32,7 @@ public class EventConditions { register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>()); register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>()); register(CommonConditions.IS_NULL, new IsNullCondition.FactoryImpl<>()); + register(CommonConditions.HAND, new HandCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java index c056c1c7e..ae0c66bd3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java @@ -26,6 +26,13 @@ public class EventFunctions { register(CommonFunctions.RUN, new RunFunction.FactoryImpl<>(EventFunctions::fromMap, EventConditions::fromMap)); register(CommonFunctions.PLACE_BLOCK, new PlaceBlockFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.BREAK_BLOCK, new BreakBlockFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.UPDATE_INTERACTION_TICK, new UpdateInteractionFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.SET_COUNT, new SetCountFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.DROP_LOOT, new DropLootFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.SWING_HAND, new SwingHandFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.SET_FOOD, new SetFoodFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.SET_SATURATION, new SetSaturationFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.PLAY_SOUND, new PlaySoundFunction.FactoryImpl<>(EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java index 97d5fc4b4..025cda880 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/BreakBlockFunction.java @@ -44,9 +44,9 @@ public class BreakBlockFunction extends AbstractConditional @Override public Function create(Map arguments) { - NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); - NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); - NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); return new BreakBlockFunction<>(x, y, z, getPredicates(arguments)); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java index 4e7b764b4..82de72647 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java @@ -12,15 +12,15 @@ public final class CommonFunctions { public static final Key TITLE = Key.of("craftengine:title"); public static final Key OPEN_WINDOW = Key.of("craftengine:open_window"); public static final Key PARTICLE = Key.of("craftengine:particle"); - public static final Key SOUND = Key.of("craftengine:sound"); + public static final Key PLAY_SOUND = Key.of("craftengine:play_sound"); public static final Key POTION_EFFECT = Key.of("craftengine:potion_effect"); public static final Key BREAK_BLOCK = Key.of("craftengine:break_block"); public static final Key CANCEL_EVENT = Key.of("craftengine:cancel_event"); + public static final Key UPDATE_INTERACTION_TICK = Key.of("craftengine:update_interaction_tick"); + public static final Key SET_COUNT = Key.of("craftengine:set_count"); public static final Key PLACE_BLOCK = Key.of("craftengine:place_block"); - public static final Key FOOD = Key.of("craftengine:food"); - public static final Key SATURATION = Key.of("craftengine:saturation"); - public static final Key MONEY = Key.of("craftengine:money"); - public static final Key OXYGEN = Key.of("craftengine:oxygen"); - public static final Key MINE_RADIUS = Key.of("craftengine:mine_radius"); + public static final Key SET_FOOD = Key.of("craftengine:food"); + public static final Key SET_SATURATION = Key.of("craftengine:saturation"); public static final Key DROP_LOOT = Key.of("craftengine:drop_loot"); + public static final Key SWING_HAND = Key.of("craftengine:swing_hand"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java new file mode 100644 index 000000000..216c1c511 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DropLootFunction.java @@ -0,0 +1,68 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.loot.LootTable; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class DropLootFunction extends AbstractConditionalFunction { + private final NumberProvider x; + private final NumberProvider y; + private final NumberProvider z; + private final LootTable lootTable; + + public DropLootFunction(NumberProvider x, NumberProvider y, NumberProvider z, LootTable lootTable, List> predicates) { + super(predicates); + this.x = x; + this.y = y; + this.z = z; + this.lootTable = lootTable; + } + + @Override + public void runInternal(CTX ctx) { + Optional optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION); + if (optionalWorldPosition.isPresent()) { + World world = optionalWorldPosition.get().world(); + WorldPosition position = new WorldPosition(world, x.getDouble(ctx), y.getDouble(ctx), z.getDouble(ctx)); + Player player = ctx.getOptionalParameter(DirectContextParameters.PLAYER).orElse(null); + List> items = lootTable.getRandomItems(ctx.contexts(), world, player); + for (Item item : items) { + world.dropItemNaturally(position, item); + } + } + } + + @Override + public Key type() { + return CommonFunctions.DROP_LOOT; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); + LootTable loots = LootTable.fromMap(MiscUtils.castToMap(arguments.get("loot"), true)); + return new DropLootFunction<>(x, y, z, loots, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java index 2c0daf916..c5fbeae29 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java @@ -77,9 +77,9 @@ public class PlaceBlockFunction extends AbstractConditional public Function create(Map arguments) { String state = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("block-state"), "warning.config.function.place_block.missing_block_state"); DelayedInitBlockState delayedInitBlockState = new DelayedInitBlockState(state); - NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); - NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); - NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); NumberProvider flags = Optional.ofNullable(arguments.get("update-flags")).map(NumberProviders::fromObject).orElse(NumberProviders.direct(UpdateOption.UPDATE_ALL.flags())); return new PlaceBlockFunction<>(delayedInitBlockState, x, y, z, flags, getPredicates(arguments)); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaySoundFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaySoundFunction.java new file mode 100644 index 000000000..ea5f4c547 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaySoundFunction.java @@ -0,0 +1,73 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.sound.SoundSource; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class PlaySoundFunction extends AbstractConditionalFunction { + private final Key soundEvent; + private final NumberProvider x; + private final NumberProvider y; + private final NumberProvider z; + private final NumberProvider volume; + private final NumberProvider pitch; + private final SoundSource source; + + public PlaySoundFunction(Key soundEvent, NumberProvider x, NumberProvider y, NumberProvider z, NumberProvider volume, NumberProvider pitch, SoundSource source, List> predicates) { + super(predicates); + this.soundEvent = soundEvent; + this.x = x; + this.y = y; + this.z = z; + this.volume = volume; + this.pitch = pitch; + this.source = source; + } + + @Override + public void runInternal(CTX ctx) { + Optional optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION); + if (optionalWorldPosition.isPresent()) { + World world = optionalWorldPosition.get().world(); + world.playSound(new Vec3d(this.x.getDouble(ctx), this.y.getDouble(ctx), this.z.getDouble(ctx)), + this.soundEvent, this.volume.getFloat(ctx), this.pitch.getFloat(ctx), this.source); + } + } + + @Override + public Key type() { + return CommonFunctions.PLAY_SOUND; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + Key soundEvent = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("sound"), "warning.config.function.play_sound.missing_sound")); + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); + NumberProvider volume = NumberProviders.fromObject(arguments.getOrDefault("volume", 1)); + NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", 1)); + SoundSource source = Optional.ofNullable(arguments.get("source")).map(String::valueOf).map(it -> SoundSource.valueOf(it.toUpperCase(Locale.ENGLISH))).orElse(SoundSource.MASTER); + return new PlaySoundFunction<>(soundEvent, x, y, z, volume, pitch, source, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetCountFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetCountFunction.java new file mode 100644 index 000000000..6d9e6b496 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetCountFunction.java @@ -0,0 +1,57 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class SetCountFunction extends AbstractConditionalFunction { + private final NumberProvider count; + private final boolean add; + + public SetCountFunction(NumberProvider count, boolean add, List> predicates) { + super(predicates); + this.count = count; + this.add = add; + } + + @Override + public void runInternal(CTX ctx) { + Optional> optionalItem = ctx.getOptionalParameter(DirectContextParameters.ITEM_IN_HAND); + if (optionalItem.isPresent()) { + Item item = optionalItem.get(); + if (this.add) { + item.count(Math.min(item.count() + (this.count.getInt(ctx)), item.maxStackSize())); + } else { + item.count(Math.min(this.count.getInt(ctx), item.maxStackSize())); + } + } + } + + @Override + public Key type() { + return CommonFunctions.SET_COUNT; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("count"), "warning.config.function.set_count.missing_count"); + boolean add = (boolean) arguments.getOrDefault("add", false); + return new SetCountFunction<>(NumberProviders.fromObject(value), add, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetFoodFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetFoodFunction.java new file mode 100644 index 000000000..fcd05f71a --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetFoodFunction.java @@ -0,0 +1,50 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class SetFoodFunction extends AbstractConditionalFunction { + private final NumberProvider count; + private final boolean add; + + public SetFoodFunction(NumberProvider count, boolean add, List> predicates) { + super(predicates); + this.count = count; + this.add = add; + } + + @Override + public void runInternal(CTX ctx) { + Optional optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + optionalPlayer.ifPresent(player -> player.setFoodLevel(this.add ? player.foodLevel() + this.count.getInt(ctx) : this.count.getInt(ctx))); + } + + @Override + public Key type() { + return CommonFunctions.SET_FOOD; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("food"), "warning.config.function.set_food.missing_food"); + boolean add = (boolean) arguments.getOrDefault("add", false); + return new SetFoodFunction<>(NumberProviders.fromObject(value), add, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetSaturationFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetSaturationFunction.java new file mode 100644 index 000000000..86634543f --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SetSaturationFunction.java @@ -0,0 +1,50 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class SetSaturationFunction extends AbstractConditionalFunction { + private final NumberProvider count; + private final boolean add; + + public SetSaturationFunction(NumberProvider count, boolean add, List> predicates) { + super(predicates); + this.count = count; + this.add = add; + } + + @Override + public void runInternal(CTX ctx) { + Optional optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + optionalPlayer.ifPresent(player -> player.setSaturation(this.add ? player.saturation() + this.count.getFloat(ctx) : this.count.getFloat(ctx))); + } + + @Override + public Key type() { + return CommonFunctions.SET_SATURATION; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("saturation"), "warning.config.function.set_saturation.missing_saturation"); + boolean add = (boolean) arguments.getOrDefault("add", false); + return new SetSaturationFunction<>(NumberProviders.fromObject(value), add, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SwingHandFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SwingHandFunction.java new file mode 100644 index 000000000..935fa210e --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SwingHandFunction.java @@ -0,0 +1,52 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class SwingHandFunction extends AbstractConditionalFunction { + private final Optional hand; + + public SwingHandFunction(Optional hand, List> predicates) { + super(predicates); + this.hand = hand; + } + + @Override + public void runInternal(CTX ctx) { + Optional cancellable = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + cancellable.ifPresent(value -> { + if (this.hand.isPresent()) { + value.swingHand(this.hand.get()); + } else { + value.swingHand(ctx.getOptionalParameter(DirectContextParameters.HAND).orElse(InteractionHand.MAIN_HAND)); + } + }); + } + + @Override + public Key type() { + return CommonFunctions.SWING_HAND; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + Optional optionalHand = Optional.ofNullable(arguments.get("hand")).map(it -> InteractionHand.valueOf(it.toString().toUpperCase(Locale.ENGLISH))); + return new SwingHandFunction<>(optionalHand, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateInteractionFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateInteractionFunction.java new file mode 100644 index 000000000..6ef587ad5 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateInteractionFunction.java @@ -0,0 +1,41 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class UpdateInteractionFunction extends AbstractConditionalFunction { + + public UpdateInteractionFunction(List> predicates) { + super(predicates); + } + + @Override + public void runInternal(CTX ctx) { + Optional cancellable = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + cancellable.ifPresent(value -> value.updateLastSuccessfulInteractionTick(value.gameTicks())); + } + + @Override + public Key type() { + return CommonFunctions.UPDATE_INTERACTION_TICK; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + return new UpdateInteractionFunction<>(getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java index 798c8e53d..495739c3b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/DirectContextParameters.java @@ -39,9 +39,13 @@ public final class DirectContextParameters { public static final ContextKey X = ContextKey.direct("x"); public static final ContextKey Y = ContextKey.direct("y"); public static final ContextKey Z = ContextKey.direct("z"); + public static final ContextKey YAW = ContextKey.direct("yaw"); + public static final ContextKey PITCH = ContextKey.direct("pitch"); public static final ContextKey BLOCK_X = ContextKey.direct("block_x"); public static final ContextKey BLOCK_Y = ContextKey.direct("block_y"); public static final ContextKey BLOCK_Z = ContextKey.direct("block_z"); + public static final ContextKey FOOD = ContextKey.direct("food"); + public static final ContextKey SATURATION = ContextKey.direct("saturation"); public static final ContextKey UUID = ContextKey.direct("uuid"); public static final ContextKey> MAIN_HAND_ITEM = ContextKey.direct("main_hand_item"); public static final ContextKey> OFF_HAND_ITEM = ContextKey.direct("off_hand_item"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java index b36225670..465b49809 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java @@ -16,6 +16,8 @@ public class EntityParameterProvider implements ChainParameterProvider { CONTEXT_FUNCTIONS.put(DirectContextParameters.X, Entity::x); CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, Entity::y); CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, Entity::z); + CONTEXT_FUNCTIONS.put(DirectContextParameters.YAW, Entity::xRot); + CONTEXT_FUNCTIONS.put(DirectContextParameters.PITCH, Entity::yRot); CONTEXT_FUNCTIONS.put(DirectContextParameters.POSITION, Entity::position); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_X, p -> MCUtils.fastFloor(p.x())); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Y, p -> MCUtils.fastFloor(p.y())); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java index 4075c6ff8..042b08c05 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PlayerParameterProvider.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.core.plugin.context.parameter; -import net.momirealms.craftengine.core.entity.AbstractEntity; import net.momirealms.craftengine.core.entity.Entity; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.Player; @@ -16,13 +15,17 @@ import java.util.function.Function; public class PlayerParameterProvider implements ChainParameterProvider { private static final Map, Function> CONTEXT_FUNCTIONS = new HashMap<>(); static { - CONTEXT_FUNCTIONS.put(DirectContextParameters.X, AbstractEntity::x); - CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, AbstractEntity::y); - CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, AbstractEntity::z); - CONTEXT_FUNCTIONS.put(DirectContextParameters.POSITION, AbstractEntity::position); + CONTEXT_FUNCTIONS.put(DirectContextParameters.X, Entity::x); + CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, Entity::y); + CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, Entity::z); + CONTEXT_FUNCTIONS.put(DirectContextParameters.YAW, Entity::xRot); + CONTEXT_FUNCTIONS.put(DirectContextParameters.PITCH, Entity::yRot); + CONTEXT_FUNCTIONS.put(DirectContextParameters.POSITION, Entity::position); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_X, p -> MCUtils.fastFloor(p.x())); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Y, p -> MCUtils.fastFloor(p.y())); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Z, p -> MCUtils.fastFloor(p.z())); + CONTEXT_FUNCTIONS.put(DirectContextParameters.FOOD, Player::foodLevel); + CONTEXT_FUNCTIONS.put(DirectContextParameters.SATURATION, Player::saturation); CONTEXT_FUNCTIONS.put(DirectContextParameters.NAME, Player::name); CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Player::uuid); CONTEXT_FUNCTIONS.put(DirectContextParameters.WORLD, Entity::world); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PositionParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PositionParameterProvider.java index 710917c19..b7e2b26b6 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PositionParameterProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/PositionParameterProvider.java @@ -18,6 +18,8 @@ public class PositionParameterProvider implements ChainParameterProvider MCUtils.fastFloor(p.x())); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Y, p -> MCUtils.fastFloor(p.y())); CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Z, p -> MCUtils.fastFloor(p.z())); diff --git a/core/src/main/java/net/momirealms/craftengine/core/sound/SoundSource.java b/core/src/main/java/net/momirealms/craftengine/core/sound/SoundSource.java new file mode 100644 index 000000000..e48a6c429 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/sound/SoundSource.java @@ -0,0 +1,27 @@ +package net.momirealms.craftengine.core.sound; + +import org.jetbrains.annotations.NotNull; + +public enum SoundSource { + MASTER("master"), + MUSIC("music"), + RECORD("record"), + WEATHER("weather"), + BLOCK("block"), + HOSTILE("hostile"), + NEUTRAL("neutral"), + PLAYER("player"), + AMBIENT("ambient"), + VOICE("voice"); + + private final String id; + + SoundSource(final String id) { + this.id = id; + } + + @NotNull + public String id() { + return this.id; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/Direction.java b/core/src/main/java/net/momirealms/craftengine/core/util/Direction.java index 87cd8df73..a48bfdc14 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/Direction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/Direction.java @@ -94,8 +94,8 @@ public enum Direction { } public static Direction[] orderedByNearest(AbstractEntity entity) { - float xRotation = entity.getXRot() * (float) (Math.PI / 180.0); - float yRotation = -entity.getYRot() * (float) (Math.PI / 180.0); + float xRotation = entity.xRot() * (float) (Math.PI / 180.0); + float yRotation = -entity.yRot() * (float) (Math.PI / 180.0); float sinX = (float) Math.sin(xRotation); float cosX = (float) Math.cos(xRotation); float sinY = (float) Math.sin(yRotation); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/World.java b/core/src/main/java/net/momirealms/craftengine/core/world/World.java index c48a66415..08efec880 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/World.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/World.java @@ -1,8 +1,10 @@ package net.momirealms.craftengine.core.world; +import net.kyori.adventure.sound.Sound; import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.sound.SoundData; +import net.momirealms.craftengine.core.sound.SoundSource; import net.momirealms.craftengine.core.util.Key; import java.nio.file.Path; @@ -34,6 +36,8 @@ public interface World { void dropExp(Position location, int amount); + void playSound(Position location, Key sound, float volume, float pitch, SoundSource source); + void playBlockSound(Position location, Key sound, float volume, float pitch); default void playBlockSound(Position location, SoundData data) { From 29c32054f06b2892c3ca7b5a1c3642522c183acd Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 22 May 2025 16:02:58 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit/build.gradle.kts | 1 - .../core/plugin/dependency/Dependencies.java | 69 ------------------- .../core/plugin/dependency/Dependency.java | 18 +++-- .../dependency/DependencyManagerImpl.java | 40 ++++++++++- .../dependency/DependencyRepository.java | 1 + .../craftengine/core/util/FileUtils.java | 15 ++++ .../craftengine/core/world/World.java | 1 - gradle.properties | 3 +- 8 files changed, 62 insertions(+), 86 deletions(-) diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index 0b9d4ae93..75e8293ea 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -46,7 +46,6 @@ dependencies { compileOnly("com.saicone.rtag:rtag-item:${rootProject.properties["rtag_version"]}") // Adventure compileOnly("net.kyori:adventure-api:${rootProject.properties["adventure_bundle_version"]}") - compileOnly("net.kyori:adventure-platform-bukkit:${rootProject.properties["adventure_platform_version"]}") compileOnly("net.kyori:adventure-text-minimessage:${rootProject.properties["adventure_bundle_version"]}") compileOnly("net.kyori:adventure-text-serializer-gson:${rootProject.properties["adventure_bundle_version"]}") { exclude("com.google.code.gson", "gson") diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java index c5c54940d..3342d05b1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java @@ -11,7 +11,6 @@ public class Dependencies { "asm", "org.ow2.asm", "asm", - "asm", Collections.emptyList() ); @@ -19,7 +18,6 @@ public class Dependencies { "asm-commons", "org.ow2.asm", "asm-commons", - "asm-commons", Collections.emptyList() ); @@ -27,7 +25,6 @@ public class Dependencies { "jar-relocator", "me.lucko", "jar-relocator", - "jar-relocator", Collections.emptyList() ); @@ -35,7 +32,6 @@ public class Dependencies { "geantyref", "io{}leangen{}geantyref", "geantyref", - "geantyref", List.of(Relocation.of("geantyref", "io{}leangen{}geantyref")) ); @@ -43,7 +39,6 @@ public class Dependencies { "cloud-core", "org{}incendo", "cloud-core", - "cloud-core", List.of(Relocation.of("cloud", "org{}incendo{}cloud"), Relocation.of("geantyref", "io{}leangen{}geantyref")) ); @@ -52,7 +47,6 @@ public class Dependencies { "cloud-brigadier", "org{}incendo", "cloud-brigadier", - "cloud-brigadier", List.of(Relocation.of("cloud", "org{}incendo{}cloud"), Relocation.of("geantyref", "io{}leangen{}geantyref")) ); @@ -61,7 +55,6 @@ public class Dependencies { "cloud-services", "org{}incendo", "cloud-services", - "cloud-services", List.of(Relocation.of("cloud", "org{}incendo{}cloud"), Relocation.of("geantyref", "io{}leangen{}geantyref")) ); @@ -70,7 +63,6 @@ public class Dependencies { "cloud-bukkit", "org{}incendo", "cloud-bukkit", - "cloud-bukkit", List.of(Relocation.of("cloud", "org{}incendo{}cloud"), Relocation.of("geantyref", "io{}leangen{}geantyref"), Relocation.of("adventure", "net{}kyori{}adventure"), @@ -82,7 +74,6 @@ public class Dependencies { "cloud-paper", "org{}incendo", "cloud-paper", - "cloud-paper", List.of(Relocation.of("cloud", "org{}incendo{}cloud"), Relocation.of("geantyref", "io{}leangen{}geantyref"), Relocation.of("adventure", "net{}kyori{}adventure"), @@ -94,7 +85,6 @@ public class Dependencies { "cloud-minecraft-extras", "org{}incendo", "cloud-minecraft-extras", - "cloud-minecraft-extras", List.of(Relocation.of("cloud", "org{}incendo{}cloud"), Relocation.of("geantyref", "io{}leangen{}geantyref"), Relocation.of("adventure", "net{}kyori{}adventure"), @@ -106,7 +96,6 @@ public class Dependencies { "boosted-yaml", "dev{}dejvokep", "boosted-yaml", - "boosted-yaml", List.of(Relocation.of("boostedyaml", "dev{}dejvokep{}boostedyaml")) ); @@ -114,7 +103,6 @@ public class Dependencies { "bstats-base", "org{}bstats", "bstats-base", - "bstats-base", List.of(Relocation.of("bstats", "org{}bstats")) ); @@ -122,7 +110,6 @@ public class Dependencies { "bstats-bukkit", "org{}bstats", "bstats-bukkit", - "bstats-bukkit", List.of(Relocation.of("bstats", "org{}bstats")) ) { @Override @@ -135,7 +122,6 @@ public class Dependencies { "gson", "com.google.code.gson", "gson", - "gson", Collections.emptyList() ); @@ -143,7 +129,6 @@ public class Dependencies { "caffeine", "com{}github{}ben-manes{}caffeine", "caffeine", - "caffeine", List.of(Relocation.of("caffeine", "com{}github{}benmanes{}caffeine")) ); @@ -151,7 +136,6 @@ public class Dependencies { "zstd-jni", "com.github.luben", "zstd-jni", - "zstd-jni", Collections.emptyList() ); @@ -159,7 +143,6 @@ public class Dependencies { "slf4j-api", "org.slf4j", "slf4j-api", - "slf4j-api", Collections.emptyList() ); @@ -167,7 +150,6 @@ public class Dependencies { "slf4j-simple", "org.slf4j", "slf4j-simple", - "slf4j-simple", Collections.emptyList() ) { @Override @@ -180,7 +162,6 @@ public class Dependencies { "commons-io", "commons-io", "commons-io", - "commons-io", List.of(Relocation.of("commons", "org{}apache{}commons")) ); @@ -188,7 +169,6 @@ public class Dependencies { "byte-buddy", "net{}bytebuddy", "byte-buddy", - "byte-buddy", List.of(Relocation.of("bytebuddy", "net{}bytebuddy")) ); @@ -196,7 +176,6 @@ public class Dependencies { "snake-yaml", "org{}yaml", "snakeyaml", - "snakeyaml", List.of(Relocation.of("snakeyaml", "org{}yaml{}snakeyaml")) ); @@ -204,7 +183,6 @@ public class Dependencies { "option", "net{}kyori", "option", - "option", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -214,7 +192,6 @@ public class Dependencies { "adventure-api", "net{}kyori", "adventure-api", - "adventure-api", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -224,7 +201,6 @@ public class Dependencies { "adventure-key", "net{}kyori", "adventure-key", - "adventure-key", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -239,7 +215,6 @@ public class Dependencies { "examination-api", "net{}kyori", "examination-api", - "examination-api", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -249,7 +224,6 @@ public class Dependencies { "examination-string", "net{}kyori", "examination-string", - "examination-string", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -264,7 +238,6 @@ public class Dependencies { "adventure-text-minimessage", "net{}kyori", "adventure-text-minimessage", - "adventure-text-minimessage", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -279,7 +252,6 @@ public class Dependencies { "adventure-text-serializer-commons", "net{}kyori", "adventure-text-serializer-commons", - "adventure-text-serializer-commons", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -294,7 +266,6 @@ public class Dependencies { "adventure-text-serializer-gson", "net{}kyori", "adventure-text-serializer-gson", - "adventure-text-serializer-gson", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -309,7 +280,6 @@ public class Dependencies { "adventure-text-serializer-json-legacy-impl", "net{}kyori", "adventure-text-serializer-json-legacy-impl", - "adventure-text-serializer-json-legacy-impl", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -324,7 +294,6 @@ public class Dependencies { "adventure-text-serializer-legacy", "net{}kyori", "adventure-text-serializer-legacy", - "adventure-text-serializer-legacy", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -339,7 +308,6 @@ public class Dependencies { "adventure-text-serializer-json", "net{}kyori", "adventure-text-serializer-json", - "adventure-text-serializer-json", List.of(Relocation.of("option", "net{}kyori{}option"), Relocation.of("examination", "net{}kyori{}examination"), Relocation.of("adventure", "net{}kyori{}adventure")) @@ -354,7 +322,6 @@ public class Dependencies { "ahocorasick", "org{}ahocorasick", "ahocorasick", - "aho-corasick", List.of(Relocation.of("ahocorasick", "org{}ahocorasick")) ); @@ -362,7 +329,6 @@ public class Dependencies { "lz4", "org{}lz4", "lz4-java", - "lz4-java", List.of(Relocation.of("jpountz", "net{}jpountz")) ); @@ -370,7 +336,6 @@ public class Dependencies { "evalex", "com{}ezylang", "EvalEx", - "evalex", List.of(Relocation.of("evalex", "com{}ezylang{}evalex")) ); @@ -378,7 +343,6 @@ public class Dependencies { "netty-codec-http", "io{}netty", "netty-codec-http", - "netty-codec-http", Collections.emptyList() ); @@ -386,7 +350,6 @@ public class Dependencies { "netty-codec-http2", "io{}netty", "netty-codec-http2", - "netty-codec-http2", Collections.emptyList() ); @@ -394,7 +357,6 @@ public class Dependencies { "reactive-streams", "org{}reactivestreams", "reactive-streams", - "reactive-streams", List.of(Relocation.of("reactivestreams", "org{}reactivestreams")) ); @@ -402,7 +364,6 @@ public class Dependencies { "jimfs", "com{}google{}jimfs", "jimfs", - "jimfs", List.of(Relocation.of("jimfs", "com{}google{}common{}jimfs")) ); @@ -410,7 +371,6 @@ public class Dependencies { "commons-imaging", "org{}apache{}commons", "commons-imaging", - "commons-imaging", List.of(Relocation.of("imaging", "org{}apache{}commons{}imaging")) ); @@ -418,7 +378,6 @@ public class Dependencies { "amazon-sdk-s3", "software{}amazon{}awssdk", "s3", - "amazon-s3", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -429,7 +388,6 @@ public class Dependencies { "amazon-sdk-netty-nio-client", "software{}amazon{}awssdk", "netty-nio-client", - "amazon-netty-nio-client", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -445,7 +403,6 @@ public class Dependencies { "amazon-sdk-core", "software{}amazon{}awssdk", "sdk-core", - "amazon-sdk-core", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -461,7 +418,6 @@ public class Dependencies { "amazon-sdk-auth", "software{}amazon{}awssdk", "auth", - "amazon-auth", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -477,7 +433,6 @@ public class Dependencies { "amazon-sdk-regions", "software{}amazon{}awssdk", "regions", - "amazon-regions", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -493,7 +448,6 @@ public class Dependencies { "amazon-sdk-identity-spi", "software{}amazon{}awssdk", "identity-spi", - "amazon-identity-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -509,7 +463,6 @@ public class Dependencies { "amazon-sdk-http-client-spi", "software{}amazon{}awssdk", "http-client-spi", - "amazon-http-client-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -525,7 +478,6 @@ public class Dependencies { "amazon-sdk-protocol-core", "software{}amazon{}awssdk", "protocol-core", - "amazon-protocol-core", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -541,7 +493,6 @@ public class Dependencies { "amazon-sdk-aws-xml-protocol", "software{}amazon{}awssdk", "aws-xml-protocol", - "amazon-aws-xml-protocol", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -557,7 +508,6 @@ public class Dependencies { "amazon-sdk-json-utils", "software{}amazon{}awssdk", "json-utils", - "amazon-json-utils", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -573,7 +523,6 @@ public class Dependencies { "amazon-sdk-aws-core", "software{}amazon{}awssdk", "aws-core", - "amazon-aws-core", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -589,7 +538,6 @@ public class Dependencies { "amazon-sdk-utils", "software{}amazon{}awssdk", "utils", - "amazon-utils", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -605,7 +553,6 @@ public class Dependencies { "amazon-sdk-annotations", "software{}amazon{}awssdk", "annotations", - "amazon-annotations", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -621,7 +568,6 @@ public class Dependencies { "amazon-sdk-crt-core", "software{}amazon{}awssdk", "crt-core", - "amazon-crt-core", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -637,7 +583,6 @@ public class Dependencies { "amazon-sdk-checksums", "software{}amazon{}awssdk", "checksums", - "amazon-checksums", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -653,7 +598,6 @@ public class Dependencies { "amazon-sdk-eventstream", "software{}amazon{}eventstream", "eventstream", - "amazon-eventstream", List.of( Relocation.of("eventstream", "software{}amazon{}eventstream"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -664,7 +608,6 @@ public class Dependencies { "amazon-sdk-profiles", "software{}amazon{}awssdk", "profiles", - "amazon-profiles", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -680,7 +623,6 @@ public class Dependencies { "amazon-sdk-retries", "software{}amazon{}awssdk", "retries", - "amazon-retries", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -696,7 +638,6 @@ public class Dependencies { "amazon-sdk-endpoints-spi", "software{}amazon{}awssdk", "endpoints-spi", - "amazon-endpoints-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -712,7 +653,6 @@ public class Dependencies { "amazon-sdk-arns", "software{}amazon{}awssdk", "arns", - "amazon-arns", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -728,7 +668,6 @@ public class Dependencies { "amazon-sdk-aws-query-protocol", "software{}amazon{}awssdk", "aws-query-protocol", - "amazon-aws-query-protocol", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -744,7 +683,6 @@ public class Dependencies { "amazon-sdk-http-auth-aws", "software{}amazon{}awssdk", "http-auth-aws", - "amazon-http-auth-aws", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -760,7 +698,6 @@ public class Dependencies { "amazon-sdk-http-auth-spi", "software{}amazon{}awssdk", "http-auth-spi", - "amazon-http-auth-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -776,7 +713,6 @@ public class Dependencies { "amazon-sdk-http-auth", "software{}amazon{}awssdk", "http-auth", - "amazon-http-auth", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -792,7 +728,6 @@ public class Dependencies { "amazon-sdk-http-auth-aws-eventstream", "software{}amazon{}awssdk", "http-auth-aws-eventstream", - "amazon-http-auth-aws-eventstream", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -808,7 +743,6 @@ public class Dependencies { "amazon-sdk-checksums-spi", "software{}amazon{}awssdk", "checksums-spi", - "amazon-checksums-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -824,7 +758,6 @@ public class Dependencies { "amazon-sdk-retries-spi", "software{}amazon{}awssdk", "retries-spi", - "amazon-retries-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -840,7 +773,6 @@ public class Dependencies { "amazon-sdk-metrics-spi", "software{}amazon{}awssdk", "metrics-spi", - "amazon-metrics-spi", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") @@ -856,7 +788,6 @@ public class Dependencies { "amazon-sdk-third-party-jackson-core", "software{}amazon{}awssdk", "third-party-jackson-core", - "amazon-third-party-jackson-core", List.of( Relocation.of("awssdk", "software{}amazon{}awssdk"), Relocation.of("reactivestreams", "org{}reactivestreams") diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java index 6a6c7e4b4..6dd449cb9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependency.java @@ -11,14 +11,12 @@ public class Dependency { private final String id; private final String groupId; private final String rawArtifactId; - private final String customArtifactID; private final List relocations; - public Dependency(String id, String groupId, String rawArtifactId, String customArtifactID, List relocations) { + public Dependency(String id, String groupId, String artifactId, List relocations) { this.id = id; this.groupId = groupId; - this.rawArtifactId = rawArtifactId; - this.customArtifactID = customArtifactID; + this.rawArtifactId = artifactId; this.relocations = relocations; } @@ -34,14 +32,14 @@ public class Dependency { return rawArtifactId; } - public String customArtifactID() { - return customArtifactID; - } - public List relocations() { return relocations; } + public String toLocalPath() { + return rewriteEscaping(groupId).replace(".", "/") + "/" + this.rawArtifactId + "/" + getVersion(); + } + private static final String MAVEN_FORMAT = "%s/%s/%s/%s-%s.jar"; public String mavenPath() { @@ -55,7 +53,7 @@ public class Dependency { } public String fileName(String classifier) { - String name = customArtifactID.toLowerCase(Locale.ENGLISH).replace('_', '-'); + String name = this.rawArtifactId.toLowerCase(Locale.ENGLISH).replace('_', '-'); String extra = classifier == null || classifier.isEmpty() ? "" : "-" + classifier; @@ -66,7 +64,7 @@ public class Dependency { return PluginProperties.getValue(id); } - private static String rewriteEscaping(String s) { + public static String rewriteEscaping(String s) { return s.replace("{}", "."); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyManagerImpl.java index 0f3f15376..a6ecf30a3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyManagerImpl.java @@ -5,16 +5,19 @@ import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender; import net.momirealms.craftengine.core.plugin.dependency.classloader.IsolatedClassLoader; import net.momirealms.craftengine.core.plugin.dependency.relocation.Relocation; import net.momirealms.craftengine.core.plugin.dependency.relocation.RelocationHandler; +import net.momirealms.craftengine.core.util.FileUtils; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.DirectoryStream; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; +import java.util.stream.Stream; public class DependencyManagerImpl implements DependencyManager { private final DependencyRegistry registry; @@ -112,18 +115,38 @@ public class DependencyManagerImpl implements DependencyManager { private Path downloadDependency(Dependency dependency) throws DependencyDownloadException { String fileName = dependency.fileName(null); - Path file = this.cacheDirectory.resolve(fileName); + Path file = this.cacheDirectory.resolve(dependency.toLocalPath()).resolve(fileName); // if the file already exists, don't attempt to re-download it. if (Files.exists(file)) { return file; } + // before downloading a newer version, delete those outdated files + Path versionFolder = file.getParent().getParent(); + if (Files.exists(versionFolder) && Files.isDirectory(versionFolder)) { + String version = dependency.getVersion(); + try (Stream dirStream = Files.list(versionFolder)) { + dirStream.filter(Files::isDirectory) + .filter(it -> !it.getFileName().toString().equals(version)) + .forEach(dir -> { + try { + FileUtils.deleteDirectory(dir); + plugin.logger().info("Cleaned up outdated dependency " + dir); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw new RuntimeException("Failed to clean " + versionFolder, e); + } + } + DependencyDownloadException lastError = null; List repository = DependencyRepository.getByID("maven"); if (!repository.isEmpty()) { int i = 0; while (i < repository.size()) { try { - plugin.logger().info("Downloading dependency(" + fileName + ")[" + repository.get(i).getUrl() + dependency.mavenPath() + "]"); + plugin.logger().info("Downloading dependency " + repository.get(i).getUrl() + dependency.mavenPath()); repository.get(i).download(dependency, file); plugin.logger().info("Successfully downloaded " + fileName); return file; @@ -142,7 +165,7 @@ public class DependencyManagerImpl implements DependencyManager { return normalFile; } - Path remappedFile = this.cacheDirectory.resolve(dependency.fileName(DependencyRegistry.isGsonRelocated() ? "remapped-legacy" : "remapped")); + Path remappedFile = this.cacheDirectory.resolve(dependency.toLocalPath()).resolve(dependency.fileName(DependencyRegistry.isGsonRelocated() ? "remapped-legacy" : "remapped")); // if the remapped source exists already, just use that. if (Files.exists(remappedFile)) { @@ -159,6 +182,7 @@ public class DependencyManagerImpl implements DependencyManager { Path cacheDirectory = plugin.dataFolderPath().resolve("libs"); try { if (Files.exists(cacheDirectory) && (Files.isDirectory(cacheDirectory) || Files.isSymbolicLink(cacheDirectory))) { + cleanDirectoryJars(cacheDirectory); return cacheDirectory; } @@ -174,6 +198,16 @@ public class DependencyManagerImpl implements DependencyManager { return cacheDirectory; } + private static void cleanDirectoryJars(Path directory) throws IOException { + try (DirectoryStream stream = Files.newDirectoryStream(directory)) { + for (Path file : stream) { + if (Files.isRegularFile(file) && file.getFileName().toString().endsWith(".jar")) { + Files.delete(file); + } + } + } + } + @Override public void close() { IOException firstEx = null; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyRepository.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyRepository.java index b7f4c0d66..8fe0fa762 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyRepository.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/DependencyRepository.java @@ -82,6 +82,7 @@ public enum DependencyRepository { public void download(Dependency dependency, Path file) throws DependencyDownloadException { try { + Files.createDirectories(file.getParent()); Files.write(file, download(dependency)); } catch (IOException e) { throw new DependencyDownloadException(e); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/FileUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/FileUtils.java index 0de7bd17f..ac23e93a2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/FileUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/FileUtils.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.util; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Comparator; import java.util.List; import java.util.stream.Stream; @@ -19,6 +20,20 @@ public class FileUtils { Files.createDirectories(Files.exists(path) ? path.toRealPath() : path); } + public static void deleteDirectory(Path folder) throws IOException { + if (!Files.exists(folder)) return; + try (Stream walk = Files.walk(folder)) { + walk.sorted(Comparator.reverseOrder()) + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException ioException) { + throw new RuntimeException(ioException); + } + }); + } + } + public static List getYmlConfigsDeeply(Path configFolder) { if (!Files.exists(configFolder)) { return List.of(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/World.java b/core/src/main/java/net/momirealms/craftengine/core/world/World.java index 08efec880..0dacaa8e4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/World.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/World.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.core.world; -import net.kyori.adventure.sound.Sound; import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.sound.SoundData; diff --git a/gradle.properties b/gradle.properties index 2ee29d431..a3b6ef8c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.54.3 +project_version=0.0.54.5 config_version=33 lang_version=13 project_group=net.momirealms @@ -21,7 +21,6 @@ asm_version=9.8 asm_commons_version=9.8 jar_relocator_version=1.7 adventure_bundle_version=4.21.0 -adventure_platform_version=4.4.0 cloud_core_version=2.0.0 cloud_services_version=2.0.0 cloud_brigadier_version=2.0.0-beta.10