From fa33dd6259c3aa3a71a9405d9376eb8671007d0e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 16 Nov 2024 18:57:15 -0800 Subject: [PATCH] Version 4.4.0 (#135) * Version 4.2.2 * Added protection against console error spam if island size is zero. If the protection range is 0 then the caluclations to teleport players back into the border will result in infinite values and other strangeness so this prevents that. This is an edge case and only really happens when the island size has been set wrongly. * Update README.md * Fix perm issue #120 (#121) * feat: detect mounted players on entity (#88) * Version 4.3.0 * Changes to work with 1.20.6. Has backwards compatibility. (#125) * Fix imports * Update zh-CN.yml (#127) * Latvian translationa (#128) * Translate lv.yml via GitLocalize * Translate lv.yml via GitLocalize --------- Co-authored-by: mt-gitlocalize Co-authored-by: tastybento * Add explicit bordertype command (#130) * Add explicit bordertype command * Add perm to addon.yml and make it default to off * Remove unused method. * 131 null to location (#132) * Version 4.3.1 * Add defensive code for null to's #131 * If border is off, then don't move player back. * Update to MC 1.21.3 and codemc updates (#134) --------- Co-authored-by: evlad Co-authored-by: Minecraft_15 <147026380+huguyt@users.noreply.github.com> Co-authored-by: gitlocalize-app[bot] <55277160+gitlocalize-app[bot]@users.noreply.github.com> Co-authored-by: mt-gitlocalize --- pom.xml | 18 +- .../java/world/bentobox/border/Border.java | 2 + .../border/commands/BorderTypeCommand.java | 7 +- .../border/commands/IslandBorderCommand.java | 2 +- .../border/listeners/BlockListener.java | 325 ++++++++++++++++++ .../border/listeners/PlayerListener.java | 31 +- src/main/resources/addon.yml | 5 +- src/main/resources/locales/lv.yml | 4 + src/main/resources/locales/zh-CN.yml | 13 +- .../commands/BorderTypeCommandTest.java | 10 +- 10 files changed, 377 insertions(+), 40 deletions(-) create mode 100644 src/main/java/world/bentobox/border/listeners/BlockListener.java diff --git a/pom.xml b/pom.xml index c856070..92442e1 100644 --- a/pom.xml +++ b/pom.xml @@ -33,13 +33,9 @@ - - codemc-snapshots - https://repo.codemc.org/repository/maven-snapshots - - codemc-releases - https://repo.codemc.org/repository/maven-releases + bentoboxworld + https://repo.codemc.org/repository/bentoboxworld/ @@ -49,12 +45,12 @@ 17 2.0.9 - 1.20.4-R0.1-SNAPSHOT - 2.0.0-SNAPSHOT + 1.21.3-R0.1-SNAPSHOT + 2.7.1-SNAPSHOT ${build.version}-SNAPSHOT - 4.3.0 + 4.4.0 -LOCAL BentoBoxWorld_Border @@ -109,6 +105,10 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots + + bentoboxworld + https://repo.codemc.org/repository/bentoboxworld/ + codemc https://repo.codemc.org/repository/maven-snapshots/ diff --git a/src/main/java/world/bentobox/border/Border.java b/src/main/java/world/bentobox/border/Border.java index 54b1ba8..78d7d65 100644 --- a/src/main/java/world/bentobox/border/Border.java +++ b/src/main/java/world/bentobox/border/Border.java @@ -14,6 +14,7 @@ import world.bentobox.bentobox.api.configuration.Config; import world.bentobox.bentobox.api.metadata.MetaDataValue; import world.bentobox.bentobox.util.Util; +import world.bentobox.border.commands.BorderTypeCommand; import world.bentobox.border.commands.IslandBorderCommand; import world.bentobox.border.listeners.BorderShower; import world.bentobox.border.listeners.PlayerListener; @@ -52,6 +53,7 @@ public void onEnable() { log("Border hooking into " + gameModeAddon.getDescription().getName()); gameModeAddon.getPlayerCommand().ifPresent(c -> new IslandBorderCommand(this, c, "border")); + gameModeAddon.getPlayerCommand().ifPresent(c -> new BorderTypeCommand(this, c, "bordertype")); } }); diff --git a/src/main/java/world/bentobox/border/commands/BorderTypeCommand.java b/src/main/java/world/bentobox/border/commands/BorderTypeCommand.java index 44dc8d3..e4f183b 100644 --- a/src/main/java/world/bentobox/border/commands/BorderTypeCommand.java +++ b/src/main/java/world/bentobox/border/commands/BorderTypeCommand.java @@ -19,13 +19,12 @@ */ public final class BorderTypeCommand extends CompositeCommand { - public static final String BORDER_TYPE_COMMAND_PERM = "border.type"; private final Border addon; private Island island; private final List availableTypes; - public BorderTypeCommand(Border addon, CompositeCommand parent) { - super(addon, parent, "type"); + public BorderTypeCommand(Border addon, CompositeCommand parent, String commandLabel) { + super(addon, parent, commandLabel); this.addon = addon; this.availableTypes = addon.getAvailableBorderTypesView() .stream() @@ -35,7 +34,7 @@ public BorderTypeCommand(Border addon, CompositeCommand parent) { @Override public void setup() { - this.setPermission(BORDER_TYPE_COMMAND_PERM); + this.setPermission("border." + this.getLabel()); this.setDescription("border.set-type.description"); this.setOnlyPlayer(true); } diff --git a/src/main/java/world/bentobox/border/commands/IslandBorderCommand.java b/src/main/java/world/bentobox/border/commands/IslandBorderCommand.java index 2963909..3a552cc 100644 --- a/src/main/java/world/bentobox/border/commands/IslandBorderCommand.java +++ b/src/main/java/world/bentobox/border/commands/IslandBorderCommand.java @@ -28,7 +28,7 @@ public void setup() { this.setOnlyPlayer(true); setConfigurableRankCommand(); - new BorderTypeCommand(this.getAddon(), this); + new BorderTypeCommand(this.getAddon(), this, "type"); } @Override diff --git a/src/main/java/world/bentobox/border/listeners/BlockListener.java b/src/main/java/world/bentobox/border/listeners/BlockListener.java new file mode 100644 index 0000000..a7d187d --- /dev/null +++ b/src/main/java/world/bentobox/border/listeners/BlockListener.java @@ -0,0 +1,325 @@ +package world.bentobox.border.listeners; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDismountEvent; +import org.bukkit.event.entity.EntityMountEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.event.vehicle.VehicleMoveEvent; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.RayTraceResult; +import org.bukkit.util.Vector; + +import world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent; +import world.bentobox.bentobox.api.flags.Flag; +import world.bentobox.bentobox.api.metadata.MetaDataValue; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; +import world.bentobox.border.Border; +import world.bentobox.border.PerPlayerBorderProxy; +import world.bentobox.border.commands.IslandBorderCommand; + +/** + * @author tastybento + */ +public class BlockListener implements Listener { + + private static final Vector XZ = new Vector(1,0,1); + private final Border addon; + private Set inTeleport; + private final BorderShower show; + private Map mountedPlayers = new HashMap<>(); + + public BlockListener(Border addon) { + this.addon = addon; + inTeleport = new HashSet<>(); + this.show = addon.getBorderShower(); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerJoin(PlayerJoinEvent e) { + // Run one-tick after joining because meta data cannot be set otherwise + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> processEvent(e)); + } + + protected void processEvent(PlayerJoinEvent e) { + User user = User.getInstance(e.getPlayer()); + + show.hideBorder(user); + // Just for sure, disable world Border + user.getPlayer().setWorldBorder(null); + + // Get the game mode that this player is in + addon.getPlugin().getIWM().getAddon(e.getPlayer().getWorld()).map(gma -> gma.getPermissionPrefix()).filter( + permPrefix -> !e.getPlayer().hasPermission(permPrefix + IslandBorderCommand.BORDER_COMMAND_PERM)) + .ifPresent(permPrefix -> { + // Restore barrier on/off to default + user.putMetaData(BorderShower.BORDER_STATE_META_DATA, + new MetaDataValue(addon.getSettings().isShowByDefault())); + if (!e.getPlayer().hasPermission(permPrefix + "border.type") && !e.getPlayer().hasPermission(permPrefix + "border.bordertype")) { + // Restore default barrier type to player + MetaDataValue metaDataValue = new MetaDataValue(addon.getSettings().getType().getId()); + user.putMetaData(PerPlayerBorderProxy.BORDER_BORDERTYPE_META_DATA, metaDataValue); + } + }); + + // Show the border if required one tick after + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands().getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> + show.showBorder(e.getPlayer(), i))); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerQuit(PlayerQuitEvent e) { + show.clearUser(User.getInstance(e.getPlayer())); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerRespawn(PlayerRespawnEvent e) { + show.clearUser(User.getInstance(e.getPlayer())); + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands().getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> + show.showBorder(e.getPlayer(), i))); + } + + private boolean isOn(Player player) { + // Check if border is off + User user = User.getInstance(player); + return user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean) + .orElse(addon.getSettings().isShowByDefault()); + + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onPlayerTeleport(PlayerTeleportEvent e) { + Player player = e.getPlayer(); + if (!isOn(player)) { + return; + } + Location to = e.getTo(); + + show.clearUser(User.getInstance(player)); + + if (to == null || !addon.inGameWorld(to.getWorld())) { + return; + } + + TeleportCause cause = e.getCause(); + boolean isBlacklistedCause = cause == TeleportCause.ENDER_PEARL || cause == TeleportCause.CHORUS_FRUIT; + + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> + addon.getIslands().getIslandAt(to).ifPresentOrElse(i -> { + Optional boxedEnderPearlFlag = i.getPlugin().getFlagsManager().getFlag("ALLOW_MOVE_BOX"); + + if (isBlacklistedCause + && (!i.getProtectionBoundingBox().contains(to.toVector()) + || !i.onIsland(player.getLocation()))) { + e.setCancelled(true); + } + + if (boxedEnderPearlFlag.isPresent() + && boxedEnderPearlFlag.get().isSetForWorld(to.getWorld()) + && cause == TeleportCause.ENDER_PEARL) { + e.setCancelled(false); + } + + show.showBorder(player, i); + }, () -> { + if (isBlacklistedCause) { + e.setCancelled(true); + return; + } + }) + ); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerLeaveIsland(PlayerMoveEvent e) { + Player p = e.getPlayer(); + if (!isOn(p)) { + return; + } + Location from = e.getFrom(); + if (!addon.getSettings().isReturnTeleport() || !outsideCheck(e.getPlayer(), from, e.getTo())) { + return; + } + // Move the player back inside the border + if (addon.getIslands().getProtectedIslandAt(from).isPresent()) { + e.setCancelled(true); + inTeleport.add(p.getUniqueId()); + Util.teleportAsync(p, from).thenRun(() -> inTeleport.remove(p.getUniqueId())); + return; + } + // Backtrack + addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> { + Vector unitVector = i.getProtectionCenter().toVector().subtract(p.getLocation().toVector()).normalize() + .multiply(new Vector(1,0,1)); + if (unitVector.lengthSquared() <= 0D) { + // Direction is zero, so nothing to do; cannot move. + return; + } + RayTraceResult r = i.getProtectionBoundingBox().rayTrace(p.getLocation().toVector(), unitVector, i.getRange()); + if (r != null && checkFinite(r.getHitPosition())) { + inTeleport.add(p.getUniqueId()); + Location targetPos = r.getHitPosition().toLocation(p.getWorld(), p.getLocation().getYaw(), p.getLocation().getPitch()); + + if (!e.getPlayer().isFlying() && addon.getSettings().isReturnTeleportBlock() + && !addon.getIslands().isSafeLocation(targetPos)) { + switch (targetPos.getWorld().getEnvironment()) { + case NETHER: + targetPos.getBlock().getRelative(BlockFace.DOWN).setType(Material.NETHERRACK); + break; + case THE_END: + targetPos.getBlock().getRelative(BlockFace.DOWN).setType(Material.END_STONE); + break; + default: + targetPos.getBlock().getRelative(BlockFace.DOWN).setType(Material.STONE); + break; + } + } + Util.teleportAsync(p, targetPos).thenRun(() -> inTeleport.remove(p.getUniqueId())); + } + }); + } + + public boolean checkFinite(Vector toCheck) { + return NumberConversions.isFinite(toCheck.getX()) && NumberConversions.isFinite(toCheck.getY()) + && NumberConversions.isFinite(toCheck.getZ()); + } + + /** + * Check if the player is outside the island protection zone that they are supposed to be in. + * @param player - player moving + * @param from - from location + * @param to - to location + * @return true if outside the island protection zone + */ + private boolean outsideCheck(Player player, Location from, Location to) { + User user = Objects.requireNonNull(User.getInstance(player)); + + if ((from.getWorld() != null && from.getWorld().equals(to.getWorld()) + && from.toVector().multiply(XZ).equals(to.toVector().multiply(XZ))) + || !addon.inGameWorld(player.getWorld()) + || user.getPlayer().getGameMode() == GameMode.SPECTATOR + // || !addon.getIslands().getIslandAt(to).filter(i -> addon.getIslands().locationIsOnIsland(player, i.getProtectionCenter())).isPresent() + || !user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean).orElse(addon.getSettings().isShowByDefault())) { + return false; + } + return addon.getIslands().getIslandAt(to).filter(i -> !i.onIsland(to)).isPresent(); + } + + /** + * Runs a task while the player is mounting an entity and eject + * if the entity went outside the protection range + * @param event - event + */ + @EventHandler + public void onEntityMount(EntityMountEvent event) { + Entity entity = event.getEntity(); + if (!(entity instanceof Player player)) { + return; + } + + mountedPlayers.put(player, Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> { + Location loc = player.getLocation(); + + if (!addon.inGameWorld(loc.getWorld())) { + return; + } + // Eject from mount if outside the protection range + if (addon.getIslands().getProtectedIslandAt(loc).isEmpty()) { + // Force the dismount event for custom entities + if (!event.getMount().eject()) { + var dismountEvent = new EntityDismountEvent(player, event.getMount()); + Bukkit.getPluginManager().callEvent(dismountEvent); + } + } + }, 1, 20)); + } + + /** + * Cancel the running task if the player was mounting an entity + * @param event - event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityDismount(EntityDismountEvent event) { + Entity entity = event.getEntity(); + if (!(entity instanceof Player player)) { + return; + } + + BukkitTask task = mountedPlayers.get(player); + if (task == null) { + return; + } + + task.cancel(); + mountedPlayers.remove(player); + } + + + /** + * Refreshes the barrier view when the player moves (more than just moving their head) + * @param e event + */ + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerMove(PlayerMoveEvent e) { + // Remove head movement + if (!e.getFrom().toVector().equals(e.getTo().toVector())) { + addon.getIslands() + .getIslandAt(e.getPlayer().getLocation()) + .ifPresent(i -> show.refreshView(User.getInstance(e.getPlayer()), i)); + } + } + + /** + * Refresh the view when riding in a vehicle + * @param e event + */ + @EventHandler(priority = EventPriority.NORMAL) + public void onVehicleMove(VehicleMoveEvent e) { + // Remove head movement + if (!e.getFrom().toVector().equals(e.getTo().toVector())) { + e.getVehicle().getPassengers().stream() + .filter(Player.class::isInstance) + .map(Player.class::cast) + .forEach(p -> addon + .getIslands() + .getIslandAt(p.getLocation()) + .ifPresent(i -> show.refreshView(User.getInstance(p), i))); + } + } + + /** + * Hide and then show the border to react to the change in protection area + * @param e + */ + @EventHandler(priority = EventPriority.NORMAL) + public void onProtectionRangeChange(IslandProtectionRangeChangeEvent e) { + // Hide and show again + e.getIsland().getPlayersOnIsland().forEach(player -> { + show.hideBorder(User.getInstance(player)); + show.showBorder(player, e.getIsland()); + }); + } +} diff --git a/src/main/java/world/bentobox/border/listeners/PlayerListener.java b/src/main/java/world/bentobox/border/listeners/PlayerListener.java index 547027f..b62d066 100644 --- a/src/main/java/world/bentobox/border/listeners/PlayerListener.java +++ b/src/main/java/world/bentobox/border/listeners/PlayerListener.java @@ -39,7 +39,6 @@ import world.bentobox.bentobox.util.Util; import world.bentobox.border.Border; import world.bentobox.border.PerPlayerBorderProxy; -import world.bentobox.border.commands.BorderTypeCommand; import world.bentobox.border.commands.IslandBorderCommand; /** @@ -75,16 +74,16 @@ protected void processEvent(PlayerJoinEvent e) { // Get the game mode that this player is in addon.getPlugin().getIWM().getAddon(e.getPlayer().getWorld()).map(gma -> gma.getPermissionPrefix()).filter( permPrefix -> !e.getPlayer().hasPermission(permPrefix + IslandBorderCommand.BORDER_COMMAND_PERM)) - .ifPresent(permPrefix -> { - // Restore barrier on/off to default - user.putMetaData(BorderShower.BORDER_STATE_META_DATA, - new MetaDataValue(addon.getSettings().isShowByDefault())); - if (!e.getPlayer().hasPermission(permPrefix + BorderTypeCommand.BORDER_TYPE_COMMAND_PERM)) { + .ifPresent(permPrefix -> { + // Restore barrier on/off to default + user.putMetaData(BorderShower.BORDER_STATE_META_DATA, + new MetaDataValue(addon.getSettings().isShowByDefault())); + if (!e.getPlayer().hasPermission(permPrefix + "border.type") && !e.getPlayer().hasPermission(permPrefix + "border.bordertype")) { // Restore default barrier type to player MetaDataValue metaDataValue = new MetaDataValue(addon.getSettings().getType().getId()); user.putMetaData(PerPlayerBorderProxy.BORDER_BORDERTYPE_META_DATA, metaDataValue); } - }); + }); // Show the border if required one tick after Bukkit.getScheduler().runTask(addon.getPlugin(), () -> addon.getIslands().getIslandAt(e.getPlayer().getLocation()).ifPresent(i -> @@ -103,14 +102,25 @@ public void onPlayerRespawn(PlayerRespawnEvent e) { show.showBorder(e.getPlayer(), i))); } + private boolean isOn(Player player) { + // Check if border is off + User user = User.getInstance(player); + return user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean) + .orElse(addon.getSettings().isShowByDefault()); + + } + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onPlayerTeleport(PlayerTeleportEvent e) { Player player = e.getPlayer(); + if (!isOn(player)) { + return; + } Location to = e.getTo(); show.clearUser(User.getInstance(player)); - if (!addon.inGameWorld(to.getWorld())) { + if (to == null || !addon.inGameWorld(to.getWorld())) { return; } @@ -146,6 +156,9 @@ public void onPlayerTeleport(PlayerTeleportEvent e) { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerLeaveIsland(PlayerMoveEvent e) { Player p = e.getPlayer(); + if (!isOn(p)) { + return; + } Location from = e.getFrom(); if (!addon.getSettings().isReturnTeleport() || !outsideCheck(e.getPlayer(), from, e.getTo())) { return; @@ -215,7 +228,7 @@ private boolean outsideCheck(Player player, Location from, Location to) { return addon.getIslands().getIslandAt(to).filter(i -> !i.onIsland(to)).isPresent(); } - /** + /** * Runs a task while the player is mounting an entity and eject * if the entity went outside the protection range * @param event - event diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index ef18ae2..bedc91a 100644 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -14,4 +14,7 @@ permissions: default: op '[gamemode].border.type': description: Player can use border type setting command - default: true \ No newline at end of file + default: true + '[gamemode].bordertype': + description: Player can use bordertype command to change the border type + default: false \ No newline at end of file diff --git a/src/main/resources/locales/lv.yml b/src/main/resources/locales/lv.yml index 82caaa9..7718225 100644 --- a/src/main/resources/locales/lv.yml +++ b/src/main/resources/locales/lv.yml @@ -4,3 +4,7 @@ border: description: pārslēdz iespēju redzēt robežu border-on: "&a Robeža ieslēgta." border-off: "&a Robeža izslēgta." + set-type: + description: maina apmales veidu + changed: "&a Apmales veids mainīts uz &b[type]&a." + error-unavailable-type: "&c Šis veids nav pieejams vai neeksistē." diff --git a/src/main/resources/locales/zh-CN.yml b/src/main/resources/locales/zh-CN.yml index ecf0f69..f2601e4 100644 --- a/src/main/resources/locales/zh-CN.yml +++ b/src/main/resources/locales/zh-CN.yml @@ -1,10 +1,9 @@ ---- border: toggle: - description: 打开/关闭边框 - border-on: "&a 启用边框。" - border-off: "&a 边框已禁用。" + description: 启用/禁用边界屏障 + border-on: '&a边界屏障已启用.' + border-off: '&a边界屏障已禁用.' set-type: - description: 更改边框的类型 - changed: "&a 边框类型更改为 &b[type]&a。" - error-unavailable-type: "&c 此类型不可用或不存在。" + description: 更改边界屏障类型 + changed: '&a边界屏障已更改为: &b[type]&a.' + error-unavailable-type: '&c该屏障类型不可用或不存在.' diff --git a/src/test/java/world/bentobox/border/commands/BorderTypeCommandTest.java b/src/test/java/world/bentobox/border/commands/BorderTypeCommandTest.java index b2bbd3a..f50e1b2 100644 --- a/src/test/java/world/bentobox/border/commands/BorderTypeCommandTest.java +++ b/src/test/java/world/bentobox/border/commands/BorderTypeCommandTest.java @@ -23,7 +23,6 @@ import org.bukkit.World; import org.bukkit.entity.Player; import org.eclipse.jdt.annotation.Nullable; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -139,14 +138,7 @@ public void setUp() throws Exception { when(addon.getSettings()).thenReturn(settings); - ic = new BorderTypeCommand(addon, ac); - } - - /** - * @throws java.lang.Exception - */ - @After - public void tearDown() throws Exception { + ic = new BorderTypeCommand(addon, ac, "type"); } /**