Merge pull request #10 from headhunter45/1-add-a-command-to-move-to-a-different-home
Some checks failed
Java CI with Gradle / build (push) Has been cancelled
Some checks failed
Java CI with Gradle / build (push) Has been cancelled
Adds /metropolis-home-move command to switch to another home.
This commit is contained in:
@@ -52,6 +52,9 @@ Use this checklist for behavior that depends on a real Paper world, player inter
|
|||||||
- With plot multipliers of 1 and 2, acquire homes and inspect their WorldGuard bounds. Confirm size follows the tier, a larger footprint does not overlap an existing home, and the multiplier is applied to the X and Z footprint only once.
|
- With plot multipliers of 1 and 2, acquire homes and inspect their WorldGuard bounds. Confirm size follows the tier, a larger footprint does not overlap an existing home, and the multiplier is applied to the X and Z footprint only once.
|
||||||
- Exercise `/metropolis-home-acquire` below and at each effective home limit. Confirm every successful request creates a distinct next-numbered home, creates none beyond the limit, and does not change other players' homes.
|
- Exercise `/metropolis-home-acquire` below and at each effective home limit. Confirm every successful request creates a distinct next-numbered home, creates none beyond the limit, and does not change other players' homes.
|
||||||
- After acquiring a second home, verify it becomes active: check the player's selected home in `plugins/Metropolis/currentHomes.yml` and use `/metropolis-home-go` to confirm travel to that home. Switch homes with `/metropolis-home-move` and verify the selection changes as expected.
|
- After acquiring a second home, verify it becomes active: check the player's selected home in `plugins/Metropolis/currentHomes.yml` and use `/metropolis-home-go` to confirm travel to that home. Switch homes with `/metropolis-home-move` and verify the selection changes as expected.
|
||||||
|
- Run `/metropolis-home-move <homeNumber>` as a player with multiple homes. Verify the command confirms the selected home, updates `currentHomes.yml`, and `/metropolis-home-go` now travels to it.
|
||||||
|
- Run `/metropolis-home-move <homeNumber> <playerName>` as an authorized administrator, then repeat from console. Check an online target is notified and a cached offline target uses the selected home on their next join.
|
||||||
|
- Try zero, negative, non-numeric, nonexistent home numbers, unknown player names, and extra arguments. Confirm each request is rejected with useful feedback and does not change the stored active home.
|
||||||
- Restart after acquiring multiple homes. Confirm all home regions remain owned by the player, the active home selection persists, and joining does not allocate another first home.
|
- Restart after acquiring multiple homes. Confirm all home regions remain owned by the player, the active home selection persists, and joining does not allocate another first home.
|
||||||
- Generate a home for an offline player administratively. Confirm permission tiers are not assumed for offline players; the username override or global settings determine plot size and limit.
|
- Generate a home for an offline player administratively. Confirm permission tiers are not assumed for offline players; the username override or global settings determine plot size and limit.
|
||||||
- Exercise `/metropolis-home-go` with a safe bed spawn inside the home and with no such bed spawn. Confirm teleportation chooses a valid location inside the home and reports a clear failure if no safe location exists.
|
- Exercise `/metropolis-home-go` with a safe bed spawn inside the home and with no such bed spawn. Confirm teleportation chooses a valid location inside the home and reports a clear failure if no safe location exists.
|
||||||
@@ -62,7 +65,7 @@ Use this checklist for behavior that depends on a real Paper world, player inter
|
|||||||
|
|
||||||
## Existing Automated Coverage
|
## Existing Automated Coverage
|
||||||
|
|
||||||
Run `./gradlew test` for the server-free JUnit suite. It has 17 tests covering:
|
Run `./gradlew test` for the server-free JUnit suite. It has 20 tests covering:
|
||||||
|
|
||||||
- `CuboidTest`: WorldEdit bound conversion, vector ordering/null handling, touching intersections, and point containment.
|
- `CuboidTest`: WorldEdit bound conversion, vector ordering/null handling, touching intersections, and point containment.
|
||||||
- `CurrentHomesStoreTest`: UUID-based persistence and resolving a legacy player-name key.
|
- `CurrentHomesStoreTest`: UUID-based persistence and resolving a legacy player-name key.
|
||||||
@@ -71,6 +74,7 @@ Run `./gradlew test` for the server-free JUnit suite. It has 17 tests covering:
|
|||||||
- `PlayerHomeTest`: UUID-based region identity and display-name retention.
|
- `PlayerHomeTest`: UUID-based region identity and display-name retention.
|
||||||
- `HomePermissionOverrideTest`: dotted permission-node parsing, priority and tie resolution, invalid entries, and username/permission/default precedence.
|
- `HomePermissionOverrideTest`: dotted permission-node parsing, priority and tie resolution, invalid entries, and username/permission/default precedence.
|
||||||
- `HomeNumberAllocatorTest`: choosing the first unused positive home number.
|
- `HomeNumberAllocatorTest`: choosing the first unused positive home number.
|
||||||
|
- `MetropolisHomeMoveCommandTest`: selecting a sender's home, selecting an offline target's home, and rejecting invalid requests.
|
||||||
- `MetropolisPlotReserveCommandTest`: parsing six coordinates and rejecting malformed coordinates.
|
- `MetropolisPlotReserveCommandTest`: parsing six coordinates and rejecting malformed coordinates.
|
||||||
- `MetropolisHomeAcquireTest`: acquisition below the limit and refusal at the limit.
|
- `MetropolisHomeAcquireTest`: acquisition below the limit and refusal at the limit.
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ Metropolis targets Paper only; Bukkit and Spigot servers are not supported.
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Automatically assigns a protected home plot when a player joins.
|
- Automatically assigns a protected home plot when a player joins.
|
||||||
- Allows players to acquire additional homes up to their configured limit, with per-player overrides.
|
- Allows players to acquire additional homes up to their effective limit, configured globally, per user, or through permission-manager groups.
|
||||||
|
- Supports permission-based plot-size and home-limit tiers with configurable priorities; explicit per-user overrides take precedence.
|
||||||
|
- Lets players and authorized administrators select an existing home as active; selections persist by player UUID across restarts.
|
||||||
- Expands the protected city region as plots are occupied.
|
- Expands the protected city region as plots are occupied.
|
||||||
- Configures plot dimensions, roads, floors, supports, signs, spawn behavior, and perimeter walls.
|
- Configures plot dimensions, roads, floors, supports, signs, spawn behavior, and perimeter walls.
|
||||||
- Reserves named plots by coordinates or a WorldEdit selection.
|
- Reserves named plots by coordinates or a WorldEdit selection.
|
||||||
@@ -33,7 +35,7 @@ Metropolis creates `plugins/Metropolis/config.yml` on first startup. Configure p
|
|||||||
- `/metropolis-home-generate <playerName>` - Generates a home for a known online or cached offline player.
|
- `/metropolis-home-generate <playerName>` - Generates a home for a known online or cached offline player.
|
||||||
- `/metropolis-home-list` - Lists occupied and reserved plots.
|
- `/metropolis-home-list` - Lists occupied and reserved plots.
|
||||||
- `/metropolis-home-go [playerName]` - Teleports to a home.
|
- `/metropolis-home-go [playerName]` - Teleports to a home.
|
||||||
- `/metropolis-home-move <homeNumber> [playerName]` - Selects a player's home.
|
- `/metropolis-home-move <homeNumber> [playerName]` - Selects an existing home as active. The player name defaults to the sender; authorized administrators and console can target online or cached offline players.
|
||||||
- `/metropolis-home-evict <playerName>` - Removes a player's ownership from their selected home region.
|
- `/metropolis-home-evict <playerName>` - Removes a player's ownership from their selected home region.
|
||||||
- `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` - Reserves a region by coordinates; players can use `/metropolis-plot-reserve <name>` with a WorldEdit selection.
|
- `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` - Reserves a region by coordinates; players can use `/metropolis-plot-reserve <name>` with a WorldEdit selection.
|
||||||
- `/metropolis-plot-go <plotName> [playerName]` - Teleports to a named plot.
|
- `/metropolis-plot-go <plotName> [playerName]` - Teleports to a named plot.
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
Metropolis turns player onboarding into city planning. As players arrive, the Paper plugin finds the next available plot, builds the surrounding roads and infrastructure, and extends a WorldGuard-protected city that feels designed rather than randomly generated.
|
Metropolis turns player onboarding into city planning. As players arrive, the Paper plugin finds the next available plot, builds the surrounding roads and infrastructure, and extends a WorldGuard-protected city that feels designed rather than randomly generated.
|
||||||
|
|
||||||
The project combines procedural spatial logic, persistent UUID-based ownership, configurable construction rules, WorldEdit-assisted reservations, and a command suite for moving, acquiring, listing, and administering homes. It is also a modernization case study: a legacy plugin brought forward to Paper 26.2 and 26.3 with Gradle, focused unit tests, and opt-in live-server integration tests. Bukkit and Spigot servers are outside the support target.
|
The project combines procedural spatial logic, persistent UUID-based ownership, configurable construction rules, WorldEdit-assisted reservations, and a command suite for acquiring and selecting multiple homes. Home limits and plot sizes can be assigned per user or through permission-manager groups using configurable permission tiers. Active-home selections persist across reconnects and server restarts. It is also a modernization case study: a legacy plugin brought forward to Paper 26.2 and 26.3 with Gradle, focused unit tests, and opt-in live-server integration tests. Bukkit and Spigot servers are outside the support target.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Metropolis expands a protected Minecraft city as players join. Each player can r
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Assigns a protected home plot when a player joins and supports acquiring additional homes up to the configured player limit.
|
- Assigns a protected home plot when a player joins and supports acquiring additional homes up to the configured player limit.
|
||||||
|
- Supports per-player plot sizes and home limits through `userOverrides` or configurable permission tiers; acquired homes can be selected as the active home.
|
||||||
- Expands the City region as plots are occupied, with optional spawn generation, world-spawn placement, floors, support blocks, signs, and perimeter walls.
|
- Expands the City region as plots are occupied, with optional spawn generation, world-spawn placement, floors, support blocks, signs, and perimeter walls.
|
||||||
- Generates roads around plots with configurable width, level, material, clearance, and supports.
|
- Generates roads around plots with configurable width, level, material, clearance, and supports.
|
||||||
- Creates named protected reservations from coordinates or a WorldEdit selection so reserved plots are not assigned as homes.
|
- Creates named protected reservations from coordinates or a WorldEdit selection so reserved plots are not assigned as homes.
|
||||||
@@ -57,7 +58,7 @@ Copy `.env.example` to `.env` and configure the Paper version/build and server p
|
|||||||
|
|
||||||
`plugins/Metropolis/config.yml` controls plot dimensions and limits, floor and support generation, signs, road width/level/material/clearance, spawn behavior, wall generation, world name, and per-player overrides. `plot.multiplier` sets the default plot-size multiplier; `plot.maxPerPlayer` sets the default home limit.
|
`plugins/Metropolis/config.yml` controls plot dimensions and limits, floor and support generation, signs, road width/level/material/clearance, spawn behavior, wall generation, world name, and per-player overrides. `plot.multiplier` sets the default plot-size multiplier; `plot.maxPerPlayer` sets the default home limit.
|
||||||
|
|
||||||
Use `permissionOverrides` to assign plot size and home limits through any permission manager. Each permission node maps to a `priority`, `plotMultiplier`, and `maxPlots`; the matching node with the highest priority wins, and the last matching entry in YAML order wins ties. An explicit username entry in `userOverrides` takes precedence over permission rules. If no override matches, the global `plot.*` defaults apply. For example:
|
Use `permissionOverrides` to assign plot size and home limits through any permission manager. Each permission node maps to a `priority`, `plotMultiplier`, and `maxPlots`; the matching node with the highest priority wins, and the last matching entry in YAML order wins ties. An explicit username entry in `userOverrides` takes precedence over permission rules. If no override matches, the global `plot.*` defaults apply. Permission rules are checked for online players; offline home generation uses username overrides or global defaults. For example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
permissionOverrides:
|
permissionOverrides:
|
||||||
@@ -82,7 +83,7 @@ Assign these permission nodes to groups or individual users in your permission p
|
|||||||
| `/metropolis-home-generate <playerName>` | `metropolis.home.generate` | Generates a home for an online or cached offline player. |
|
| `/metropolis-home-generate <playerName>` | `metropolis.home.generate` | Generates a home for an online or cached offline player. |
|
||||||
| `/metropolis-home-list` | `metropolis.home.list` | Lists the occupied and reserved Metropolis plots with their bounds. |
|
| `/metropolis-home-list` | `metropolis.home.list` | Lists the occupied and reserved Metropolis plots with their bounds. |
|
||||||
| `/metropolis-home-go [playerName]` | `metropolis.home.go` | Teleports the sender, or a permitted target player, to their home. |
|
| `/metropolis-home-go [playerName]` | `metropolis.home.go` | Teleports the sender, or a permitted target player, to their home. |
|
||||||
| `/metropolis-home-move <homeNumber> [playerName]` | `metropolis.home.move` | Selects one of a player's existing home regions. The player argument defaults to the sender. |
|
| `/metropolis-home-move <homeNumber> [playerName]` | `metropolis.home.move` | Selects one of a player's existing homes as active. The player argument defaults to the sender; console and authorized admins can target online or cached offline players. The selection persists across restarts. |
|
||||||
| `/metropolis-home-evict <playerName>` | `metropolis.home.evict` | Removes the player's ownership from their selected home region. |
|
| `/metropolis-home-evict <playerName>` | `metropolis.home.evict` | Removes the player's ownership from their selected home region. |
|
||||||
| `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` | `metropolis.plot.reserve` | Creates a named reservation from explicit bounds. A player can instead run `/metropolis-plot-reserve <name>` with a WorldEdit selection. |
|
| `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` | `metropolis.plot.reserve` | Creates a named reservation from explicit bounds. A player can instead run `/metropolis-plot-reserve <name>` with a WorldEdit selection. |
|
||||||
| `/metropolis-plot-go <plotName> [playerName]` | `metropolis.plot.go` | Teleports the sender or target player to a named occupied or reserved plot. |
|
| `/metropolis-plot-go <plotName> [playerName]` | `metropolis.plot.go` | Teleports the sender or target player to a named occupied or reserved plot. |
|
||||||
|
|||||||
10
TODO.md
10
TODO.md
@@ -36,16 +36,14 @@
|
|||||||
| GIT-004 | Planning | Add a command to request home allocation. |
|
| GIT-004 | Planning | Add a command to request home allocation. |
|
||||||
| GIT-003 | Ready | Add support for multiple homes. |
|
| GIT-003 | Ready | Add support for multiple homes. |
|
||||||
| GIT-002 | Planning | Add a command to teleport to a reservation you are part of. |
|
| GIT-002 | Planning | Add a command to teleport to a reservation you are part of. |
|
||||||
| GIT-001 | Planning | Add a command to move to a different home. |
|
| GIT-001 | Done | Add a command to move to a different home. |
|
||||||
|
|
||||||
# GIT-001 - Add a command to move to a different home.
|
# GIT-001 - Add a command to move to a different home.
|
||||||
**Status:** Ready
|
**Status:** Done
|
||||||
**Depends On:** [GIT-003](#git-003---add-support-for-multiple-homes)
|
**Depends On:** [GIT-003](#git-003---add-support-for-multiple-homes)
|
||||||
**Descriptioon:**
|
**Description:**
|
||||||
|
|
||||||
/metropolis-home-move [playerName]
|
`/metropolis-home-move <homeNumber> [playerName]` selects one of a player's existing homes as active. Without a player name, the command acts on the player who ran it; console and authorized administrators can specify an online or cached offline player. Reject non-positive or malformed numbers, unknown players, nonexistent homes, and extra arguments with clear feedback. Persist the selection by player UUID and confirm the change to the sender and, when online, the target player.
|
||||||
The target player will be the callee or if specified [playerName].
|
|
||||||
This command should set the target player's home to the plot defined by .
|
|
||||||
|
|
||||||
# GIT-002 - Add a command to teleport to a reservation you are part of.
|
# GIT-002 - Add a command to teleport to a reservation you are part of.
|
||||||
**Status:** Ready
|
**Status:** Ready
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.bukkit.OfflinePlayer;
|
|||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class MetropolisHomeMoveCommand implements CommandExecutor {
|
public class MetropolisHomeMoveCommand implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin;
|
MetropolisPlugin _plugin;
|
||||||
@@ -33,37 +34,53 @@ public class MetropolisHomeMoveCommand implements CommandExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||||
OfflinePlayer player = null;
|
if (args.length < 1 || args.length > 2) {
|
||||||
int newHomeNumber = 0;
|
sender.sendMessage("Usage: /metropolis-home-move <homeNumber> [playerName]");
|
||||||
|
return false;
|
||||||
if (sender instanceof OfflinePlayer) {
|
|
||||||
player = (OfflinePlayer) sender;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int homeNumber;
|
||||||
|
try {
|
||||||
|
homeNumber = Integer.parseInt(args[0]);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
sender.sendMessage("Home number must be a positive integer.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (homeNumber < 1) {
|
||||||
|
sender.sendMessage("Home number must be a positive integer.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OfflinePlayer target;
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
try {
|
if (!(sender instanceof Player player)) {
|
||||||
newHomeNumber = Integer.parseInt(args[0]);
|
sender.sendMessage("Console must specify a player name.");
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (args.length >= 2) {
|
target = player;
|
||||||
try {
|
|
||||||
newHomeNumber = Integer.parseInt(args[0]);
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
player = _plugin.getOfflinePlayer(args[1]);
|
|
||||||
} else {
|
} else {
|
||||||
|
target = _plugin.getOfflinePlayer(args[1]);
|
||||||
|
if (target == null) {
|
||||||
|
sender.sendMessage("No known player named " + args[1] + ".");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_plugin.homeExists(target.getUniqueId(), homeNumber)) {
|
||||||
|
String targetName =
|
||||||
|
target.getName() == null ? target.getUniqueId().toString() : target.getName();
|
||||||
|
sender.sendMessage(targetName + " does not have home " + homeNumber + ".");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player == null || !_plugin.homeExists(player.getUniqueId(), newHomeNumber)) {
|
_plugin.setHome(target.getUniqueId(), homeNumber);
|
||||||
return false;
|
String targetName =
|
||||||
|
target.getName() == null ? target.getUniqueId().toString() : target.getName();
|
||||||
|
sender.sendMessage("Home " + homeNumber + " is now active for " + targetName + ".");
|
||||||
|
if (target instanceof Player targetPlayer && targetPlayer != sender) {
|
||||||
|
targetPlayer.sendMessage("Your active Metropolis home is now home " + homeNumber + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
_plugin.setHome(player.getUniqueId(), newHomeNumber);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ commands:
|
|||||||
permission: metropolis.home.evict
|
permission: metropolis.home.evict
|
||||||
usage: /metropolis-home-evict <playerName>
|
usage: /metropolis-home-evict <playerName>
|
||||||
metropolis-home-move:
|
metropolis-home-move:
|
||||||
description: This command swaps a player's current home with a reserved plot.
|
|
||||||
permission: metropolis.home.move
|
permission: metropolis.home.move
|
||||||
usage: /metropolis-home-move <newHomeNumber> [player]
|
usage: /metropolis-home-move <newHomeNumber> [player]
|
||||||
metropolis-home-go:
|
metropolis-home-go:
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.contains;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class MetropolisHomeMoveCommandTest {
|
||||||
|
private static final UUID PLAYER_ID = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void selectsTheSendersExistingHome() {
|
||||||
|
MetropolisPlugin plugin = mock(MetropolisPlugin.class);
|
||||||
|
Player sender = mock(Player.class);
|
||||||
|
when(sender.getUniqueId()).thenReturn(PLAYER_ID);
|
||||||
|
when(sender.getName()).thenReturn("PlayerName");
|
||||||
|
when(plugin.homeExists(PLAYER_ID, 2)).thenReturn(true);
|
||||||
|
MetropolisHomeMoveCommand command = new MetropolisHomeMoveCommand(plugin);
|
||||||
|
|
||||||
|
assertTrue(command.onCommand(sender, mock(Command.class), "move", new String[] {"2"}));
|
||||||
|
|
||||||
|
verify(plugin).setHome(PLAYER_ID, 2);
|
||||||
|
verify(sender).sendMessage(contains("Home 2 is now active for PlayerName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void selectsAnOfflineTargetsExistingHome() {
|
||||||
|
MetropolisPlugin plugin = mock(MetropolisPlugin.class);
|
||||||
|
CommandSender sender = mock(CommandSender.class);
|
||||||
|
OfflinePlayer target = mock(OfflinePlayer.class);
|
||||||
|
when(plugin.getOfflinePlayer("OfflineName")).thenReturn(target);
|
||||||
|
when(target.getUniqueId()).thenReturn(PLAYER_ID);
|
||||||
|
when(target.getName()).thenReturn("OfflineName");
|
||||||
|
when(plugin.homeExists(PLAYER_ID, 3)).thenReturn(true);
|
||||||
|
MetropolisHomeMoveCommand command = new MetropolisHomeMoveCommand(plugin);
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"3", "OfflineName"}));
|
||||||
|
|
||||||
|
verify(plugin).setHome(PLAYER_ID, 3);
|
||||||
|
verify(sender).sendMessage(contains("Home 3 is now active for OfflineName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsInvalidNumbersMissingPlayersAndNonexistentHomes() {
|
||||||
|
MetropolisPlugin plugin = mock(MetropolisPlugin.class);
|
||||||
|
Player sender = mock(Player.class);
|
||||||
|
when(sender.getUniqueId()).thenReturn(PLAYER_ID);
|
||||||
|
MetropolisHomeMoveCommand command = new MetropolisHomeMoveCommand(plugin);
|
||||||
|
|
||||||
|
assertFalse(command.onCommand(sender, mock(Command.class), "move", new String[] {"0"}));
|
||||||
|
assertFalse(command.onCommand(sender, mock(Command.class), "move", new String[] {"nope"}));
|
||||||
|
assertFalse(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"1", "unknown"}));
|
||||||
|
when(plugin.getOfflinePlayer("unknown")).thenReturn(null);
|
||||||
|
assertFalse(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"1", "unknown"}));
|
||||||
|
assertFalse(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"1", "2", "extra"}));
|
||||||
|
assertFalse(command.onCommand(sender, mock(Command.class), "move", new String[] {"1"}));
|
||||||
|
|
||||||
|
verify(plugin, never()).setHome(PLAYER_ID, 0);
|
||||||
|
verify(sender, times(2)).sendMessage(contains("positive integer"));
|
||||||
|
verify(sender).sendMessage(contains("does not have home 1"));
|
||||||
|
verify(sender).sendMessage(contains("Usage:"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user