diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java index 21b5dd84d..cb990ecff 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java @@ -2,7 +2,6 @@ package world.bentobox.bentobox.api.commands.island; import java.io.IOException; import java.util.List; -import java.util.Set; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.island.IslandEvent.Reason; @@ -62,12 +61,11 @@ public class IslandCreateCommand extends CompositeCommand { return false; } // Check the schem name exists - Set validNames = getPlugin().getSchemsManager().get(getWorld()).keySet(); - if (!validNames.contains(name)) { + name = getPlugin().getSchemsManager().validate(getWorld(), name); + if (name == null) { user.sendMessage("commands.island.create.unknown-schem"); return false; } - } user.sendMessage("commands.island.create.creating-island"); try { diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java index bca5b7f1f..709532f1c 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java @@ -14,7 +14,6 @@ import world.bentobox.bentobox.managers.island.NewIsland; import java.io.IOException; import java.util.List; -import java.util.Set; /** * @author tastybento @@ -103,13 +102,7 @@ public class IslandResetCommand extends ConfirmableCommand { if (args.isEmpty()) { return SchemsManager.DEFAULT_SCHEM_NAME; } - - String name = args.get(0).toLowerCase(java.util.Locale.ENGLISH); - Set validNames = getPlugin().getSchemsManager().get(getWorld()).keySet(); - if (!name.equals(SchemsManager.DEFAULT_SCHEM_NAME) && !validNames.contains(name)) { - return null; - } - return name; + return getPlugin().getSchemsManager().validate(getWorld(), args.get(0).toLowerCase(java.util.Locale.ENGLISH)); } private boolean resetIsland(User user, String name) { diff --git a/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java b/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java index 083801797..3343fb41f 100644 --- a/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java @@ -7,12 +7,14 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.TreeMap; import java.util.jar.JarFile; import org.bukkit.World; import org.bukkit.configuration.InvalidConfigurationException; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.addons.Addon; @@ -91,19 +93,30 @@ public class SchemsManager { FilenameFilter schemFilter = (File dir, String name) -> name.toLowerCase(java.util.Locale.ENGLISH).endsWith(FILE_EXTENSION) && !name.toLowerCase(java.util.Locale.ENGLISH).startsWith("nether-") && !name.toLowerCase(java.util.Locale.ENGLISH).startsWith("end-"); - Arrays.stream(Objects.requireNonNull(schems.list(schemFilter))).map(name -> name.substring(0, name.length() - 6)).forEach(name -> { - if (!plugin.getSchemsManager().loadSchem(addon.getOverWorld(), schems, name)) { - plugin.logError("Could not load " + name + ".schem for " + addon.getWorldSettings().getFriendlyName()); - } - if (addon.getWorldSettings().isNetherGenerate() && addon.getWorldSettings().isNetherIslands() - && !plugin.getSchemsManager().loadSchem(addon.getNetherWorld(), schems, "nether-" + name)) { - plugin.logError("Could not load nether-" + name + ".schem for " + addon.getWorldSettings().getFriendlyName()); - } - if (addon.getWorldSettings().isEndGenerate() && addon.getWorldSettings().isEndIslands() - && !plugin.getSchemsManager().loadSchem(addon.getEndWorld(), schems, "end-" + name)) { - plugin.logError("Could not load end-" + name + ".schem for " + addon.getWorldSettings().getFriendlyName()); - } - }); + Arrays.stream(Objects.requireNonNull(schems.list(schemFilter))).map(name -> name.substring(0, name.length() - 6)).forEach(name -> importSchem(addon, schems, name)); + } + + + + /** + * Imports one schem to the game mode + * @param addon + * @param schems + * @param name + */ + private void importSchem(GameModeAddon addon, File schems, String name) { + if (!plugin.getSchemsManager().loadSchem(addon.getOverWorld(), schems, name)) { + plugin.logError("Could not load " + name + ".schem for " + addon.getWorldSettings().getFriendlyName()); + } + if (addon.getWorldSettings().isNetherGenerate() && addon.getWorldSettings().isNetherIslands() + && !plugin.getSchemsManager().loadSchem(addon.getNetherWorld(), schems, "nether-" + name)) { + plugin.logError("Could not load nether-" + name + ".schem for " + addon.getWorldSettings().getFriendlyName()); + } + if (addon.getWorldSettings().isEndGenerate() && addon.getWorldSettings().isEndIslands() + && !plugin.getSchemsManager().loadSchem(addon.getEndWorld(), schems, "end-" + name)) { + plugin.logError("Could not load end-" + name + ".schem for " + addon.getWorldSettings().getFriendlyName()); + } + } private boolean loadSchem(World world, File schems, String name) { @@ -146,4 +159,22 @@ public class SchemsManager { plugin.log("This might be due to an invalid schem format. Keep in mind that schems are not schematics."); } } + + + /** + * Check if a schem is valid for this game mode or not + * @param world - the world to check + * @param name - name of schem (not including .schem) + * @return name if valid, null if not + */ + public @Nullable String validate(World world, String name) { + Set validNames = get(world).keySet(); + if (!name.equals(SchemsManager.DEFAULT_SCHEM_NAME) && !validNames.contains(name)) { + // See if it has not been loaded yet + + return null; + } + return name; + + } } diff --git a/src/main/java/world/bentobox/bentobox/schems/Clipboard.java b/src/main/java/world/bentobox/bentobox/schems/Clipboard.java index af97a90d9..1c01f6185 100644 --- a/src/main/java/world/bentobox/bentobox/schems/Clipboard.java +++ b/src/main/java/world/bentobox/bentobox/schems/Clipboard.java @@ -118,7 +118,7 @@ public class Clipboard { /** * Copy the blocks between pos1 and pos2 to the clipboard * @param user - user - * @return true if successful, false if pos1 or pos2 are undefined + * @return true if successful, false if pos1 or pos2 are undefined or something is already in the clipboard */ public boolean copy(User user, boolean copyAir) { if (pos1 == null || pos2 == null) { @@ -166,7 +166,8 @@ public class Clipboard { } /** - * Pastes the clipboard to island location + * Pastes the clipboard to island location. + * If pos1 and pos2 are not set already, they are automatically set to the pasted coordinates * @param world - world in which to paste * @param island - location to paste * @param task - task to run after pasting @@ -185,7 +186,7 @@ public class Clipboard { } private void paste(World world, Island island, Location loc, Runnable task) { - new Paster(plugin, blockConfig, world, island, loc, task); + new Paster(plugin, this, blockConfig, world, island, loc, task); } /** @@ -392,6 +393,9 @@ public class Clipboard { blockConfig.load(file); copied = true; Files.delete(file.toPath()); + // Clear pos1 and 2 + setPos1(null); + setPos2(null); } /* @@ -400,7 +404,7 @@ public class Clipboard { /** * @param user - use trying to load * @param fileName - filename - * @return - ture if load is successful, false if not + * @return - true if load is successful, false if not */ public boolean load(User user, String fileName) { try { diff --git a/src/main/java/world/bentobox/bentobox/schems/Paster.java b/src/main/java/world/bentobox/bentobox/schems/Paster.java index 744d39b87..bff27c89a 100644 --- a/src/main/java/world/bentobox/bentobox/schems/Paster.java +++ b/src/main/java/world/bentobox/bentobox/schems/Paster.java @@ -50,7 +50,11 @@ public class Paster { CANCEL } - BentoBox plugin; + private BentoBox plugin; + // The minimum block position (x,y,z) + private Location pos1; + // The maximum block position (x,y,z) + private Location pos2; // Speed of pasting private int pasteSpeed; @@ -68,7 +72,17 @@ public class Paster { - public Paster(final BentoBox plugin, final YamlConfiguration blockConfig, final World world, final Island island, final Location loc, final Runnable task) { + /** + * Pastes a schem + * @param plugin - BentoBox instance + * @param clipboard - the clipboard that called this paster + * @param blockConfig - the schem Yaml File + * @param world - the world to paste into + * @param island - the island object + * @param loc - the location to paste to + * @param task - the task the run after pasting + */ + public Paster(final BentoBox plugin, Clipboard clipboard, final YamlConfiguration blockConfig, final World world, final Island island, final Location loc, final Runnable task) { this.plugin = plugin; if (!blockConfig.contains(BLOCKS_YAML_PREFIX)) { plugin.logError("Clipboard has no block data in it to paste!"); @@ -117,6 +131,11 @@ public class Paster { } if (pasteState.equals(PasteState.DONE)) { // All done. Cancel task + // Set pos1 and 2 if this was a clipboard paste + if (island == null && (clipboard.getPos1() == null || clipboard.getPos2() == null)) { + clipboard.setPos1(pos1); + clipboard.setPos2(pos2); + } if (task != null) { // Run follow-on task if it exists Bukkit.getScheduler().runTask(plugin, task); @@ -145,6 +164,42 @@ public class Paster { if (config.isConfigurationSection(ENTITY)) { setEntity(block.getLocation(), config.getConfigurationSection(ENTITY)); } + // pos1 and pos2 update + updatePos(world, x,y,z); + } + + /** + * Tracks the minimum and maximum block positions + * @param world - world + * @param x - x + * @param y - y + * @param z - z + */ + private void updatePos(World world, int x, int y, int z) { + if (pos1 == null) { + pos1 = new Location(world, x, y, z); + } + if (pos2 == null) { + pos2 = new Location(world, x, y, z); + } + if (x < pos1.getBlockX()) { + pos1.setX(x); + } + if (x > pos2.getBlockX()) { + pos2.setX(x); + } + if (y < pos1.getBlockY()) { + pos1.setY(y); + } + if (y > pos2.getBlockY()) { + pos2.setY(y); + } + if (z < pos1.getBlockZ()) { + pos1.setZ(z); + } + if (z > pos2.getBlockZ()) { + pos2.setZ(z); + } } private void pasteEntity(World world, Location location, ConfigurationSection config) { diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java index a8f852ab0..a96019efd 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java @@ -268,7 +268,7 @@ public class IslandCreateCommandTest { */ @Test public void testExecuteUserStringListOfStringKnownSchem() throws IOException { - when(sm.get(Mockito.any())).thenReturn(Collections.singletonMap("custom", mock(Clipboard.class))); + when(sm.validate(Mockito.any(), Mockito.any())).thenReturn("custom"); assertTrue(cc.execute(user, "", Collections.singletonList("custom"))); Mockito.verify(builder).player(Mockito.eq(user)); Mockito.verify(builder).world(Mockito.any()); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java index 6e9e437a6..f8ce884d7 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java @@ -1,5 +1,16 @@ package world.bentobox.bentobox.api.commands.island; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.UUID; + import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; @@ -13,6 +24,7 @@ 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 world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.api.commands.CompositeCommand; @@ -24,19 +36,6 @@ import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.PlayersManager; import world.bentobox.bentobox.managers.SchemsManager; import world.bentobox.bentobox.managers.island.NewIsland; -import world.bentobox.bentobox.schems.Clipboard; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author tastybento @@ -118,9 +117,7 @@ public class IslandResetCommandTest { // Schems manager - custom schem SchemsManager sm = mock(SchemsManager.class); - Map map = new HashMap<>(); - map.put("custom", null); - when(sm.get(Mockito.any())).thenReturn(map); + when(sm.validate(Mockito.any(), Mockito.any())).thenReturn("custom"); when(plugin.getSchemsManager()).thenReturn(sm); }