Improvements to the Paster (#632)

* Version up 1.4.1-SNAPSHOT

* Sets pos1 and pos2 after pasting a loaded schem

Corrects version name in POM.

* Shifted schem name validation into SchemsManager
This commit is contained in:
tastybento 2019-04-13 16:54:04 -07:00 committed by Florian CUNY
parent 141e1d388d
commit 4e73d7de5a
7 changed files with 126 additions and 48 deletions

View File

@ -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<String> 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 {

View File

@ -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<String> 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) {

View File

@ -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, <tt>null</tt> if not
*/
public @Nullable String validate(World world, String name) {
Set<String> 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;
}
}

View File

@ -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 - <tt>true</tt> if load is successful, <tt>false</tt> if not
*/
public boolean load(User user, String fileName) {
try {

View File

@ -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) {

View File

@ -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());

View File

@ -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<String, Clipboard> 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);
}