From 451756bc81a917cb488059bb865334b1c00f8777 Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 12 Jul 2018 21:25:07 -0700 Subject: [PATCH] Added clean super-flat world setting and test --- locales/en-US.yml | 6 + .../us/tastybento/bskyblock/BSkyBlock.java | 27 ++- .../flags/CleanSuperFlatListener.java | 42 ++++ .../us/tastybento/bskyblock/lists/Flags.java | 6 +- .../flags/CleanSuperFlatListenerTest.java | 181 ++++++++++++++++++ 5 files changed, 259 insertions(+), 3 deletions(-) create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListener.java create mode 100644 src/test/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListenerTest.java diff --git a/locales/en-US.yml b/locales/en-US.yml index b74030dca..02c27a745 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -320,6 +320,12 @@ protection: description: "Toggle teleportation" name: "Chorus fruits" hint: "No teleporting" + CLEAN_SUPER_FLAT: + description: | + Enable to clean any + super-flat chunks in + island worlds + name: "Clean Super Flat" COLLECT_LAVA: description: | Toggle collecting lava diff --git a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java index 33d8d12d5..382511da7 100755 --- a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java +++ b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java @@ -62,8 +62,12 @@ public class BSkyBlock extends JavaPlugin { private HeadGetter headGetter; + private boolean isLoaded; + @Override public void onEnable(){ + // Not loaded + setLoaded(false); // Store the current millis time so we can tell how many ms it took for BSB to fully load. final long startMillis = System.currentTimeMillis(); @@ -142,6 +146,7 @@ public class BSkyBlock extends JavaPlugin { instance.log("Thanks for using our plugin !"); instance.log("- Tastybento and Poslovitch, 2017-2018"); instance.log("#############################################"); + instance.setLoaded(true); }); }); } @@ -182,7 +187,9 @@ public class BSkyBlock extends JavaPlugin { islandsManager.shutdown(); } // Save settings - new BSBConfig<>(this, Settings.class).saveConfigObject(settings); + if (isEnabled()) { + new BSBConfig<>(this, Settings.class).saveConfigObject(settings); + } } private void registerCustomCharts(){ @@ -339,4 +346,22 @@ public class BSkyBlock extends JavaPlugin { } + + /** + * @return the isLoaded + */ + public boolean isLoaded() { + return isLoaded; + } + + + + /** + * @param isLoaded the isLoaded to set + */ + public void setLoaded(boolean isLoaded) { + this.isLoaded = isLoaded; + } + + } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListener.java new file mode 100644 index 000000000..19e4549fd --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListener.java @@ -0,0 +1,42 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.flags.AbstractFlagListener; +import us.tastybento.bskyblock.lists.Flags; + +/** + * Cleans super-flat world chunks or normal nether chunks if they generate accidentally + * due to lack of a generator being loaded + * @author tastybento + * + */ +public class CleanSuperFlatListener extends AbstractFlagListener { + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onChunkLoad(ChunkLoadEvent e) { + BSkyBlock plugin = BSkyBlock.getInstance(); + if (!plugin.isLoaded()) { + return; + } + World world = e.getWorld(); + if (!e.getChunk().getBlock(0, 0, 0).getType().equals(Material.BEDROCK) + || !Flags.CLEAN_SUPER_FLAT.isSetForWorld(world) + || (world.getEnvironment().equals(Environment.NETHER) && (!plugin.getIWM().isNetherGenerate(world) || !plugin.getIWM().isNetherIslands(world))) + || (world.getEnvironment().equals(Environment.THE_END) && (!plugin.getIWM().isEndGenerate(world) || !plugin.getIWM().isEndIslands(world)))) { + return; + } + world.regenerateChunk(e.getChunk().getX(), e.getChunk().getZ()); + plugin.logWarning("Regenerating superflat chunk at " + (e.getChunk().getX() * 16) + "," + (e.getChunk().getZ() * 16)); + + } + +} diff --git a/src/main/java/us/tastybento/bskyblock/lists/Flags.java b/src/main/java/us/tastybento/bskyblock/lists/Flags.java index cb7ffa12e..9ec3f9b5f 100644 --- a/src/main/java/us/tastybento/bskyblock/lists/Flags.java +++ b/src/main/java/us/tastybento/bskyblock/lists/Flags.java @@ -16,6 +16,7 @@ import us.tastybento.bskyblock.listeners.flags.BlockInteractionListener; import us.tastybento.bskyblock.listeners.flags.BreakBlocksListener; import us.tastybento.bskyblock.listeners.flags.BreedingListener; import us.tastybento.bskyblock.listeners.flags.BucketListener; +import us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener; import us.tastybento.bskyblock.listeners.flags.EggListener; import us.tastybento.bskyblock.listeners.flags.EnderChestListener; import us.tastybento.bskyblock.listeners.flags.EnterExitListener; @@ -52,7 +53,7 @@ public class Flags { // TODO: add KEEP_INVENTORY - is it needed? public static final Flag BREAK_BLOCKS = new FlagBuilder().id("BREAK_BLOCKS").icon(Material.STONE).listener(new BreakBlocksListener()).build(); - public static final Flag PLACE_BLOCKS = new FlagBuilder().id("PLACE_BLOCKS").icon(Material.BEDROCK).listener(new PlaceBlocksListener()).build(); + public static final Flag PLACE_BLOCKS = new FlagBuilder().id("PLACE_BLOCKS").icon(Material.GRASS).listener(new PlaceBlocksListener()).build(); // Block interactions - all use BlockInteractionListener() public static final Flag ANVIL = new FlagBuilder().id("ANVIL").icon(Material.ANVIL).listener(new BlockInteractionListener()).build(); @@ -180,7 +181,8 @@ public class Flags { .listener(new IslandRespawnListener()).allowedByDefault(true).onClick(new WorldToggleClickListener("ISLAND_RESPAWN")).build(); public static final Flag OFFLINE_REDSTONE = new FlagBuilder().id("OFFLINE_REDSTONE").icon(Material.REDSTONE_COMPARATOR).type(Type.WORLD_SETTING) .listener(new OfflineRedstoneListener()).allowedByDefault(true).onClick(new WorldToggleClickListener("OFFLINE_REDSTONE")).build(); - + public static final Flag CLEAN_SUPER_FLAT = new FlagBuilder().id("CLEAN_SUPER_FLAT").icon(Material.BEDROCK).type(Type.WORLD_SETTING) + .listener(new CleanSuperFlatListener()).allowedByDefault(false).onClick(new WorldToggleClickListener("CLEAN_SUPER_FLAT")).build(); /** * @return List of all the flags in this class */ diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListenerTest.java new file mode 100644 index 000000000..d8fb9bb20 --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/CleanSuperFlatListenerTest.java @@ -0,0 +1,181 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.inventory.ItemFactory; +import org.bukkit.inventory.meta.ItemMeta; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.configuration.WorldSettings; +import us.tastybento.bskyblock.lists.Flags; +import us.tastybento.bskyblock.managers.IslandWorldManager; +import us.tastybento.bskyblock.util.Util; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BSkyBlock.class, Util.class }) +public class CleanSuperFlatListenerTest { + + private World world; + private Block block; + private Chunk chunk; + private IslandWorldManager iwm; + private BSkyBlock plugin; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + + // Set up plugin + plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + + when(plugin.isLoaded()).thenReturn(true); + + // World + world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(world); + + // World Settings + iwm = mock(IslandWorldManager.class); + when(plugin.getIWM()).thenReturn(iwm); + WorldSettings ws = mock(WorldSettings.class); + when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws); + Map worldFlags = new HashMap<>(); + when(ws.getWorldFlags()).thenReturn(worldFlags); + when(iwm.isNetherGenerate(Mockito.any())).thenReturn(true); + when(iwm.isEndGenerate(Mockito.any())).thenReturn(true); + when(iwm.isNetherIslands(Mockito.any())).thenReturn(true); + when(iwm.isEndIslands(Mockito.any())).thenReturn(true); + + + PowerMockito.mockStatic(Bukkit.class); + ItemFactory itemF = mock(ItemFactory.class); + ItemMeta im = mock(ItemMeta.class); + when(itemF.getItemMeta(Mockito.any())).thenReturn(im); + when(Bukkit.getItemFactory()).thenReturn(itemF); + + Flags.CLEAN_SUPER_FLAT.setSetting(world, true); + + chunk = mock(Chunk.class); + when(chunk.getWorld()).thenReturn(world); + block = mock(Block.class); + when(block.getType()).thenReturn(Material.BEDROCK); + when(chunk.getBlock(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(block); + + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener#onChunkLoad(org.bukkit.event.world.ChunkLoadEvent)}. + */ + @Test + public void testOnChunkLoadNotBedrockNoFlsg() { + when(block.getType()).thenReturn(Material.AIR); + Flags.CLEAN_SUPER_FLAT.setSetting(world, false); + + ChunkLoadEvent e = new ChunkLoadEvent(chunk, false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world, Mockito.never()).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener#onChunkLoad(org.bukkit.event.world.ChunkLoadEvent)}. + */ + @Test + public void testOnChunkLoadNotLoaded() { + when(plugin.isLoaded()).thenReturn(false); + ChunkLoadEvent e = new ChunkLoadEvent(chunk, false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world, Mockito.never()).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener#onChunkLoad(org.bukkit.event.world.ChunkLoadEvent)}. + */ + @Test + public void testOnChunkLoadBedrock() { + ChunkLoadEvent e = new ChunkLoadEvent(chunk, false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener#onChunkLoad(org.bukkit.event.world.ChunkLoadEvent)}. + */ + @Test + public void testOnChunkLoadBedrockNoClean() { + Flags.CLEAN_SUPER_FLAT.setSetting(world, false); + + ChunkLoadEvent e = new ChunkLoadEvent(chunk, false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world, Mockito.never()).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener#onChunkLoad(org.bukkit.event.world.ChunkLoadEvent)}. + */ + @Test + public void testOnChunkLoadBedrockNether() { + when(world.getEnvironment()).thenReturn(World.Environment.NETHER); + ChunkLoadEvent e = new ChunkLoadEvent(chunk, false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); + when(iwm.isNetherGenerate(Mockito.any())).thenReturn(false); + when(iwm.isNetherIslands(Mockito.any())).thenReturn(true); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); // No more than once + when(iwm.isNetherGenerate(Mockito.any())).thenReturn(true); + when(iwm.isNetherIslands(Mockito.any())).thenReturn(false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); // No more than once + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.CleanSuperFlatListener#onChunkLoad(org.bukkit.event.world.ChunkLoadEvent)}. + */ + @Test + public void testOnChunkLoadBedrockEnd() { + when(world.getEnvironment()).thenReturn(World.Environment.THE_END); + ChunkLoadEvent e = new ChunkLoadEvent(chunk, false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); + when(iwm.isEndGenerate(Mockito.any())).thenReturn(false); + when(iwm.isEndIslands(Mockito.any())).thenReturn(true); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); // No more than once + when(iwm.isEndGenerate(Mockito.any())).thenReturn(true); + when(iwm.isEndIslands(Mockito.any())).thenReturn(false); + new CleanSuperFlatListener().onChunkLoad(e); + Mockito.verify(world).regenerateChunk(Mockito.anyInt(), Mockito.anyInt()); // No more than once + } + +}