diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/Blocks.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/Blocks.java index 1e75d5dd2..2492d9d35 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/blocks/Blocks.java +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/Blocks.java @@ -1,20 +1,30 @@ package com.willfp.eco.core.blocks; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.willfp.eco.core.blocks.args.BlockArgParseResult; +import com.willfp.eco.core.blocks.args.BlockArgParser; import com.willfp.eco.core.blocks.impl.EmptyTestableBlock; import com.willfp.eco.core.blocks.impl.MaterialTestableBlock; +import com.willfp.eco.core.blocks.impl.ModifiedTestableBlock; import com.willfp.eco.core.blocks.impl.UnrestrictedMaterialTestableBlock; import com.willfp.eco.core.blocks.provider.BlockProvider; +import com.willfp.eco.core.blocks.tag.BlockTag; import com.willfp.eco.util.NamespacedKeyUtils; +import com.willfp.eco.util.NumberUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; /** * Class to manage all custom and vanilla blocks. @@ -25,16 +35,55 @@ public final class Blocks { */ private static final Map REGISTRY = new ConcurrentHashMap<>(); + /** + * Cached custom block lookups, using {@link HashedBlock}. + */ + private static final LoadingCache> CACHE = Caffeine.newBuilder() + .expireAfterAccess(10, TimeUnit.MINUTES) + .build( + key -> { + TestableBlock match = null; + for (TestableBlock block : REGISTRY.values()) { + if (block.shouldMarkAsCustom() && block.matches(key.getBlock())) { + match = block; + break; + } + } + + return Optional.ofNullable(match); + } + ); + /** * All block providers. */ private static final Map PROVIDERS = new ConcurrentHashMap<>(); + /** + * All block parsers. + */ + private static final List ARG_PARSERS = new ArrayList<>(); + /** * The lookup handler. */ private static final BlocksLookupHandler BLOCKS_LOOKUP_HANDLER = new BlocksLookupHandler(Blocks::doParse); + /** + * Instance of EmptyTestableBlock. + */ + private static final TestableBlock EMPTY_TESTABLE_BLOCK = new EmptyTestableBlock(); + + /** + * Friendly material names (without underscores, etc.) + */ + private static final Map FRIENDLY_MATERIAL_NAMES = new HashMap<>(); + + /** + * All tags. + */ + private static final Map TAGS = new HashMap<>(); + /** * Register a new custom block. * @@ -55,6 +104,15 @@ public static void registerBlockProvider(@NotNull final BlockProvider provider) PROVIDERS.put(provider.getNamespace(), provider); } + /** + * Register a new arg parser. + * + * @param parser The parser. + */ + public static void registerArgParser(@NotNull final BlockArgParser parser) { + ARG_PARSERS.add(parser); + } + /** * Remove a block. * @@ -64,6 +122,31 @@ public static void removeCustomBlock(@NotNull final NamespacedKey key) { REGISTRY.remove(key); } + /** + * Turn a Block back into a lookup string. + * + * @param block The Block. + * @return The lookup string. + */ + @NotNull + public static String toLookupString(@Nullable final Block block) { + if (block == null) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + + CustomBlock customblock = getCustomBlock(block); + + if (customblock != null) { + builder.append(customblock.getKey()); + } else { + builder.append(block.getType().name().toLowerCase()); + } + + return builder.toString(); + } + /** * This is the backbone of the eco block system. *

@@ -87,38 +170,139 @@ private static TestableBlock doParse(@NotNull final String[] args) { return new EmptyTestableBlock(); } + TestableBlock block = null; + String[] split = args[0].toLowerCase().split(":"); + + String base = split[0]; + boolean isTag = base.startsWith("#"); + + if (isTag) { + String tag = base.substring(1); + BlockTag blockTag = TAGS.get(tag); + + if (blockTag == null) { + return new EmptyTestableBlock(); + } + block = blockTag.toTestableBlock(); + } + if (split.length == 1) { - if (args[0].startsWith("*")) { - Material type = Material.getMaterial(args[0].substring(1)); - return (type == null) ? new EmptyTestableBlock() : new UnrestrictedMaterialTestableBlock(type); - } else { - Material type = Material.getMaterial(args[0].toUpperCase()); - return (type == null) ? new EmptyTestableBlock() : new MaterialTestableBlock(type); + String blockType = args[0]; + boolean isWildcard = blockType.startsWith("*"); + if (isWildcard) { + blockType = blockType.substring(1); + } + Material material = FRIENDLY_MATERIAL_NAMES.get(blockType.toLowerCase()); + if (material == null || material == Material.AIR) { + return new EmptyTestableBlock(); } + block = isWildcard ? new UnrestrictedMaterialTestableBlock(material) : new MaterialTestableBlock(material); } - NamespacedKey namespacedKey = NamespacedKeyUtils.create(split[0], split[1]); - TestableBlock block = REGISTRY.get(namespacedKey); + if (split.length == 2 && !isTag) { + String namespace = split[0]; + String keyID = split[1]; + NamespacedKey namespacedKey = NamespacedKeyUtils.create(namespace, keyID); + TestableBlock part = REGISTRY.get(namespacedKey); - if (block != null) { - return block; - } + if (part == null && PROVIDERS.containsKey(namespace)) { + BlockProvider provider = PROVIDERS.get(namespace); - BlockProvider provider = PROVIDERS.get(split[0]); - if (provider == null) { - return new EmptyTestableBlock(); + String reformattedKey = keyID.replace("__", ":"); + + part = provider.provideForKey(reformattedKey); + if (part instanceof EmptyTestableBlock || part == null) { + return new EmptyTestableBlock(); + } + + registerCustomBlock(namespacedKey, part); + } + + if (part != null) { + block = part; + } } - block = provider.provideForKey(split[1]); if (block == null) { return new EmptyTestableBlock(); } - registerCustomBlock(namespacedKey, block); + if (block instanceof MaterialTestableBlock materialTestableBlock) { + + String[] modifierArgs = Arrays.copyOfRange(args, 1, args.length); + List parseResults = new ArrayList<>(); + + BlockData blockData = materialTestableBlock.getMaterial().createBlockData(); + + for (BlockArgParser argParser : ARG_PARSERS) { + BlockArgParseResult result = argParser.parseArguments(modifierArgs, blockData); + if (result != null) { + parseResults.add(result); + } + } + + Function placer = block::place; + + if (!parseResults.isEmpty()) { + block = new ModifiedTestableBlock( + block, + test -> { + for (BlockArgParseResult parseResult : parseResults) { + if (!parseResult.test().test(test)) { + return false; + } + } + + return true; + }, + location -> { + Block placed = placer.apply(location); + + for (BlockArgParseResult parseResult : parseResults) { + parseResult.modifier().accept(placed); + } + + return placed; + } + ); + } + } + return block; } + /** + * Get a Testable Block from a Block. + *

+ * Will search for registered blocks first. If there are no matches in the registry, + * then it will return a {@link MaterialTestableBlock} matching the block type. + *

+ * Does not account for modifiers (arg parser data). + * + * @param block The Block. + * @return The found Testable Block. + */ + @NotNull + public static TestableBlock getBlock(@Nullable final Block block) { + if (block == null || block.getType().isAir()) { + return new EmptyTestableBlock(); + } + + CustomBlock customBlock = getCustomBlock(block); + + if (customBlock != null) { + return customBlock; + } + + for (TestableBlock known : REGISTRY.values()) { + if (known.matches(block)) { + return known; + } + } + return new MaterialTestableBlock(block.getType()); + } + /** * Get if block is a custom block. * @@ -126,24 +310,172 @@ private static TestableBlock doParse(@NotNull final String[] args) { * @return If is custom. */ public static boolean isCustomBlock(@NotNull final Block block) { - for (TestableBlock testable : REGISTRY.values()) { - if (testable.matches(block)) { + return getCustomBlock(block) != null; + } + + /** + * Get custom block from block. + * + * @param block The block. + * @return The custom block, or null if not exists. + */ + @Nullable + public static CustomBlock getCustomBlock(@Nullable final Block block) { + if (block == null) { + return null; + } + + return CACHE.get(HashedBlock.of(block)).map(Blocks::getOrWrap).orElse(null); + } + + /** + * Get all registered custom blocks. + * + * @return A set of all blocks. + */ + public static Set getCustomBlocks() { + return REGISTRY.values().stream().map(Blocks::getOrWrap).collect(Collectors.toSet()); + } + + /** + * Return a CustomBlock instance for a given TestableBlock. + * + * @param block The block. + * @return The CustomBlock. + */ + @NotNull + public static CustomBlock getOrWrap(@NotNull final TestableBlock block) { + if (block instanceof CustomBlock) { + return (CustomBlock) block; + } else { + return new CustomBlock( + NamespacedKeyUtils.createEcoKey("wrapped_" + NumberUtils.randInt(0, 100000)), + block::matches, + block::place + ); + } + } + + /** + * Convert an array of materials to an array of testable blocks. + * + * @param materials The materials. + * @return An array of functionally identical testable blocks. + */ + @NotNull + public static TestableBlock[] fromMaterials(@NotNull final Material... materials) { + return Arrays.stream(materials) + .filter(Material::isBlock) + .map(MaterialTestableBlock::new) + .toArray(MaterialTestableBlock[]::new); + } + + /** + * Convert a collection of materials into a collection of testable blocks. + * + * @param materials The materials. + * @return A collection of functionally identical testable blocks. + */ + @NotNull + public static Collection fromMaterials(@NotNull final Iterable materials) { + List blocks = new ArrayList<>(); + for (Material material : materials) { + if (material.isBlock()) { + blocks.add(new MaterialTestableBlock(material)); + } + } + + return blocks; + } + + /** + * Get if a block is empty. + * + * @param block The block. + * @return If empty. + */ + public static boolean isEmpty(@Nullable final Block block) { + return EMPTY_TESTABLE_BLOCK.matches(block); + } + + /** + * Get if a block matches any blocks. + * + * @param block The block. + * @param testableBlocks The testable blocks. + * @return If matches any. + */ + public static boolean matchesAny(@Nullable final Block block, + @NotNull final Collection testableBlocks) { + for (TestableBlock testableBlock : testableBlocks) { + if (testableBlock.matches(block)) { return true; } } + return false; } /** * Get all registered custom blocks. * - * @return A set of all blocks. + * @param blocks The blocks. + * @param testableBlocks The testable blocks. + * @return If matches any. + */ + public static boolean matchesAny(@NotNull final Collection blocks, + @NotNull final Collection testableBlocks) { + for (Block block : blocks) { + if (matchesAny(block, testableBlocks)) { + return true; + } + } + + return false; + } + + /** + * Register a new block tag. + * + * @param tag The tag. + */ + public static void registerTag(@NotNull final BlockTag tag) { + TAGS.put(tag.getIdentifier(), tag); + } + + /** + * Get all tags. + * + * @return All tags. */ - public static Set getCustomBlocks() { - return new HashSet<>(REGISTRY.values()); + public static Collection getTags() { + return TAGS.values(); } private Blocks() { throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } + + static { + for (Material material : Material.values()) { + if (!material.isBlock()) continue; // skip not blocks + + FRIENDLY_MATERIAL_NAMES.put(material.name().toLowerCase(), material); + + String oneWord = material.name().toLowerCase().replace("_", ""); + if (!FRIENDLY_MATERIAL_NAMES.containsKey(oneWord)) { + FRIENDLY_MATERIAL_NAMES.put(oneWord, material); + } + + String plural = material.name().toLowerCase() + "s"; + if (!FRIENDLY_MATERIAL_NAMES.containsKey(plural)) { + FRIENDLY_MATERIAL_NAMES.put(plural, material); + } + + String oneWordPlural = oneWord + "s"; + if (!FRIENDLY_MATERIAL_NAMES.containsKey(oneWordPlural)) { + FRIENDLY_MATERIAL_NAMES.put(oneWordPlural, material); + } + } + } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/HashedBlock.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/HashedBlock.java new file mode 100644 index 000000000..0ca08f8b8 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/HashedBlock.java @@ -0,0 +1,76 @@ +package com.willfp.eco.core.blocks; + +import org.bukkit.block.Block; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * A block and its hash. + */ +public final class HashedBlock { + /** + * The block. + */ + private final Block block; + + /** + * The hash. + */ + private final int hash; + + /** + * Create new hashed block. + * + * @param block The block. + * @param hash The hash. + */ + private HashedBlock(@NotNull final Block block, + final int hash) { + this.block = block; + this.hash = hash; + } + + /** + * Get the block. + * + * @return The Block. + */ + public Block getBlock() { + return this.block; + } + + /** + * Get the hash. + * + * @return The hash. + */ + public int getHash() { + return this.hash; + } + + @Override + public int hashCode() { + return this.hash; + } + + @Override + public boolean equals(@Nullable final Object other) { + if (!(other instanceof HashedBlock o)) { + return false; + } + + return o.hash == this.hash; + } + + /** + * Hashed block from a block. + * + * @param block The block. + * @return The hashed block. + */ + public static HashedBlock of(@NotNull final Block block) { + return new HashedBlock(block, Objects.hash(block.getWorld().getName(), block.getX(), block.getY(), block.getZ())); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/TestableBlock.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/TestableBlock.java index aa16e0fe1..b6f33d586 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/blocks/TestableBlock.java +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/TestableBlock.java @@ -28,4 +28,15 @@ public interface TestableBlock extends Testable { */ @NotNull Block place(@NotNull Location location); + + /** + * If a block matching this test should be marked as a custom block. + *

+ * This is true by default for backwards compatibility reasons. + * + * @return If the block should be marked as custom. + */ + default boolean shouldMarkAsCustom() { + return true; + } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/args/BlockArgParseResult.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/args/BlockArgParseResult.java new file mode 100644 index 000000000..ee4435a89 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/args/BlockArgParseResult.java @@ -0,0 +1,37 @@ +package com.willfp.eco.core.blocks.args; + +import com.willfp.eco.core.entities.args.EntityArgParser; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +/** + * The result of an arg parses. + * + * @param test The test for the block. + * @param modifier The modifier to apply to the block. + * @see EntityArgParser + */ +public record BlockArgParseResult(@NotNull Predicate test, + @NotNull Consumer modifier) { + /** + * Kotlin destructuring support. + * + * @return The test. + */ + public Predicate component1() { + return test; + } + + /** + * Kotlin destructuring support. + * + * @return The modifier. + */ + public Consumer component2() { + return modifier; + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/args/BlockArgParser.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/args/BlockArgParser.java new file mode 100644 index 000000000..e18988f22 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/args/BlockArgParser.java @@ -0,0 +1,23 @@ +package com.willfp.eco.core.blocks.args; + +import com.willfp.eco.core.blocks.TestableBlock; +import org.bukkit.Location; +import org.bukkit.block.data.BlockData; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * An argument parser that should generate + * a modified BlockData for {@link TestableBlock#place(Location)} . + */ +public interface BlockArgParser { + /** + * Parse the arguments. + * + * @param args The arguments. + * @param blockData The block data to be modified. + * @return The modified block data. + */ + @Nullable BlockArgParseResult parseArguments(@NotNull String[] args, + @NotNull BlockData blockData); +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/EmptyTestableBlock.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/EmptyTestableBlock.java index 190470eb4..301e46791 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/EmptyTestableBlock.java +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/EmptyTestableBlock.java @@ -1,6 +1,7 @@ package com.willfp.eco.core.blocks.impl; import com.willfp.eco.core.blocks.TestableBlock; +import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.block.Block; import org.jetbrains.annotations.NotNull; @@ -24,6 +25,8 @@ public boolean matches(@Nullable final Block other) { @Override public @NotNull Block place(@NotNull final Location location) { + Validate.notNull(location.getWorld()); + return location.getBlock(); } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/MaterialTestableBlock.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/MaterialTestableBlock.java index 713e069c3..82af42b3a 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/MaterialTestableBlock.java +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/MaterialTestableBlock.java @@ -6,6 +6,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,10 +17,10 @@ public class MaterialTestableBlock implements TestableBlock { /** * The block type. */ - private final Material material; + protected final Material material; /** - * Create a new unrestricted material testable block. + * Create a new block data testable block. * * @param material The material. */ @@ -42,16 +43,16 @@ public boolean matches(@Nullable final Block block) { public @NotNull Block place(@NotNull Location location) { Validate.notNull(location.getWorld()); - Block block = location.getWorld().getBlockAt(location); + Block block = location.getBlock(); block.setType(material); return block; } /** - * Get the material. + * Get the block data. * - * @return The material. + * @return The block data. */ public Material getMaterial() { return this.material; diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/ModifiedTestableBlock.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/ModifiedTestableBlock.java new file mode 100644 index 000000000..19dc07407 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/ModifiedTestableBlock.java @@ -0,0 +1,69 @@ +package com.willfp.eco.core.blocks.impl; + +import com.willfp.eco.core.blocks.TestableBlock; +import org.apache.commons.lang.Validate; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * Existing testable block with an extra function. + * + * @see com.willfp.eco.core.entities.CustomEntity + */ +public class ModifiedTestableBlock implements TestableBlock { + /** + * The block. + */ + private final TestableBlock handle; + + /** + * The data. + */ + private final Predicate test; + + /** + * The provider to place a block. + */ + private final Function provider; + + /** + * Create a new modified testable block. + * + * @param block The base block. + * @param test The test. + * @param provider The provider to place a block. + */ + public ModifiedTestableBlock(@NotNull final TestableBlock block, + @NotNull final Predicate<@NotNull Block> test, + @NotNull final Function provider) { + this.handle = block; + this.test = test; + this.provider = provider; + } + + @Override + public boolean matches(@Nullable final Block block) { + return block != null && handle.matches(block) && test.test(block); + } + + @Override + public @NotNull Block place(@NotNull final Location location) { + Validate.notNull(location.getWorld()); + + return provider.apply(location); + } + + /** + * Get the handle. + * + * @return The handle. + */ + public TestableBlock getHandle() { + return this.handle; + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/UnrestrictedMaterialTestableBlock.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/UnrestrictedMaterialTestableBlock.java index 498c07aba..51d915eec 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/UnrestrictedMaterialTestableBlock.java +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/impl/UnrestrictedMaterialTestableBlock.java @@ -1,6 +1,5 @@ package com.willfp.eco.core.blocks.impl; -import com.willfp.eco.core.blocks.TestableBlock; import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.Material; @@ -11,11 +10,7 @@ /** * A testable block for materials regardless of data. */ -public class UnrestrictedMaterialTestableBlock implements TestableBlock { - /** - * The block type. - */ - private final Material material; +public class UnrestrictedMaterialTestableBlock extends MaterialTestableBlock { /** * Create a new unrestricted material testable block. @@ -23,7 +18,7 @@ public class UnrestrictedMaterialTestableBlock implements TestableBlock { * @param material The material. */ public UnrestrictedMaterialTestableBlock(@NotNull final Material material) { - this.material = material; + super(material); } @Override @@ -40,13 +35,4 @@ public boolean matches(@Nullable final Block other) { return block; } - - /** - * Get the material. - * - * @return The material. - */ - public Material getMaterial() { - return this.material; - } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/BlockTag.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/BlockTag.java new file mode 100644 index 000000000..300288e62 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/BlockTag.java @@ -0,0 +1,55 @@ +package com.willfp.eco.core.blocks.tag; + +import com.willfp.eco.core.blocks.TestableBlock; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A group of blocks that share a common trait. + */ +public interface BlockTag { + /** + * Get the identifier of the tag. + * + * @return The identifier. + */ + @NotNull + String getIdentifier(); + + /** + * Check if a block matches the tag. + * + * @param block The block to check. + * @return If the block matches the tag. + */ + boolean matches(@NotNull Block block); + + /** + * Convert this tag to a testable block. + * + * @return The testable block. + */ + @NotNull + default TestableBlock toTestableBlock() { + return new TestableBlock() { + @Override + public boolean matches(@Nullable final Block block) { + return block != null && BlockTag.this.matches(block); + } + + @Override + public @NotNull Block place(@NotNull final Location location) { + return location.getBlock(); + } + + @Override + public String toString() { + return "BlockTagTestableBlock{" + + "tag=" + BlockTag.this.getIdentifier() + + '}'; + } + }; + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/CustomBlockTag.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/CustomBlockTag.java new file mode 100644 index 000000000..cfaf76315 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/CustomBlockTag.java @@ -0,0 +1,29 @@ +package com.willfp.eco.core.blocks.tag; + +import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; + +/** + * A custom block tag. + */ +public abstract class CustomBlockTag implements BlockTag { + /** + * The key. + */ + private final NamespacedKey key; + + /** + * Create a new custom block tag. + * + * @param key The key. + */ + public CustomBlockTag(@NotNull final NamespacedKey key) { + this.key = key; + } + + @Override + @NotNull + public String getIdentifier() { + return key.toString(); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/VanillaBlockTag.java b/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/VanillaBlockTag.java new file mode 100644 index 000000000..fa8c3e80f --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/blocks/tag/VanillaBlockTag.java @@ -0,0 +1,53 @@ +package com.willfp.eco.core.blocks.tag; + +import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.jetbrains.annotations.NotNull; + +/** + * A vanilla block tag. + */ +public final class VanillaBlockTag implements BlockTag { + /** + * The identifier. + */ + private final String identifier; + + /** + * The tag. + */ + private final Tag tag; + + /** + * Create a new vanilla block tag. + * + * @param identifier The identifier. + * @param tag The tag. + */ + public VanillaBlockTag(@NotNull final String identifier, + @NotNull final Tag tag) { + this.identifier = identifier; + this.tag = tag; + } + + /** + * Get the tag. + * + * @return The tag. + */ + public Tag getTag() { + return tag; + } + + @Override + @NotNull + public String getIdentifier() { + return identifier; + } + + @Override + public boolean matches(@NotNull final Block block) { + return tag.isTagged(block.getType()); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/items/Items.java b/eco-api/src/main/java/com/willfp/eco/core/items/Items.java index f0b6047cc..643e22603 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/items/Items.java +++ b/eco-api/src/main/java/com/willfp/eco/core/items/Items.java @@ -324,11 +324,10 @@ private static TestableItem doParse(@NotNull final String[] args) { List> predicates = new ArrayList<>(); - for ( - LookupArgParser argParser : ARG_PARSERS) { + for (LookupArgParser argParser : ARG_PARSERS) { Predicate predicate = argParser.parseArguments(modifierArgs, meta); if (predicate != null) { - predicates.add(argParser.parseArguments(modifierArgs, meta)); + predicates.add(predicate); } } diff --git a/eco-api/src/main/kotlin/com/willfp/eco/core/blocks/Blocks.kt b/eco-api/src/main/kotlin/com/willfp/eco/core/blocks/Blocks.kt new file mode 100644 index 000000000..371c34685 --- /dev/null +++ b/eco-api/src/main/kotlin/com/willfp/eco/core/blocks/Blocks.kt @@ -0,0 +1,26 @@ +@file:JvmName("BlocksExtensions") + +package com.willfp.eco.core.blocks + +import org.bukkit.block.Block + +/** @see Blocks.toLookupString */ +fun Block?.toLookupString(): String = + Blocks.toLookupString(this) + +/** @see Blocks.isEmpty */ +@Deprecated("Use Blocks.isEcoEmpty", ReplaceWith("Block.isEmpty(this)")) +val Block?.isEmpty: Boolean + get() = Blocks.isEmpty(this) + +/** @see Block.isEmpty */ +val Block?.isEcoEmpty: Boolean + get() = Blocks.isEmpty(this) + +/** @see Blocks.matchesAny */ +fun Collection.matches(block: Block): Boolean = + Blocks.matchesAny(block, this) + +/** @see Blocks.matchesAny */ +fun Collection.matches(blocks: Collection): Boolean = + Blocks.matchesAny(blocks, this) diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAgeable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAgeable.kt new file mode 100644 index 000000000..feea77914 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAgeable.kt @@ -0,0 +1,56 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.Ageable +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Sapling + +object BlockArgParserAgeable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val maximumAge = when (blockData) { + is Ageable -> blockData.maximumAge + is Sapling -> blockData.maximumStage + else -> return null + } + var age: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("age", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argAge = argSplit[1].toIntOrNull() ?: continue + if (argAge in (maximumAge + 1)..<0) { + continue + } + age = argAge + } + + age ?: return null + + return BlockArgParseResult( + { + when (val data = it.blockData) { + is Ageable -> data.age == age + is Sapling -> data.stage == age + else -> false + } + }, + { + val data = it.blockData + + when (data) { + is Ageable -> data.age = age + is Sapling -> data.stage = age + else -> return@BlockArgParseResult + } + + it.blockData = data + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAnaloguePowerable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAnaloguePowerable.kt new file mode 100644 index 000000000..57e521669 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAnaloguePowerable.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.AnaloguePowerable +import org.bukkit.block.data.BlockData + +object BlockArgParserAnaloguePowerable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val analoguePowerable = blockData as? AnaloguePowerable ?: return null + var power: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("power", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argPower = argSplit[1].toIntOrNull() ?: continue + if (argPower in (analoguePowerable.maximumPower + 1)..<0) { + continue + } + power = argPower + } + + power ?: return null + + return BlockArgParseResult( + { + val analoguePowerable = it.blockData as? AnaloguePowerable ?: return@BlockArgParseResult false + + analoguePowerable.power == power + }, + { + val analoguePowerable = it.blockData as? AnaloguePowerable ?: return@BlockArgParseResult + + analoguePowerable.power = power + it.blockData = analoguePowerable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAttachable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAttachable.kt new file mode 100644 index 000000000..f9b5c4ac3 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserAttachable.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.Attachable +import org.bukkit.block.data.BlockData + +object BlockArgParserAttachable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Attachable) return null + var attached: Boolean? = null + + for (arg in args) { + if (arg.equals("attached", true)) { + attached = true + } + } + + attached ?: return null + + return BlockArgParseResult( + { + val attachable = it.blockData as? Attachable ?: return@BlockArgParseResult false + + attachable.isAttached == attached + }, + { + val attachable = it.blockData as? Attachable ?: return@BlockArgParseResult + + attachable.isAttached = attached + it.blockData = attachable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBamboo.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBamboo.kt new file mode 100644 index 000000000..35e28a91c --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBamboo.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Bamboo + +object BlockArgParserBamboo : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Bamboo) return null + var bambooLeaves: Bamboo.Leaves? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("leaves", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + bambooLeaves = runCatching { Bamboo.Leaves.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + bambooLeaves ?: return null + + return BlockArgParseResult( + { + val bamboo = it.blockData as? Bamboo ?: return@BlockArgParseResult false + + bamboo.leaves == bambooLeaves + }, + { + val bamboo = it.blockData as? Bamboo ?: return@BlockArgParseResult + + bamboo.leaves = bambooLeaves + it.blockData = bamboo + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBisected.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBisected.kt new file mode 100644 index 000000000..e777117db --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBisected.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.Bisected +import org.bukkit.block.data.BlockData + +object BlockArgParserBisected : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Bisected) return null + var bisectedHalf: Bisected.Half? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("bisected", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + bisectedHalf = runCatching { Bisected.Half.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + bisectedHalf ?: return null + + return BlockArgParseResult( + { + val bisected = it.blockData as? Bisected ?: return@BlockArgParseResult false + + bisected.half == bisectedHalf + }, + { + val bisected = it.blockData as? Bisected ?: return@BlockArgParseResult + + bisected.half = bisectedHalf + it.blockData = bisected + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBubbleColumn.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBubbleColumn.kt new file mode 100644 index 000000000..145f2d039 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserBubbleColumn.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.BubbleColumn + +object BlockArgParserBubbleColumn : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is BubbleColumn) return null + var drag: Boolean? = null + + for (arg in args) { + if (arg.equals("drag", true)) { + drag = true + } + } + + drag ?: return null + + return BlockArgParseResult( + { + val bubbleColumn = it.blockData as? BubbleColumn ?: return@BlockArgParseResult false + + bubbleColumn.isDrag == drag + }, + { + val bubbleColumn = it.blockData as? BubbleColumn ?: return@BlockArgParseResult + + bubbleColumn.isDrag = drag + it.blockData = bubbleColumn + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCake.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCake.kt new file mode 100644 index 000000000..5cba8af5f --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCake.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Cake + +object BlockArgParserCake : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val cake = blockData as? Cake ?: return null + var bites: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("bites", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argBites = argSplit[1].toIntOrNull() ?: continue + if (argBites in (cake.maximumBites + 1)..<0) { + continue + } + bites = argBites + } + + bites ?: return null + + return BlockArgParseResult( + { + val cake = it.blockData as? Cake ?: return@BlockArgParseResult false + + cake.bites == bites + }, + { + val cake = it.blockData as? Cake ?: return@BlockArgParseResult + + cake.bites = bites + it.blockData = cake + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCampfire.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCampfire.kt new file mode 100644 index 000000000..2d5106449 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCampfire.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Campfire + +object BlockArgParserCampfire : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Campfire) return null + var signalFire: Boolean? = null + + for (arg in args) { + if (arg.equals("signal_fire", true)) { + signalFire = true + } + } + + signalFire ?: return null + + return BlockArgParseResult( + { + val campfire = it.blockData as? Campfire ?: return@BlockArgParseResult false + + campfire.isSignalFire == signalFire + }, + { + val campfire = it.blockData as? Campfire ?: return@BlockArgParseResult + + campfire.isSignalFire = signalFire + it.blockData = campfire + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCaveVinesPlant.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCaveVinesPlant.kt new file mode 100644 index 000000000..e9667be63 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCaveVinesPlant.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.CaveVinesPlant + +object BlockArgParserCaveVinesPlant : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is CaveVinesPlant) return null + var berries: Boolean? = null + + for (arg in args) { + if (arg.equals("berries", true)) { + berries = true + } + } + + berries ?: return null + + return BlockArgParseResult( + { + val caveVinesPlant = it.blockData as? CaveVinesPlant ?: return@BlockArgParseResult false + + caveVinesPlant.isBerries == berries + }, + { + val caveVinesPlant = it.blockData as? CaveVinesPlant ?: return@BlockArgParseResult + + caveVinesPlant.isBerries = berries + it.blockData = caveVinesPlant + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserChest.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserChest.kt new file mode 100644 index 000000000..af86805d4 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserChest.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Chest + +object BlockArgParserChest : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Chest) return null + var chestType: Chest.Type? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("type", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + chestType = runCatching { Chest.Type.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + chestType ?: return null + + return BlockArgParseResult( + { + val chest = it.blockData as? Chest ?: return@BlockArgParseResult false + + chest.type == chestType + }, + { + val chest = it.blockData as? Chest ?: return@BlockArgParseResult + + chest.type = chestType + it.blockData = chest + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCommandBlock.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCommandBlock.kt new file mode 100644 index 000000000..f6727ae93 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCommandBlock.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.CommandBlock + +object BlockArgParserCommandBlock : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is CommandBlock) return null + var conditional: Boolean? = null + + for (arg in args) { + if (arg.equals("conditional", true)) { + conditional = true + } + } + + conditional ?: return null + + return BlockArgParseResult( + { + val commandBlock = it.blockData as? CommandBlock ?: return@BlockArgParseResult false + + commandBlock.isConditional == conditional + }, + { + val commandBlock = it.blockData as? CommandBlock ?: return@BlockArgParseResult + + commandBlock.isConditional = conditional + it.blockData = commandBlock + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserComparator.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserComparator.kt new file mode 100644 index 000000000..1ff13d5a3 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserComparator.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Comparator + +object BlockArgParserComparator : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Comparator) return null + var comparatorMode: Comparator.Mode? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("mode", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + comparatorMode = runCatching { Comparator.Mode.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + comparatorMode ?: return null + + return BlockArgParseResult( + { + val comparator = it.blockData as? Comparator ?: return@BlockArgParseResult false + + comparator.mode == comparatorMode + }, + { + val comparator = it.blockData as? Comparator ?: return@BlockArgParseResult + + comparator.mode = comparatorMode + it.blockData = comparator + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCrafter.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCrafter.kt new file mode 100644 index 000000000..e539c6aae --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserCrafter.kt @@ -0,0 +1,52 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Crafter + +object BlockArgParserCrafter : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Crafter) return null + + var orientation: Crafter.Orientation? = null + var triggered: Boolean? = null + var crafting: Boolean? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("orientation", true)) { + if (argSplit.size < 2) { + continue + } + orientation = + runCatching { Crafter.Orientation.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } else if (argSplit[0].equals("triggered", true)) { + triggered = true + } else if (argSplit[0].equals("crafting", true)) { + crafting = true + } + } + + if (orientation == null && triggered == null && crafting == null) return null + + return BlockArgParseResult( + { + val crafter = it.blockData as? Crafter ?: return@BlockArgParseResult false + + (orientation == null || crafter.orientation == orientation) && + (triggered == null || crafter.isTriggered == triggered) && + (crafting == null || crafter.isCrafting == crafting) + }, + { + val crafter = it.blockData as? Crafter ?: return@BlockArgParseResult + + if (orientation != null) crafter.orientation = orientation + if (triggered != null) crafter.isTriggered = triggered + if (crafting != null) crafter.isCrafting = crafting + + it.blockData = crafter + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDaylightDetector.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDaylightDetector.kt new file mode 100644 index 000000000..82bce4871 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDaylightDetector.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.DaylightDetector + +object BlockArgParserDaylightDetector : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is DaylightDetector) return null + var inverted: Boolean? = null + + for (arg in args) { + if (arg.equals("inverted", true)) { + inverted = true + } + } + + inverted ?: return null + + return BlockArgParseResult( + { + val daylightDetector = it.blockData as? DaylightDetector ?: return@BlockArgParseResult false + + daylightDetector.isInverted == inverted + }, + { + val daylightDetector = it.blockData as? DaylightDetector ?: return@BlockArgParseResult + + daylightDetector.isInverted = inverted + it.blockData = daylightDetector + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDirectional.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDirectional.kt new file mode 100644 index 000000000..44799af52 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDirectional.kt @@ -0,0 +1,41 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Directional + +object BlockArgParserDirectional : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val directional = blockData as? Directional ?: return null + var direction: BlockFace? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("direction", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + direction = directional.faces.firstOrNull { it.name.equals(argSplit[1].uppercase(), true) } ?: continue + } + + direction ?: return null + + return BlockArgParseResult( + { + val directional = it.blockData as? Directional ?: return@BlockArgParseResult false + + directional.facing == direction + }, + { + val directional = it.blockData as? Directional ?: return@BlockArgParseResult + + directional.facing = direction + it.blockData = directional + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDispenser.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDispenser.kt new file mode 100644 index 000000000..a9e42f575 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDispenser.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Dispenser + +object BlockArgParserDispenser : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Dispenser) return null + var triggered: Boolean? = null + + for (arg in args) { + if (arg.equals("triggered", true)) { + triggered = true + } + } + + triggered ?: return null + + return BlockArgParseResult( + { + val dispenser = it.blockData as? Dispenser ?: return@BlockArgParseResult false + + dispenser.isTriggered == triggered + }, + { + val dispenser = it.blockData as? Dispenser ?: return@BlockArgParseResult + + dispenser.isTriggered = triggered + it.blockData = dispenser + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDoor.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDoor.kt new file mode 100644 index 000000000..27764ff81 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserDoor.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Door + +object BlockArgParserDoor : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Door) return null + var doorHinge: Door.Hinge? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("hinge", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + doorHinge = runCatching { Door.Hinge.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + doorHinge ?: return null + + return BlockArgParseResult( + { + val door = it.blockData as? Door ?: return@BlockArgParseResult false + + door.hinge == doorHinge + }, + { + val door = it.blockData as? Door ?: return@BlockArgParseResult + + door.hinge = doorHinge + it.blockData = door + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserEndPortalFrame.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserEndPortalFrame.kt new file mode 100644 index 000000000..43ba6bcb8 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserEndPortalFrame.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.EndPortalFrame + +object BlockArgParserEndPortalFrame : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is EndPortalFrame) return null + var eye: Boolean? = null + + for (arg in args) { + if (arg.equals("eye", true)) { + eye = true + } + } + + eye ?: return null + + return BlockArgParseResult( + { + val endPortalFrame = it.blockData as? EndPortalFrame ?: return@BlockArgParseResult false + + endPortalFrame.hasEye() == eye + }, + { + val endPortalFrame = it.blockData as? EndPortalFrame ?: return@BlockArgParseResult + + endPortalFrame.setEye(eye) + it.blockData = endPortalFrame + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserFaceAttachable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserFaceAttachable.kt new file mode 100644 index 000000000..687b6c596 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserFaceAttachable.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.FaceAttachable + +object BlockArgParserFaceAttachable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is FaceAttachable) return null + var attachedFace: FaceAttachable.AttachedFace? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("attached_face", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + attachedFace = runCatching { FaceAttachable.AttachedFace.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + attachedFace ?: return null + + return BlockArgParseResult( + { + val faceAttachable = it.blockData as? FaceAttachable ?: return@BlockArgParseResult false + + faceAttachable.attachedFace == attachedFace + }, + { + val faceAttachable = it.blockData as? FaceAttachable ?: return@BlockArgParseResult + + faceAttachable.attachedFace = attachedFace + it.blockData = faceAttachable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserFarmland.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserFarmland.kt new file mode 100644 index 000000000..a4d5d5265 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserFarmland.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Farmland + +object BlockArgParserFarmland : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val farmland = blockData as? Farmland ?: return null + var moisture: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("moisture", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argMoisture = argSplit[1].toIntOrNull() ?: continue + if (argMoisture in (farmland.maximumMoisture + 1)..<0) { + continue + } + moisture = argMoisture + } + + moisture ?: return null + + return BlockArgParseResult( + { + val farmland = it.blockData as? Farmland ?: return@BlockArgParseResult false + + farmland.moisture == moisture + }, + { + val farmland = it.blockData as? Farmland ?: return@BlockArgParseResult + + farmland.moisture = moisture + it.blockData = farmland + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserGate.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserGate.kt new file mode 100644 index 000000000..60fae3a5e --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserGate.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Gate + +object BlockArgParserGate : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Gate) return null + var inWall: Boolean? = null + + for (arg in args) { + if (arg.equals("in_wall", true)) { + inWall = true + } + } + + inWall ?: return null + + return BlockArgParseResult( + { + val gate = it.blockData as? Gate ?: return@BlockArgParseResult false + + gate.isInWall == inWall + }, + { + val gate = it.blockData as? Gate ?: return@BlockArgParseResult + + gate.isInWall = inWall + it.blockData = gate + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserHangable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserHangable.kt new file mode 100644 index 000000000..f25b7ae85 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserHangable.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Hangable + +object BlockArgParserHangable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Hangable) return null + var hanging: Boolean? = null + + for (arg in args) { + if (arg.equals("hanging", true)) { + hanging = true + } + } + + hanging ?: return null + + return BlockArgParseResult( + { + val hangable = it.blockData as? Hangable ?: return@BlockArgParseResult false + + hangable.isHanging == hanging + }, + { + val hangable = it.blockData as? Hangable ?: return@BlockArgParseResult + + hangable.isHanging = hanging + it.blockData = hangable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserHangingMoss.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserHangingMoss.kt new file mode 100644 index 000000000..d4c92899b --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserHangingMoss.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.HangingMoss + +object BlockArgParserHangingMoss : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is HangingMoss) return null + var tip: Boolean? = null + + for (arg in args) { + if (arg.equals("tip", true)) { + tip = true + } + } + + tip ?: return null + + return BlockArgParseResult( + { + val hangingMoss = it.blockData as? HangingMoss ?: return@BlockArgParseResult false + + hangingMoss.isTip == tip + }, + { + val hangingMoss = it.blockData as? HangingMoss ?: return@BlockArgParseResult + + hangingMoss.isTip = tip + it.blockData = hangingMoss + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserJigsaw.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserJigsaw.kt new file mode 100644 index 000000000..e3b962e27 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserJigsaw.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Jigsaw + +object BlockArgParserJigsaw : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Jigsaw) return null + var orientation: Jigsaw.Orientation? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("orientation", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + orientation = runCatching { Jigsaw.Orientation.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + orientation ?: return null + + return BlockArgParseResult( + { + val jigsaw = it.blockData as? Jigsaw ?: return@BlockArgParseResult false + + jigsaw.orientation == orientation + }, + { + val jigsaw = it.blockData as? Jigsaw ?: return@BlockArgParseResult + + jigsaw.orientation = orientation + it.blockData = jigsaw + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserLevelled.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserLevelled.kt new file mode 100644 index 000000000..f1c9776a3 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserLevelled.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Levelled + +object BlockArgParserLevelled : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val levelled = blockData as? Levelled ?: return null + var level: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("level", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argLevel = argSplit[1].toIntOrNull() ?: continue + if (argLevel in (levelled.maximumLevel + 1)..<0) { + continue + } + level = argLevel + } + + level ?: return null + + return BlockArgParseResult( + { + val levelled = it.blockData as? Levelled ?: return@BlockArgParseResult false + + levelled.level == level + }, + { + val levelled = it.blockData as? Levelled ?: return@BlockArgParseResult + + levelled.level = level + it.blockData = levelled + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserLightable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserLightable.kt new file mode 100644 index 000000000..4a518e3c8 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserLightable.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Lightable + +object BlockArgParserLightable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Lightable) return null + var lit: Boolean? = null + + for (arg in args) { + if (arg.equals("lit", true)) { + lit = true + } + } + + lit ?: return null + + return BlockArgParseResult( + { + val lightable = it.blockData as? Lightable ?: return@BlockArgParseResult false + + lightable.isLit == lit + }, + { + val lightable = it.blockData as? Lightable ?: return@BlockArgParseResult + + lightable.isLit = lit + it.blockData = lightable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserMossyCarpet.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserMossyCarpet.kt new file mode 100644 index 000000000..e455b474f --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserMossyCarpet.kt @@ -0,0 +1,48 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.MossyCarpet + +object BlockArgParserMossyCarpet : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is MossyCarpet) return null + + val mossyCarpetHeight = BlockFace.entries.associateWith { MossyCarpet.Height.NONE }.toMutableMap() + var mossyCarpetBottom: Boolean? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("height", true)) { + if (argSplit.size < 3) { + continue + } + val face = runCatching { BlockFace.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + val height = runCatching { MossyCarpet.Height.valueOf(argSplit[2].uppercase()) }.getOrNull() ?: continue + mossyCarpetHeight[face] = height + } else if (argSplit[0].equals("bottom", true)) { + mossyCarpetBottom = true + } + } + + return BlockArgParseResult( + { + val mossyCarpet = it.blockData as? MossyCarpet ?: return@BlockArgParseResult false + + BlockFace.entries.all { face -> + mossyCarpetHeight[face] == mossyCarpet.getHeight(face) + } && (mossyCarpetBottom == null || mossyCarpet.isBottom == mossyCarpetBottom) + }, + { + val mossyCarpet = it.blockData as? MossyCarpet ?: return@BlockArgParseResult + + mossyCarpetHeight.forEach { carpet -> mossyCarpet.setHeight(carpet.key, carpet.value) } + if (mossyCarpetBottom != null) mossyCarpet.isBottom = mossyCarpetBottom + + it.blockData = mossyCarpet + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserMultipleFacing.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserMultipleFacing.kt new file mode 100644 index 000000000..8181c115b --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserMultipleFacing.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.MultipleFacing + +object BlockArgParserMultipleFacing : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val multipleFacing = blockData as? MultipleFacing ?: return null + + val faces = multipleFacing.allowedFaces.associateWith { false }.toMutableMap() + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("face", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + + val face = multipleFacing.allowedFaces.firstOrNull { it.name.equals(argSplit[1].uppercase(), true) } ?: continue + faces[face] = true + } + + return BlockArgParseResult( + { + val multipleFacing = it.blockData as? MultipleFacing ?: return@BlockArgParseResult false + + multipleFacing.allowedFaces.all { face -> + faces[face] == multipleFacing.hasFace(face) + } + }, + { + val multipleFacing = it.blockData as? MultipleFacing ?: return@BlockArgParseResult + + faces.forEach { facing -> multipleFacing.setFace(facing.key, facing.value) } + + it.blockData = multipleFacing + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserNoteBlock.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserNoteBlock.kt new file mode 100644 index 000000000..35cf85bfe --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserNoteBlock.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.Instrument +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.NoteBlock + +object BlockArgParserNoteBlock : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is NoteBlock) return null + var instrument: Instrument? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("instrument", true)) { + if (argSplit.size < 2) { + continue + } + instrument = runCatching { Instrument.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } // TODO: notes + } + + instrument ?: return null + + return BlockArgParseResult( + { + val noteBlock = it.blockData as? NoteBlock ?: return@BlockArgParseResult false + + noteBlock.instrument == instrument + }, + { + val noteBlock = it.blockData as? NoteBlock ?: return@BlockArgParseResult + + noteBlock.instrument = instrument + it.blockData = noteBlock + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserOpenable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserOpenable.kt new file mode 100644 index 000000000..58daa7932 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserOpenable.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Openable + +object BlockArgParserOpenable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Openable) return null + var open: Boolean? = null + + for (arg in args) { + if (arg.equals("open", true)) { + open = true + } + } + + open ?: return null + + return BlockArgParseResult( + { + val openable = it.blockData as? Openable ?: return@BlockArgParseResult false + + openable.isOpen == open + }, + { + val openable = it.blockData as? Openable ?: return@BlockArgParseResult + + openable.isOpen = open + it.blockData = openable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserOrientable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserOrientable.kt new file mode 100644 index 000000000..e0dca0bbb --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserOrientable.kt @@ -0,0 +1,41 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.Axis +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Orientable + +object BlockArgParserOrientable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val orientable = blockData as? Orientable ?: return null + var axis: Axis? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("axis", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + axis = orientable.axes.firstOrNull { it.name.equals(argSplit[1].uppercase(), true) } ?: continue + } + + axis ?: return null + + return BlockArgParseResult( + { + val orientable = it.blockData as? Orientable ?: return@BlockArgParseResult false + + orientable.axis == axis + }, + { + val orientable = it.blockData as? Orientable ?: return@BlockArgParseResult + + orientable.axis = axis + it.blockData = orientable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserPointedDripstone.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserPointedDripstone.kt new file mode 100644 index 000000000..6df026474 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserPointedDripstone.kt @@ -0,0 +1,54 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.PointedDripstone + +object BlockArgParserPointedDripstone : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val pointedDripstone = blockData as? PointedDripstone ?: return null + + var thickness: PointedDripstone.Thickness? = null + var verticalDirection: BlockFace? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("direction", true)) { + if (argSplit.size < 2) { + continue + } + verticalDirection = pointedDripstone.verticalDirections.firstOrNull { + it.name.equals(argSplit[1].uppercase(), true) + } ?: continue + } else if (argSplit[0].equals("thickness", true)) { + if (argSplit.size < 2) { + continue + } + thickness = + runCatching { PointedDripstone.Thickness.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + } + + if (verticalDirection == null && thickness == null) return null + + return BlockArgParseResult( + { + val pointedDripstone = it.blockData as? PointedDripstone ?: return@BlockArgParseResult false + + (verticalDirection == null || pointedDripstone.verticalDirection == verticalDirection) && + (thickness == null || pointedDripstone.thickness == thickness) + }, + { + val pointedDripstone = it.blockData as? PointedDripstone ?: return@BlockArgParseResult + + if (verticalDirection != null) pointedDripstone.verticalDirection = verticalDirection + if (thickness != null) pointedDripstone.thickness = thickness + + it.blockData = pointedDripstone + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserPowerable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserPowerable.kt new file mode 100644 index 000000000..4a504d4c5 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserPowerable.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Powerable + +object BlockArgParserPowerable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Powerable) return null + var powered: Boolean? = null + + for (arg in args) { + if (arg.equals("powered", true)) { + powered = true + } + } + + powered ?: return null + + return BlockArgParseResult( + { + val powerable = it.blockData as? Powerable ?: return@BlockArgParseResult false + + powerable.isPowered == powered + }, + { + val powerable = it.blockData as? Powerable ?: return@BlockArgParseResult + + powerable.isPowered = powered + it.blockData = powerable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserQuantity.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserQuantity.kt new file mode 100644 index 000000000..038392661 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserQuantity.kt @@ -0,0 +1,69 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Hatchable +import org.bukkit.block.data.type.Candle +import org.bukkit.block.data.type.SeaPickle +import org.bukkit.block.data.type.TurtleEgg + +object BlockArgParserQuantity : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val maximumQuantity = when (val blockData = blockData) { + is TurtleEgg -> blockData.maximumEggs + is Candle -> blockData.maximumCandles + is SeaPickle -> blockData.maximumPickles + is Hatchable -> blockData.maximumHatch + else -> return null + } + val minimumQuantity = when (val blockData = blockData) { + is TurtleEgg -> blockData.minimumEggs + else -> 0 + } + + var quantity: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("quantity", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argQuantity = argSplit[1].toIntOrNull() ?: continue + if (argQuantity in (maximumQuantity + 1).. data.eggs == quantity + is Candle -> data.candles == quantity + is SeaPickle -> data.pickles == quantity + is Hatchable -> data.hatch == quantity + else -> false + } + }, + { + val data = it.blockData + + when (data) { + is Candle -> data.candles = quantity + is SeaPickle -> data.pickles = quantity + is TurtleEgg -> data.eggs = quantity + is Hatchable -> data.hatch = quantity + else -> return@BlockArgParseResult + } + + it.blockData = data + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRail.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRail.kt new file mode 100644 index 000000000..f36d7db0d --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRail.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Rail + +object BlockArgParserRail : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val rail = blockData as? Rail ?: return null + var shape: Rail.Shape? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("shape", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + shape = rail.shapes.firstOrNull { it.name.equals(argSplit[1].uppercase(), true) } ?: continue + } + + shape ?: return null + + return BlockArgParseResult( + { + val rail = it.blockData as? Rail ?: return@BlockArgParseResult false + + rail.shape == shape + }, + { + val rail = it.blockData as? Rail ?: return@BlockArgParseResult + + rail.shape = shape + it.blockData = rail + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRedstoneWire.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRedstoneWire.kt new file mode 100644 index 000000000..b9d6e9745 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRedstoneWire.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.RedstoneWire + +object BlockArgParserRedstoneWire : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val redstoneWire = blockData as? RedstoneWire ?: return null + + val faces = redstoneWire.allowedFaces.associateWith { RedstoneWire.Connection.NONE }.toMutableMap() + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("face", true)) { + continue + } + if (argSplit.size < 3) { + continue + } + + val face = redstoneWire.allowedFaces.firstOrNull { it.name.equals(argSplit[1].uppercase(), true) } ?: continue + faces[face] = runCatching { RedstoneWire.Connection.valueOf(argSplit[2].uppercase()) }.getOrNull() ?: continue + } + + return BlockArgParseResult( + { + val redstoneWire = it.blockData as? RedstoneWire ?: return@BlockArgParseResult false + + redstoneWire.allowedFaces.all { face -> + faces[face] == redstoneWire.getFace(face) + } + }, + { + val redstoneWire = it.blockData as? RedstoneWire ?: return@BlockArgParseResult + + faces.forEach { facing -> redstoneWire.setFace(facing.key, facing.value) } + + it.blockData = redstoneWire + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRepeater.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRepeater.kt new file mode 100644 index 000000000..49aee3d5c --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRepeater.kt @@ -0,0 +1,48 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Repeater + +object BlockArgParserRepeater : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val repeater = blockData as? Repeater ?: return null + var delay: Int? = null + var locked: Boolean? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("delay", true)) { + if (argSplit.size < 2) { + continue + } + val argDelay = argSplit[1].toIntOrNull() ?: continue + if (argDelay in (repeater.maximumDelay + 1).., blockData: BlockData): BlockArgParseResult? { + val respawnAnchor = blockData as? RespawnAnchor ?: return null + var charges: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("charges", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argCharges = argSplit[1].toIntOrNull() ?: continue + if (argCharges in (respawnAnchor.maximumCharges + 1)..<0) { + continue + } + charges = argCharges + } + + charges ?: return null + + return BlockArgParseResult( + { + val respawnAnchor = it.blockData as? RespawnAnchor ?: return@BlockArgParseResult false + + respawnAnchor.charges == charges + }, + { + val respawnAnchor = it.blockData as? RespawnAnchor ?: return@BlockArgParseResult + + respawnAnchor.charges = charges + it.blockData = respawnAnchor + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRotatable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRotatable.kt new file mode 100644 index 000000000..96ccd4b93 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserRotatable.kt @@ -0,0 +1,41 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Rotatable + +object BlockArgParserRotatable : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Rotatable) return null + var rotation: BlockFace? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("rotation", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + rotation = runCatching { BlockFace.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + rotation ?: return null + + return BlockArgParseResult( + { + val rotatable = it.blockData as? Rotatable ?: return@BlockArgParseResult false + + rotatable.rotation == rotation + }, + { + val rotatable = it.blockData as? Rotatable ?: return@BlockArgParseResult + + rotatable.rotation = rotation + it.blockData = rotatable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserScaffolding.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserScaffolding.kt new file mode 100644 index 000000000..d203e0a4c --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserScaffolding.kt @@ -0,0 +1,48 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Scaffolding + +object BlockArgParserScaffolding : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val scaffolding = blockData as? Scaffolding ?: return null + var distance: Int? = null + var bottom: Boolean? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("distance", true)) { + if (argSplit.size < 2) { + continue + } + val argDistance = argSplit[1].toIntOrNull() ?: continue + if (argDistance in (scaffolding.maximumDistance + 1)..<0) { + continue + } + distance = argDistance + } else if (argSplit[0].equals("bottom", true)) { + bottom = true + } + } + + if (distance == null && bottom == null) return null + + return BlockArgParseResult( + { + val scaffolding = it.blockData as? Scaffolding ?: return@BlockArgParseResult false + + (distance == null || scaffolding.distance == distance) && (bottom == null || scaffolding.isBottom == bottom) + }, + { + val scaffolding = it.blockData as? Scaffolding ?: return@BlockArgParseResult + + if (distance != null) scaffolding.distance = distance + if (bottom != null) scaffolding.isBottom = bottom + + it.blockData = scaffolding + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSculkSensor.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSculkSensor.kt new file mode 100644 index 000000000..daa66e58b --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSculkSensor.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.SculkSensor + +object BlockArgParserSculkSensor : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is SculkSensor) return null + var phase: SculkSensor.Phase? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("phase", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + phase = runCatching { SculkSensor.Phase.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + phase ?: return null + + return BlockArgParseResult( + { + val sculkSensor = it.blockData as? SculkSensor ?: return@BlockArgParseResult false + + sculkSensor.phase == phase + }, + { + val sculkSensor = it.blockData as? SculkSensor ?: return@BlockArgParseResult + + sculkSensor.phase = phase + it.blockData = sculkSensor + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSculkShrieker.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSculkShrieker.kt new file mode 100644 index 000000000..08e452799 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSculkShrieker.kt @@ -0,0 +1,41 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.SculkShrieker + +object BlockArgParserSculkShrieker : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is SculkShrieker) return null + var canSummon: Boolean? = null + var shrieking: Boolean? = null + + for (arg in args) { + if (arg.equals("can_summon", true)) { + canSummon = true + } else if (arg.equals("shrieking", true)) { + shrieking = true + } + } + + if (canSummon == null && shrieking == null) return null + + return BlockArgParseResult( + { + val sculkShrieker = it.blockData as? SculkShrieker ?: return@BlockArgParseResult false + + (canSummon == null || sculkShrieker.isCanSummon == canSummon) && + (shrieking == null || sculkShrieker.isShrieking == shrieking) + }, + { + val sculkShrieker = it.blockData as? SculkShrieker ?: return@BlockArgParseResult + + if (canSummon != null) sculkShrieker.isCanSummon = canSummon + if (shrieking != null) sculkShrieker.isShrieking = shrieking + + it.blockData = sculkShrieker + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSlab.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSlab.kt new file mode 100644 index 000000000..ab98205ed --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSlab.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Slab + +object BlockArgParserSlab : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Slab) return null + var slabType: Slab.Type? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("slab", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + slabType = runCatching { Slab.Type.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + slabType ?: return null + + return BlockArgParseResult( + { + val slab = it.blockData as? Slab ?: return@BlockArgParseResult false + + slab.type == slabType + }, + { + val slab = it.blockData as? Slab ?: return@BlockArgParseResult + + slab.type = slabType + it.blockData = slab + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSnow.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSnow.kt new file mode 100644 index 000000000..06f1cddc8 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserSnow.kt @@ -0,0 +1,44 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Snow + +object BlockArgParserSnow : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + val snow = blockData as? Snow ?: return null + var layers: Int? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("layers", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + val argLayers = argSplit[1].toIntOrNull() ?: continue + if (argLayers in (snow.maximumLayers + 1).., blockData: BlockData): BlockArgParseResult? { + if (blockData !is Snowable) return null + var snowy: Boolean? = null + + for (arg in args) { + if (arg.equals("snowy", true)) { + snowy = true + } + } + + snowy ?: return null + + return BlockArgParseResult( + { + val snowable = it.blockData as? Snowable ?: return@BlockArgParseResult false + + snowable.isSnowy == snowy + }, + { + val snowable = it.blockData as? Snowable ?: return@BlockArgParseResult + + snowable.isSnowy = snowy + it.blockData = snowable + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserStairs.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserStairs.kt new file mode 100644 index 000000000..a0206405e --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserStairs.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Stairs + +object BlockArgParserStairs : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Stairs) return null + var shape: Stairs.Shape? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("shape", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + shape = runCatching { Stairs.Shape.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + shape ?: return null + + return BlockArgParseResult( + { + val stairs = it.blockData as? Stairs ?: return@BlockArgParseResult false + + stairs.shape == shape + }, + { + val stairs = it.blockData as? Stairs ?: return@BlockArgParseResult + + stairs.shape = shape + it.blockData = stairs + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserStructureBlock.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserStructureBlock.kt new file mode 100644 index 000000000..375465467 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserStructureBlock.kt @@ -0,0 +1,40 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.StructureBlock + +object BlockArgParserStructureBlock : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is StructureBlock) return null + var mode: StructureBlock.Mode? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("mode", true)) { + continue + } + if (argSplit.size < 2) { + continue + } + mode = runCatching { StructureBlock.Mode.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + } + + mode ?: return null + + return BlockArgParseResult( + { + val structureBlock = it.blockData as? StructureBlock ?: return@BlockArgParseResult false + + structureBlock.mode == mode + }, + { + val structureBlock = it.blockData as? StructureBlock ?: return@BlockArgParseResult + + structureBlock.mode = mode + it.blockData = structureBlock + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTNT.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTNT.kt new file mode 100644 index 000000000..330dbf5c0 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTNT.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.TNT + +object BlockArgParserTNT : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is TNT) return null + var unstable: Boolean? = null + + for (arg in args) { + if (arg.equals("unstable", true)) { + unstable = true + } + } + + unstable ?: return null + + return BlockArgParseResult( + { + val tnt = it.blockData as? TNT ?: return@BlockArgParseResult false + + tnt.isUnstable == unstable + }, + { + val tnt = it.blockData as? TNT ?: return@BlockArgParseResult + + tnt.isUnstable = unstable + it.blockData = tnt + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTrial.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTrial.kt new file mode 100644 index 000000000..08398900f --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTrial.kt @@ -0,0 +1,75 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.TrialSpawner +import org.bukkit.block.data.type.Vault + +object BlockArgParserTrial : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if ( + blockData !is TrialSpawner && + blockData !is Vault + ) return null + + var state: Any? = null + var ominous: Boolean? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("ominous", true)) { + ominous = true + } else if (argSplit[0].equals("state", true)) { + if (argSplit.size < 2) { + continue + } + state = when (blockData) { + is TrialSpawner -> runCatching { TrialSpawner.State.valueOf(argSplit[1].uppercase()) }.getOrNull() + ?: continue + + is Vault -> runCatching { Vault.State.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + else -> continue + } + } + + } + + if (state == null && ominous == null) return null + + return BlockArgParseResult( + { + when (val blockData = it.blockData) { + is TrialSpawner -> + (state == null || blockData.trialSpawnerState == state) && + (ominous == null || blockData.isOminous == ominous) + + is Vault -> (state == null || blockData.vaultState == state) && + (ominous == null || blockData.isOminous == ominous) + + else -> false + } + }, + { + val data = it.blockData + + when (data) { + is TrialSpawner -> { + if (ominous != null) data.isOminous = ominous + if (state != null) data.trialSpawnerState = + state as? TrialSpawner.State ?: return@BlockArgParseResult + } + + is Vault -> { + if (ominous != null) data.isOminous = ominous + if (state != null) data.vaultState = state as? Vault.State ?: return@BlockArgParseResult + } + + else -> return@BlockArgParseResult + } + + it.blockData = data + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTripwire.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTripwire.kt new file mode 100644 index 000000000..f499c842d --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserTripwire.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Tripwire + +object BlockArgParserTripwire : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Tripwire) return null + var disarmed: Boolean? = null + + for (arg in args) { + if (arg.equals("disarmed", true)) { + disarmed = true + } + } + + disarmed ?: return null + + return BlockArgParseResult( + { + val tripwire = it.blockData as? Tripwire ?: return@BlockArgParseResult false + + tripwire.isDisarmed == disarmed + }, + { + val tripwire = it.blockData as? Tripwire ?: return@BlockArgParseResult + + tripwire.isDisarmed = disarmed + it.blockData = tripwire + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserWall.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserWall.kt new file mode 100644 index 000000000..99c711b69 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserWall.kt @@ -0,0 +1,48 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Wall + +object BlockArgParserWall : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Wall) return null + + val faces = BlockFace.entries.associateWith { Wall.Height.NONE }.toMutableMap() + var up: Boolean? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (argSplit[0].equals("face", true)) { + if (argSplit.size < 3) { + continue + } + + val face = runCatching { BlockFace.valueOf(argSplit[1].uppercase()) }.getOrNull() ?: continue + faces[face] = runCatching { Wall.Height.valueOf(argSplit[2].uppercase()) }.getOrNull() ?: continue + } else if (argSplit[0].equals("up", true)) { + up = true + } + } + + return BlockArgParseResult( + { + val wall = it.blockData as? Wall ?: return@BlockArgParseResult false + + BlockFace.entries.all { face -> + faces[face] == wall.getHeight(face) + } && (up == null || wall.isUp == up) + }, + { + val wall = it.blockData as? Wall ?: return@BlockArgParseResult + + faces.forEach { facing -> wall.setHeight(facing.key, facing.value) } + if (up != null) wall.isUp = up + + it.blockData = wall + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserWaterlogged.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserWaterlogged.kt new file mode 100644 index 000000000..42ad3a8c1 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/BlockArgParserWaterlogged.kt @@ -0,0 +1,35 @@ +package com.willfp.eco.internal.blocks + +import com.willfp.eco.core.blocks.args.BlockArgParseResult +import com.willfp.eco.core.blocks.args.BlockArgParser +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Waterlogged + +object BlockArgParserWaterlogged : BlockArgParser { + override fun parseArguments(args: Array, blockData: BlockData): BlockArgParseResult? { + if (blockData !is Waterlogged) return null + var waterlogged: Boolean? = null + + for (arg in args) { + if (arg.equals("waterlogged", true)) { + waterlogged = true + } + } + + waterlogged ?: return null + + return BlockArgParseResult( + { + val waterloggedBlock = it.blockData as? Waterlogged ?: return@BlockArgParseResult false + + waterloggedBlock.isWaterlogged == waterlogged + }, + { + val waterloggedBlock = it.blockData as? Waterlogged ?: return@BlockArgParseResult + + waterloggedBlock.isWaterlogged = waterlogged + it.blockData = waterloggedBlock + } + ) + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/tags/VanillaBlockTags.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/tags/VanillaBlockTags.kt new file mode 100644 index 000000000..28ca2fc31 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/blocks/tags/VanillaBlockTags.kt @@ -0,0 +1,39 @@ +package com.willfp.eco.internal.blocks.tags + +import com.willfp.eco.core.blocks.Blocks +import com.willfp.eco.core.blocks.tag.VanillaBlockTag +import org.bukkit.Keyed +import org.bukkit.Material +import org.bukkit.Tag + +object VanillaBlockTags { + fun register() { + // Get all tags + val allTags = Tag::class.java.declaredFields + .filter { it.type == Tag::class.java } + .mapNotNull { + val tag = it.get(null) as? Tag<*> + if (tag == null) { + null + } else { + NamedTag(it.name.lowercase(), tag) + } + } + + // Register all tags + for (tag in allTags) { + if (tag.isMaterial) { + Blocks.registerTag( + @Suppress("UNCHECKED_CAST") + (VanillaBlockTag(tag.name, tag.tag as Tag)) + ) + } + } + } + + private data class NamedTag(val name: String, val tag: Tag) { + // Check if tag is material + val isMaterial: Boolean + get() = tag.values.firstOrNull() is Material + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt index fcbfa1db1..6eb5117c6 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt @@ -4,6 +4,7 @@ import com.willfp.eco.core.Eco import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike import com.willfp.eco.core.PluginProps +import com.willfp.eco.core.blocks.Blocks import com.willfp.eco.core.command.CommandBase import com.willfp.eco.core.command.PluginCommandBase import com.willfp.eco.core.config.ConfigType @@ -248,6 +249,12 @@ class EcoImpl : EcoSpigotPlugin(), Eco { } } + for (customBlock in Blocks.getCustomBlocks()) { + if (customBlock.key.namespace.equals(plugin.name.lowercase(), ignoreCase = true)) { + Blocks.removeCustomBlock(customBlock.key) + } + } + val classLoader = plugin::class.java.classLoader if (classLoader is URLClassLoader) { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt index 365bbf49d..1b4359cd4 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt @@ -3,6 +3,7 @@ package com.willfp.eco.internal.spigot import com.willfp.eco.core.Eco import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.Prerequisite +import com.willfp.eco.core.blocks.Blocks import com.willfp.eco.core.data.ExternalDataStore import com.willfp.eco.core.entities.Entities import com.willfp.eco.core.integrations.IntegrationLoader @@ -21,6 +22,59 @@ import com.willfp.eco.core.items.Items import com.willfp.eco.core.packet.PacketListener import com.willfp.eco.core.particle.Particles import com.willfp.eco.core.price.Prices +import com.willfp.eco.internal.blocks.BlockArgParserAgeable +import com.willfp.eco.internal.blocks.BlockArgParserAnaloguePowerable +import com.willfp.eco.internal.blocks.BlockArgParserAttachable +import com.willfp.eco.internal.blocks.BlockArgParserBamboo +import com.willfp.eco.internal.blocks.BlockArgParserBisected +import com.willfp.eco.internal.blocks.BlockArgParserBubbleColumn +import com.willfp.eco.internal.blocks.BlockArgParserCake +import com.willfp.eco.internal.blocks.BlockArgParserCampfire +import com.willfp.eco.internal.blocks.BlockArgParserCaveVinesPlant +import com.willfp.eco.internal.blocks.BlockArgParserChest +import com.willfp.eco.internal.blocks.BlockArgParserCommandBlock +import com.willfp.eco.internal.blocks.BlockArgParserComparator +import com.willfp.eco.internal.blocks.BlockArgParserCrafter +import com.willfp.eco.internal.blocks.BlockArgParserDaylightDetector +import com.willfp.eco.internal.blocks.BlockArgParserDirectional +import com.willfp.eco.internal.blocks.BlockArgParserDispenser +import com.willfp.eco.internal.blocks.BlockArgParserDoor +import com.willfp.eco.internal.blocks.BlockArgParserEndPortalFrame +import com.willfp.eco.internal.blocks.BlockArgParserFaceAttachable +import com.willfp.eco.internal.blocks.BlockArgParserFarmland +import com.willfp.eco.internal.blocks.BlockArgParserGate +import com.willfp.eco.internal.blocks.BlockArgParserHangable +import com.willfp.eco.internal.blocks.BlockArgParserHangingMoss +import com.willfp.eco.internal.blocks.BlockArgParserJigsaw +import com.willfp.eco.internal.blocks.BlockArgParserLevelled +import com.willfp.eco.internal.blocks.BlockArgParserLightable +import com.willfp.eco.internal.blocks.BlockArgParserMossyCarpet +import com.willfp.eco.internal.blocks.BlockArgParserMultipleFacing +import com.willfp.eco.internal.blocks.BlockArgParserNoteBlock +import com.willfp.eco.internal.blocks.BlockArgParserOpenable +import com.willfp.eco.internal.blocks.BlockArgParserOrientable +import com.willfp.eco.internal.blocks.BlockArgParserPointedDripstone +import com.willfp.eco.internal.blocks.BlockArgParserPowerable +import com.willfp.eco.internal.blocks.BlockArgParserQuantity +import com.willfp.eco.internal.blocks.BlockArgParserRail +import com.willfp.eco.internal.blocks.BlockArgParserRedstoneWire +import com.willfp.eco.internal.blocks.BlockArgParserRepeater +import com.willfp.eco.internal.blocks.BlockArgParserRespawnAnchor +import com.willfp.eco.internal.blocks.BlockArgParserRotatable +import com.willfp.eco.internal.blocks.BlockArgParserScaffolding +import com.willfp.eco.internal.blocks.BlockArgParserSculkSensor +import com.willfp.eco.internal.blocks.BlockArgParserSculkShrieker +import com.willfp.eco.internal.blocks.BlockArgParserSlab +import com.willfp.eco.internal.blocks.BlockArgParserSnow +import com.willfp.eco.internal.blocks.BlockArgParserSnowy +import com.willfp.eco.internal.blocks.BlockArgParserStairs +import com.willfp.eco.internal.blocks.BlockArgParserStructureBlock +import com.willfp.eco.internal.blocks.BlockArgParserTNT +import com.willfp.eco.internal.blocks.BlockArgParserTrial +import com.willfp.eco.internal.blocks.BlockArgParserTripwire +import com.willfp.eco.internal.blocks.BlockArgParserWall +import com.willfp.eco.internal.blocks.BlockArgParserWaterlogged +import com.willfp.eco.internal.blocks.tags.VanillaBlockTags import com.willfp.eco.internal.data.MavenVersionToStringAdapter import com.willfp.eco.internal.data.VersionToStringAdapter import com.willfp.eco.internal.entities.EntityArgParserAdult @@ -111,6 +165,9 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefRPGHorses import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2 import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefTowny import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefWorldGuard +import com.willfp.eco.internal.spigot.integrations.customblocks.CustomBlocksCraftEngine +import com.willfp.eco.internal.spigot.integrations.customblocks.CustomBlocksItemsAdder +import com.willfp.eco.internal.spigot.integrations.customblocks.CustomBlocksNexo import com.willfp.eco.internal.spigot.integrations.customblocks.CustomBlocksOraxen import com.willfp.eco.internal.spigot.integrations.customentities.CustomEntitiesMythicMobs import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsCraftEngine @@ -160,7 +217,6 @@ import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.event.Listener import org.bukkit.inventory.ItemStack -import kotlin.jvm.java import su.nightexpress.coinsengine.api.CoinsEngineAPI abstract class EcoSpigotPlugin : EcoPlugin() { @@ -191,6 +247,59 @@ abstract class EcoSpigotPlugin : EcoPlugin() { Items.registerArgParser(ArgParserTooltipStyle) Items.registerArgParser(ArgParserTrim) + Blocks.registerArgParser(BlockArgParserAgeable) + Blocks.registerArgParser(BlockArgParserAnaloguePowerable) + Blocks.registerArgParser(BlockArgParserAttachable) + Blocks.registerArgParser(BlockArgParserBamboo) + Blocks.registerArgParser(BlockArgParserBisected) + Blocks.registerArgParser(BlockArgParserBubbleColumn) + Blocks.registerArgParser(BlockArgParserCake) + Blocks.registerArgParser(BlockArgParserCampfire) + Blocks.registerArgParser(BlockArgParserCaveVinesPlant) + Blocks.registerArgParser(BlockArgParserChest) + Blocks.registerArgParser(BlockArgParserCommandBlock) + Blocks.registerArgParser(BlockArgParserComparator) + Blocks.registerArgParser(BlockArgParserCrafter) + Blocks.registerArgParser(BlockArgParserDaylightDetector) + Blocks.registerArgParser(BlockArgParserDirectional) + Blocks.registerArgParser(BlockArgParserDispenser) + Blocks.registerArgParser(BlockArgParserDoor) + Blocks.registerArgParser(BlockArgParserEndPortalFrame) + Blocks.registerArgParser(BlockArgParserFaceAttachable) + Blocks.registerArgParser(BlockArgParserFarmland) + Blocks.registerArgParser(BlockArgParserGate) + Blocks.registerArgParser(BlockArgParserHangable) + Blocks.registerArgParser(BlockArgParserHangingMoss) + Blocks.registerArgParser(BlockArgParserJigsaw) + Blocks.registerArgParser(BlockArgParserLevelled) + Blocks.registerArgParser(BlockArgParserLightable) + Blocks.registerArgParser(BlockArgParserMossyCarpet) + Blocks.registerArgParser(BlockArgParserMultipleFacing) + Blocks.registerArgParser(BlockArgParserNoteBlock) + Blocks.registerArgParser(BlockArgParserOpenable) + Blocks.registerArgParser(BlockArgParserOrientable) + Blocks.registerArgParser(BlockArgParserPointedDripstone) + Blocks.registerArgParser(BlockArgParserPowerable) + Blocks.registerArgParser(BlockArgParserQuantity) + Blocks.registerArgParser(BlockArgParserRail) + Blocks.registerArgParser(BlockArgParserRedstoneWire) + Blocks.registerArgParser(BlockArgParserRepeater) + Blocks.registerArgParser(BlockArgParserRespawnAnchor) + Blocks.registerArgParser(BlockArgParserRotatable) + Blocks.registerArgParser(BlockArgParserScaffolding) + Blocks.registerArgParser(BlockArgParserSculkSensor) + Blocks.registerArgParser(BlockArgParserSculkShrieker) + Blocks.registerArgParser(BlockArgParserSlab) + Blocks.registerArgParser(BlockArgParserSnow) + Blocks.registerArgParser(BlockArgParserSnowy) + Blocks.registerArgParser(BlockArgParserStairs) + Blocks.registerArgParser(BlockArgParserStructureBlock) + Blocks.registerArgParser(BlockArgParserTNT) + Blocks.registerArgParser(BlockArgParserTrial) + Blocks.registerArgParser(BlockArgParserTripwire) + Blocks.registerArgParser(BlockArgParserWall) + Blocks.registerArgParser(BlockArgParserWaterlogged) + Entities.registerArgParser(EntityArgParserName) Entities.registerArgParser(EntityArgParserNoAI) Entities.registerArgParser(EntityArgParserAttackDamage) @@ -228,6 +337,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() { SegmentParserUseIfPresent.register() CustomItemsManager.registerProviders() + CustomBlocksManager.registerProviders() ExternalDataStore.registerAdapter(VersionToStringAdapter) // Handle with shadow. @@ -263,7 +373,9 @@ abstract class EcoSpigotPlugin : EcoPlugin() { this.logger.info("No conflicts found!") } - CustomItemsManager.registerProviders() // Do it again here + // Do it again here + CustomItemsManager.registerProviders() + CustomBlocksManager.registerProviders() // Register events for ShopSellEvent for (integration in ShopManager.getRegisteredIntegrations()) { @@ -281,8 +393,9 @@ abstract class EcoSpigotPlugin : EcoPlugin() { bukkitAudiences = BukkitAudiences.create(this) } - // Init vanilla item tags + // Init vanilla tags VanillaItemTags.register() + VanillaBlockTags.register() } override fun handleDisable() { @@ -313,6 +426,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() { override fun handleAfterLoad() { CustomItemsManager.registerAllItems() + CustomBlocksManager.registerAllBlocks() CustomEntitiesManager.registerAllEntities() ShopManager.registerEcoProvider() } @@ -361,10 +475,22 @@ abstract class EcoSpigotPlugin : EcoPlugin() { IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs()) }, // Custom Items - IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen(this)) }, - IntegrationLoader("Nexo") { CustomItemsManager.register(CustomItemsNexo(this)) }, - IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder()) }, - IntegrationLoader("CraftEngine") { CustomItemsManager.register(CustomItemsCraftEngine(this)) }, + IntegrationLoader("Oraxen") { + CustomItemsManager.register(CustomItemsOraxen(this)) + CustomBlocksManager.register(CustomBlocksOraxen(this)) + }, + IntegrationLoader("Nexo") { + CustomItemsManager.register(CustomItemsNexo(this)) + CustomBlocksManager.register(CustomBlocksNexo(this)) + }, + IntegrationLoader("ItemsAdder") { + CustomItemsManager.register(CustomItemsItemsAdder()) + CustomBlocksManager.register(CustomBlocksItemsAdder()) + }, + IntegrationLoader("CraftEngine") { + CustomItemsManager.register(CustomItemsCraftEngine(this)) + CustomBlocksManager.register(CustomBlocksCraftEngine(this)) + }, IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) }, IntegrationLoader("ExecutableItems") { CustomItemsManager.register(CustomItemsExecutableItems()) }, IntegrationLoader("CustomCrafting") { @@ -425,9 +551,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() { // Placeholder IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) }, - // Custom Blocks - IntegrationLoader("Oraxen") { CustomBlocksManager.register(CustomBlocksOraxen(this)) }, - // Misc IntegrationLoader("mcMMO") { McmmoManager.register(McmmoIntegrationImpl()) }, IntegrationLoader("Multiverse-Inventories") { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksCraftEngine.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksCraftEngine.kt new file mode 100644 index 000000000..96e174d49 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksCraftEngine.kt @@ -0,0 +1,67 @@ +package com.willfp.eco.internal.spigot.integrations.customblocks + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.blocks.Blocks +import com.willfp.eco.core.blocks.CustomBlock +import com.willfp.eco.core.blocks.TestableBlock +import com.willfp.eco.core.blocks.provider.BlockProvider +import com.willfp.eco.core.integrations.customblocks.CustomBlocksIntegration +import com.willfp.eco.util.namespacedKeyOf +import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks +import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent +import net.momirealms.craftengine.core.util.Key +import org.bukkit.block.Block +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import java.util.function.Predicate + +class CustomBlocksCraftEngine( + private val plugin: EcoPlugin +) : CustomBlocksIntegration, Listener { + override fun registerProvider() { + plugin.eventManager.registerListener(this) + } + + override fun getPluginName(): String { + return "CraftEngine" + } + + @EventHandler + @Suppress("UNUSED_PARAMETER") + fun onBlockRegister(event: CraftEngineReloadEvent) { + Blocks.registerBlockProvider(CraftEngineProvider()) + } + + private class CraftEngineProvider : BlockProvider("craftengine") { + override fun provideForKey(key: String): TestableBlock? { + val split = key.split(":").toMutableList() + + if (split.size < 2) { + return null + } + + val namespace = split[0] + val value = split[1] + + val id = Key.of(namespace, value) + val blockId = CraftEngineBlocks.byId(id) ?: return null + val namespacedKey = namespacedKeyOf("craftengine", key.lowercase().replace(":", "__")) + + return CustomBlock( + namespacedKey, + Predicate { test: Block -> + if (!CraftEngineBlocks.isCustomBlock(test)) { + return@Predicate false + } + val immutableBlockState = CraftEngineBlocks.getCustomBlockState(test) ?: return@Predicate false + return@Predicate immutableBlockState.owner().value().id().equals(blockId.id()) + }, + { location -> + CraftEngineBlocks.place(location, id, true) + location.block + } + ) + } + + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksItemsAdder.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksItemsAdder.kt new file mode 100644 index 000000000..4ffe171c1 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksItemsAdder.kt @@ -0,0 +1,42 @@ +package com.willfp.eco.internal.spigot.integrations.customblocks + +import com.willfp.eco.core.blocks.Blocks +import com.willfp.eco.core.blocks.CustomBlock +import com.willfp.eco.core.blocks.TestableBlock +import com.willfp.eco.core.blocks.provider.BlockProvider +import com.willfp.eco.core.integrations.customblocks.CustomBlocksIntegration +import com.willfp.eco.util.namespacedKeyOf +import org.bukkit.block.Block +import java.util.function.Predicate + +class CustomBlocksItemsAdder : CustomBlocksIntegration { + override fun registerProvider() { + Blocks.registerBlockProvider(ItemsAdderProvider()) + } + + override fun getPluginName(): String { + return "ItemsAdder" + } + + private class ItemsAdderProvider : BlockProvider("itemsadder") { + override fun provideForKey(key: String): TestableBlock? { + val internalId = if (key.contains(":")) key else "itemsadder:$key" + + val block = dev.lone.itemsadder.api.CustomBlock.getInstance(internalId) ?: return null + val id = block.id + val namespacedKey = namespacedKeyOf("itemsadder", key.lowercase().replace(":", "__")) + return CustomBlock( + namespacedKey, + Predicate { test: Block -> + val customBlock = + dev.lone.itemsadder.api.CustomBlock.byAlreadyPlaced(test) ?: return@Predicate false + customBlock.id.equals(id, ignoreCase = true) + }, + { location -> + dev.lone.itemsadder.api.CustomBlock.place(id, location) + location.block + } + ) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksNexo.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksNexo.kt new file mode 100644 index 000000000..09aa99c4f --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksNexo.kt @@ -0,0 +1,57 @@ +package com.willfp.eco.internal.spigot.integrations.customblocks + +import com.nexomc.nexo.api.NexoBlocks +import com.nexomc.nexo.api.NexoItems +import com.nexomc.nexo.api.events.NexoItemsLoadedEvent +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.blocks.Blocks +import com.willfp.eco.core.blocks.CustomBlock +import com.willfp.eco.core.blocks.TestableBlock +import com.willfp.eco.core.blocks.provider.BlockProvider +import com.willfp.eco.core.integrations.customblocks.CustomBlocksIntegration +import com.willfp.eco.util.namespacedKeyOf +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener + +class CustomBlocksNexo( + private val plugin: EcoPlugin +) : CustomBlocksIntegration, Listener { + override fun registerProvider() { + plugin.eventManager.registerListener(this) + } + + override fun getPluginName(): String { + return "Nexo" + } + + @EventHandler + @Suppress("UNUSED_PARAMETER") + fun onBlockRegister(event: NexoItemsLoadedEvent) { + Blocks.registerBlockProvider(NexoProvider()) + } + + private class NexoProvider : BlockProvider("nexo") { + override fun provideForKey(key: String): TestableBlock? { + // The key + if (!NexoBlocks.isCustomBlock(key)) { + return null + } + + val item = NexoItems.itemFromId(key) ?: return null + val id = NexoItems.idFromItem(item) + val namespacedKey = namespacedKeyOf("nexo", id.toString()) + + return CustomBlock( + namespacedKey, + { + NexoBlocks.isCustomBlock(it) && + id.equals(NexoBlocks.customBlockMechanic(it.location)?.itemID, ignoreCase = true) + }, + { location -> + NexoBlocks.place(id, location) + location.block + } + ) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksOraxen.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksOraxen.kt index 97ddebb3e..ded95f9e5 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksOraxen.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customblocks/CustomBlocksOraxen.kt @@ -8,6 +8,7 @@ import com.willfp.eco.core.blocks.provider.BlockProvider import com.willfp.eco.core.integrations.customblocks.CustomBlocksIntegration import com.willfp.eco.util.namespacedKeyOf import io.th0rgal.oraxen.api.OraxenBlocks +import io.th0rgal.oraxen.api.OraxenItems import io.th0rgal.oraxen.api.events.OraxenItemsLoadedEvent import org.bukkit.event.EventHandler import org.bukkit.event.Listener @@ -25,7 +26,7 @@ class CustomBlocksOraxen( @EventHandler @Suppress("UNUSED_PARAMETER") - fun onItemRegister(event: OraxenItemsLoadedEvent) { + fun onBlockRegister(event: OraxenItemsLoadedEvent) { Blocks.registerBlockProvider(OraxenProvider()) } @@ -36,16 +37,18 @@ class CustomBlocksOraxen( return null } - val namespacedKey = namespacedKeyOf("oraxen", key) + val item = OraxenItems.getItemById(key) ?: return null + val id = OraxenItems.getIdByItem(item) + val namespacedKey = namespacedKeyOf("oraxen", id) return CustomBlock( namespacedKey, - { block -> - // TODO: Implement this - TODO("Not yet implemented") + { + OraxenBlocks.isOraxenBlock(it) && + id.equals(OraxenBlocks.getOraxenBlock(it.location).itemID, ignoreCase = true) }, { location -> - OraxenBlocks.place(key, location) + OraxenBlocks.place(id, location) location.block } ) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsCraftEngine.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsCraftEngine.kt index d6c371841..68a0ab5ef 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsCraftEngine.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsCraftEngine.kt @@ -6,7 +6,7 @@ import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.TestableItem import com.willfp.eco.core.items.provider.ItemProvider -import com.willfp.eco.util.NamespacedKeyUtils +import com.willfp.eco.util.namespacedKeyOf import net.momirealms.craftengine.bukkit.api.CraftEngineItems import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent import net.momirealms.craftengine.core.util.Key @@ -45,7 +45,7 @@ class CustomItemsCraftEngine( val id = Key.of(namespace, value) val item = CraftEngineItems.byId(id) ?: return null - val namespacedKey = NamespacedKeyUtils.create("craftengine", key.lowercase().replace(":", "__")) + val namespacedKey = namespacedKeyOf("craftengine", key.lowercase().replace(":", "__")) val stack = item.buildItemStack() return CustomItem( diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemsAdder.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemsAdder.kt index 9de79f999..2637641dc 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemsAdder.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemsAdder.kt @@ -5,7 +5,7 @@ import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.TestableItem import com.willfp.eco.core.items.provider.ItemProvider -import com.willfp.eco.util.NamespacedKeyUtils +import com.willfp.eco.util.namespacedKeyOf import dev.lone.itemsadder.api.CustomStack import org.bukkit.inventory.ItemStack import java.util.function.Predicate @@ -25,7 +25,7 @@ class CustomItemsItemsAdder : CustomItemsIntegration { val item = CustomStack.getInstance(internalId) ?: return null val id = item.id - val namespacedKey = NamespacedKeyUtils.create("itemsadder", key.lowercase().replace(":", "__")) + val namespacedKey = namespacedKeyOf("itemsadder", key.lowercase().replace(":", "__")) val stack = item.itemStack return CustomItem( namespacedKey, diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsNexo.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsNexo.kt index b5c1de865..8aca321d7 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsNexo.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsNexo.kt @@ -8,7 +8,7 @@ import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.TestableItem import com.willfp.eco.core.items.provider.ItemProvider -import com.willfp.eco.util.NamespacedKeyUtils +import com.willfp.eco.util.namespacedKeyOf import org.bukkit.event.EventHandler import org.bukkit.event.Listener @@ -33,7 +33,7 @@ class CustomItemsNexo( override fun provideForKey(key: String): TestableItem? { val item = NexoItems.itemFromId(key) ?: return null val id = NexoItems.idFromItem(item) - val namespacedKey = NamespacedKeyUtils.create("nexo", id.toString()) + val namespacedKey = namespacedKeyOf("nexo", id.toString()) return CustomItem( namespacedKey, { id.equals(NexoItems.idFromItem(it), ignoreCase = true) }, diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsOraxen.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsOraxen.kt index 9b4c7fb1a..c822a9b65 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsOraxen.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsOraxen.kt @@ -6,7 +6,7 @@ import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.TestableItem import com.willfp.eco.core.items.provider.ItemProvider -import com.willfp.eco.util.NamespacedKeyUtils +import com.willfp.eco.util.namespacedKeyOf import io.th0rgal.oraxen.api.OraxenItems import io.th0rgal.oraxen.api.events.OraxenItemsLoadedEvent import org.bukkit.event.EventHandler @@ -33,7 +33,7 @@ class CustomItemsOraxen( override fun provideForKey(key: String): TestableItem? { val item = OraxenItems.getItemById(key) ?: return null val id = OraxenItems.getIdByItem(item) - val namespacedKey = NamespacedKeyUtils.create("oraxen", id) + val namespacedKey = namespacedKeyOf("oraxen", id) return CustomItem( namespacedKey, { id.equals(OraxenItems.getIdByItem(it), ignoreCase = true) },