diff --git a/CHANGELOG.md b/CHANGELOG.md index 9486d35180..937eda2a1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Table of contents -- [Release Candidate 29 (07 Nov 2021)](#release-candidate-29-06-nov-2021) +- [Release Candidate 30 (TBD)](#release-candidate-30-tbd) +- [Release Candidate 29 (07 Nov 2021)](#release-candidate-29-07-nov-2021) - [Release Candidate 28 (06 Sep 2021)](#release-candidate-28-06-sep-2021) - [Release Candidate 27 (03 Sep 2021)](#release-candidate-27-03-sep-2021) - [Release Candidate 26 (20 Jul 2021)](#release-candidate-26-20-jul-2021) @@ -29,6 +30,16 @@ - [Release Candidate 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019) - [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019) +## Release Candidate 30 (TBD) + +#### Additions + +#### Changes + +#### Fixes +* Crimson and Warped Pressure Plates are now properly recognized as pressure plates +* Fixed #3336 + ## Release Candidate 29 (07 Nov 2021) #### Additions diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/AdvancedIndustrialMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/AdvancedIndustrialMiner.java index 2a93db3b55..5cec6e1b1e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/AdvancedIndustrialMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/AdvancedIndustrialMiner.java @@ -1,5 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner; +import javax.annotation.ParametersAreNonnullByDefault; + import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -21,6 +23,7 @@ */ public class AdvancedIndustrialMiner extends IndustrialMiner { + @ParametersAreNonnullByDefault public AdvancedIndustrialMiner(ItemGroup itemGroup, SlimefunItemStack item) { super(itemGroup, item, Material.DIAMOND_BLOCK, true, 5); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java index 12cb60064d..f1b9768b46 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java @@ -51,6 +51,7 @@ public class IndustrialMiner extends MultiBlockMachine { protected final Map activeMiners = new HashMap<>(); protected final List fuelTypes = new ArrayList<>(); + private final OreDictionary oreDictionary; private final ItemSetting canMineAncientDebris = new ItemSetting<>(this, "can-mine-ancient-debris", false); private final ItemSetting canMineDeepslateOres = new ItemSetting<>(this, "can-mine-deepslate-ores", true); private final boolean silkTouch; @@ -58,8 +59,15 @@ public class IndustrialMiner extends MultiBlockMachine { @ParametersAreNonnullByDefault public IndustrialMiner(ItemGroup itemGroup, SlimefunItemStack item, Material baseMaterial, boolean silkTouch, int range) { - super(itemGroup, item, new ItemStack[] { null, null, null, new CustomItemStack(Material.PISTON, "活塞 (朝上)"), new ItemStack(Material.CHEST), new CustomItemStack(Material.PISTON, "活塞 (朝上)"), new ItemStack(baseMaterial), new ItemStack(Material.BLAST_FURNACE), new ItemStack(baseMaterial) }, BlockFace.UP); - + // @formatter:off + super(itemGroup, item, new ItemStack[] { + null, null, null, + new CustomItemStack(Material.PISTON, "Piston (facing up)"), new ItemStack(Material.CHEST), new CustomItemStack(Material.PISTON, "Piston (facing up)"), + new ItemStack(baseMaterial), new ItemStack(Material.BLAST_FURNACE), new ItemStack(baseMaterial) + }, BlockFace.UP); + // @formatter:on + + this.oreDictionary = OreDictionary.forVersion(Slimefun.getMinecraftVersion()); this.range = range; this.silkTouch = silkTouch; @@ -114,67 +122,17 @@ protected void registerDefaultFuelTypes() { /** * This method returns the outcome that mining certain ores yields. * - * @param ore + * @param material * The {@link Material} of the ore that was mined * * @return The outcome when mining this ore */ - public @Nonnull ItemStack getOutcome(@Nonnull Material ore) { + public @Nonnull ItemStack getOutcome(@Nonnull Material material) { if (hasSilkTouch()) { - return new ItemStack(ore); - } - - MinecraftVersion minecraftVersion = Slimefun.getMinecraftVersion(); - Random random = ThreadLocalRandom.current(); - - if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_17)) { - // In 1.17, breaking metal ores should get raw metals. Also support deepslate ores. - switch (ore) { - case DEEPSLATE_COAL_ORE: - return new ItemStack(Material.COAL); - case DEEPSLATE_DIAMOND_ORE: - return new ItemStack(Material.DIAMOND); - case DEEPSLATE_EMERALD_ORE: - return new ItemStack(Material.EMERALD); - case DEEPSLATE_REDSTONE_ORE: - return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2)); - case DEEPSLATE_LAPIS_ORE: - return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); - case COPPER_ORE: - case DEEPSLATE_COPPER_ORE: - return new ItemStack(Material.RAW_COPPER); - case IRON_ORE: - case DEEPSLATE_IRON_ORE: - return new ItemStack(Material.RAW_IRON); - case GOLD_ORE: - case DEEPSLATE_GOLD_ORE: - return new ItemStack(Material.RAW_GOLD); - default: - break; - } - } - - // In 1.16, breaking nether gold ores should get gold nuggets - if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_16) && ore == Material.NETHER_GOLD_ORE) { - return new ItemStack(Material.GOLD_NUGGET, 2 + random.nextInt(4)); - } - - switch (ore) { - case COAL_ORE: - return new ItemStack(Material.COAL); - case DIAMOND_ORE: - return new ItemStack(Material.DIAMOND); - case EMERALD_ORE: - return new ItemStack(Material.EMERALD); - case REDSTONE_ORE: - return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2)); - case LAPIS_ORE: - return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); - case NETHER_QUARTZ_ORE: - return new ItemStack(Material.QUARTZ); - default: - // This includes Iron and Gold ore (and Ancient Debris) - return new ItemStack(ore); + return new ItemStack(material); + } else { + Random random = ThreadLocalRandom.current(); + return oreDictionary.getDrops(material, random); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/MiningTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/MiningTask.java index aef3fadd5b..60a15a4b7f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/MiningTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/MiningTask.java @@ -36,9 +36,9 @@ /** * This represents a running instance of an {@link IndustrialMiner}. - * + * * @author TheBusyBiscuit - * + * * @see IndustrialMiner * @see AdvancedIndustrialMiner * @@ -55,9 +55,9 @@ class MiningTask implements Runnable { private final BlockPosition end; private final int height; - private int fuel = 0; - private int ores = 0; private boolean running = false; + private int fuelLevel = 0; + private int ores = 0; private int x; private int z; @@ -80,7 +80,7 @@ class MiningTask implements Runnable { /** * This starts the {@link IndustrialMiner} at the given {@link Block}. - * + * * @param b * The {@link Block} which marks the center of this {@link IndustrialMiner} */ @@ -102,7 +102,7 @@ void stop() { /** * This method stops the {@link IndustrialMiner} with an error message. * The error message is a path to the location in Slimefun's localization files. - * + * * @param reason * The reason why we stop */ @@ -120,14 +120,6 @@ void stop(@Nonnull MinerStoppingReason reason) { * This method starts the warm-up animation for the {@link IndustrialMiner}. */ private void warmUp() { - fuel = consumeFuel(); - - if (fuel <= 0) { - // This Miner has not enough fuel. - stop(MinerStoppingReason.NO_FUEL); - return; - } - /* * This is our warm up animation. * The pistons will push after another in decreasing intervals @@ -140,6 +132,21 @@ private void warmUp() { queue.thenRun(8, () -> setPistonState(pistons[1], true)); queue.thenRun(10, () -> setPistonState(pistons[1], false)); + /* + * Fixes #3336 + * Trigger each piston once, so that the structure is validated. + * Then consume fuel. + */ + queue.thenRun(() -> { + consumeFuel(); + + if (fuelLevel <= 0) { + // This Miner has not enough fuel. + stop(MinerStoppingReason.NO_FUEL); + return; + } + }); + queue.thenRun(6, () -> setPistonState(pistons[0], true)); queue.thenRun(9, () -> setPistonState(pistons[0], false)); @@ -196,7 +203,7 @@ public void run() { furnace.getWorld().playSound(furnace.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 0.2F, 1F); b.setType(Material.AIR); - fuel--; + fuelLevel--; ores++; // Repeat the same column when we hit an ore. @@ -216,7 +223,7 @@ public void run() { } /** - * This advanced the {@link IndustrialMiner} to the next column + * This advances the {@link IndustrialMiner} to the next column */ private void nextColumn() { if (x < end.getX()) { @@ -244,20 +251,20 @@ private void nextColumn() { /** * This refuels the {@link IndustrialMiner} and pushes the given {@link ItemStack} to * its {@link Chest}. - * + * * @param item * The {@link ItemStack} to push to the {@link Chest}. - * + * * @return Whether the operation was successful */ private boolean push(@Nonnull ItemStack item) { - if (fuel < 1) { + if (fuelLevel < 1) { // Restock fuel - fuel = consumeFuel(); + consumeFuel(); } // Check if there is enough fuel to run - if (fuel > 0) { + if (fuelLevel > 0) { if (chest.getType() == Material.CHEST) { BlockState state = PaperLib.getBlockState(chest, false).getState(); @@ -287,23 +294,19 @@ private boolean push(@Nonnull ItemStack item) { /** * This consumes fuel from the given {@link Chest}. - * - * @return The gained fuel value */ - private int consumeFuel() { + private void consumeFuel() { if (chest.getType() == Material.CHEST) { BlockState state = PaperLib.getBlockState(chest, false).getState(); if (state instanceof Chest) { Inventory inv = ((Chest) state).getBlockInventory(); - return consumeFuel(inv); + this.fuelLevel = grabFuelFrom(inv); } } - - return 0; } - private int consumeFuel(@Nonnull Inventory inv) { + private int grabFuelFrom(@Nonnull Inventory inv) { for (int i = 0; i < inv.getSize(); i++) { for (MachineFuel fuelType : miner.fuelTypes) { ItemStack item = inv.getContents()[i]; @@ -381,4 +384,4 @@ private void setExtended(@Nonnull Block block, @Nonnull Piston piston, boolean e block.getWorld().playSound(block.getLocation(), extended ? Sound.BLOCK_PISTON_EXTEND : Sound.BLOCK_PISTON_CONTRACT, 0.1F, 1F); } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary.java new file mode 100644 index 0000000000..39b6b3477d --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary.java @@ -0,0 +1,37 @@ +package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner; + +import java.util.Random; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; + +/** + * Simple interface to map ore blocks to their respective item(s). + * + * @author TheBusyBiscuit + * + */ +interface OreDictionary { + + @Nonnull + @ParametersAreNonnullByDefault + ItemStack getDrops(Material material, Random random); + + static @Nonnull OreDictionary forVersion(@Nonnull MinecraftVersion version) { + if (version.isAtLeast(MinecraftVersion.MINECRAFT_1_17)) { + // MC 1.17 - 1.18 + return new OreDictionary17(); + } else if (version.isAtLeast(MinecraftVersion.MINECRAFT_1_16)) { + // MC 1.16 + return new OreDictionary16(); + } else { + // MC 1.14 - 1.15 + return new OreDictionary14(); + } + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary14.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary14.java new file mode 100644 index 0000000000..54971fcf8f --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary14.java @@ -0,0 +1,44 @@ +package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner; + +import java.util.Random; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +/** + * Our {@link OreDictionary} implementation for MC 1.14 or higher. + * + * @author TheBusyBiscuit + * + */ +class OreDictionary14 implements OreDictionary { + + @Override + @ParametersAreNonnullByDefault + public @Nonnull ItemStack getDrops(Material material, Random random) { + switch (material) { + case COAL_ORE: + return new ItemStack(Material.COAL); + case DIAMOND_ORE: + return new ItemStack(Material.DIAMOND); + case EMERALD_ORE: + return new ItemStack(Material.EMERALD); + case REDSTONE_ORE: + return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2)); + case LAPIS_ORE: + return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); + case NETHER_QUARTZ_ORE: + return new ItemStack(Material.QUARTZ); + case IRON_ORE: + return new ItemStack(Material.IRON_ORE); + case GOLD_ORE: + return new ItemStack(Material.GOLD_ORE); + default: + return new ItemStack(material); + } + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary16.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary16.java new file mode 100644 index 0000000000..242c88ee92 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary16.java @@ -0,0 +1,33 @@ +package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner; + +import java.util.Random; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +/** + * Our {@link OreDictionary} implementation for MC 1.16 or higher. + * + * @author TheBusyBiscuit + * + */ +class OreDictionary16 extends OreDictionary14 { + + @Override + @ParametersAreNonnullByDefault + public @Nonnull ItemStack getDrops(Material material, Random random) { + switch (material) { + case NETHER_GOLD_ORE: + // In 1.16, breaking nether gold ores should get gold nuggets + return new ItemStack(Material.GOLD_NUGGET, 2 + random.nextInt(4)); + case ANCIENT_DEBRIS: + return new ItemStack(Material.ANCIENT_DEBRIS); + default: + return super.getDrops(material, random); + } + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary17.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary17.java new file mode 100644 index 0000000000..ae1c140eb5 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/OreDictionary17.java @@ -0,0 +1,52 @@ +package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner; + +import java.util.Random; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +/** + * Our {@link OreDictionary} implementation for MC 1.17 or higher. + * + * @author TheBusyBiscuit + * + */ +class OreDictionary17 extends OreDictionary16 { + + @Override + @ParametersAreNonnullByDefault + public ItemStack getDrops(Material material, Random random) { + // In 1.17, breaking metal ores should get raw metals. Also support deepslate ores. + switch (material) { + case COAL_ORE: + case DEEPSLATE_COAL_ORE: + return new ItemStack(Material.COAL); + case DIAMOND_ORE: + case DEEPSLATE_DIAMOND_ORE: + return new ItemStack(Material.DIAMOND); + case EMERALD_ORE: + case DEEPSLATE_EMERALD_ORE: + return new ItemStack(Material.EMERALD); + case REDSTONE_ORE: + case DEEPSLATE_REDSTONE_ORE: + return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2)); + case LAPIS_ORE: + case DEEPSLATE_LAPIS_ORE: + return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); + case COPPER_ORE: + case DEEPSLATE_COPPER_ORE: + return new ItemStack(Material.RAW_COPPER); + case IRON_ORE: + case DEEPSLATE_IRON_ORE: + return new ItemStack(Material.RAW_IRON); + case GOLD_ORE: + case DEEPSLATE_GOLD_ORE: + return new ItemStack(Material.RAW_GOLD); + default: + return super.getDrops(material, random); + } + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java index 8465a9db8b..46aefadbbb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -504,11 +504,13 @@ public static boolean canPlayerUseItem(@Nonnull Player p, @Nullable ItemStack it } /** - * Helper method to check if an Inventory is empty (has no items in "storage"). If the MC version is 1.16 or above + * Helper method to check if an Inventory is empty (has no items in "storage"). + * If the MC version is 1.16 or above * this will call {@link Inventory#isEmpty()} (Which calls MC code resulting in a faster method). * * @param inventory * The {@link Inventory} to check. + * * @return True if the inventory is empty and false otherwise */ public static boolean isInventoryEmpty(@Nonnull Inventory inventory) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/WorldUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/WorldUtils.java index 072e435037..0484654ecc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/WorldUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/WorldUtils.java @@ -37,6 +37,7 @@ public static int getMinHeight(@Nonnull World world) { if (major.isAtLeast(MinecraftVersion.MINECRAFT_1_17) || major.isMinecraftVersion(16) && patch == 5) { return world.getMinHeight(); } else { + // Default to zero for pre-1.16 worlds return 0; } }