From 1b5100f184b42c094603f88625abfb66e0f11835 Mon Sep 17 00:00:00 2001 From: Florent Clarret Date: Tue, 11 Jul 2017 11:50:24 +0200 Subject: [PATCH 1/4] Simplify the unit tests for the some commands Commands : setidletimeout, setworldspawnpoint, spawnpoint and toggleDownfall --- .../minecraft/SetIdleTimeoutCommandTest.java | 25 ++--- .../minecraft/SetWorldSpawnCommandTest.java | 72 ++++-------- .../minecraft/SpawnPointCommandTest.java | 106 +++++------------- .../minecraft/ToggleDownfallCommandTest.java | 27 ++--- 4 files changed, 64 insertions(+), 166 deletions(-) diff --git a/src/test/java/net/glowstone/command/minecraft/SetIdleTimeoutCommandTest.java b/src/test/java/net/glowstone/command/minecraft/SetIdleTimeoutCommandTest.java index 799dac5b10..cc75fd86e4 100644 --- a/src/test/java/net/glowstone/command/minecraft/SetIdleTimeoutCommandTest.java +++ b/src/test/java/net/glowstone/command/minecraft/SetIdleTimeoutCommandTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; @RunWith(PowerMockRunner.class) @PrepareForTest(Bukkit.class) @@ -41,63 +42,51 @@ public void before() { @Test public void testExecuteFailsWithoutPermission() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); final boolean commandResult = command.execute(sender, "label", new String[0]); assertThat(commandResult, is(false)); - Mockito.verify(sender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); + Mockito.verify(sender).sendMessage(eq(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); } @Test public void testExecuteFailsWithoutParameters() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); final boolean commandResult = command.execute(opSender, "label", new String[0]); assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Usage: /setidletimeout ")); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Usage: /setidletimeout ")); } @Test public void testExecuteFailsWithIncorrectNumber() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); final boolean commandResult = command.execute(opSender, "label", new String[]{"invalidNumber"}); assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "'invalidNumber' is not a valid number")); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'invalidNumber' is not a valid number")); } @Test public void testExecuteFailsWithNegativeTimeout() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); final boolean commandResult = command.execute(opSender, "label", new String[]{"-42"}); assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "The number you have entered (-42) is too small, it must be at least 1")); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "The number you have entered (-42) is too small, it must be at least 1")); } @Test public void testExecuteFailsWithNullTimeout() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); final boolean commandResult = command.execute(opSender, "label", new String[]{"0"}); assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "The number you have entered (0) is too small, it must be at least 1")); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "The number you have entered (0) is too small, it must be at least 1")); } @Test public void testExecuteSucceeds() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); final boolean commandResult = command.execute(opSender, "label", new String[]{"50"}); assertThat(commandResult, is(true)); - Mockito.verify(opSender).sendMessage(captor.capture()); + Mockito.verify(opSender).sendMessage(eq("Successfully set the idle timeout to 50 minutes.")); Mockito.verify(Bukkit.getServer()).setIdleTimeout(50); - assertThat(captor.getValue(), is("Successfully set the idle timeout to 50 minutes.")); } @Test diff --git a/src/test/java/net/glowstone/command/minecraft/SetWorldSpawnCommandTest.java b/src/test/java/net/glowstone/command/minecraft/SetWorldSpawnCommandTest.java index 002b3a206b..ba160e1230 100644 --- a/src/test/java/net/glowstone/command/minecraft/SetWorldSpawnCommandTest.java +++ b/src/test/java/net/glowstone/command/minecraft/SetWorldSpawnCommandTest.java @@ -22,6 +22,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; @RunWith(PowerMockRunner.class) @PrepareForTest({CommandUtils.class, GlowServer.class, GlowWorld.class}) @@ -54,104 +55,69 @@ public void before() { @Test public void testExecuteFailsWithoutPermission() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(sender, "label", new String[0]); - - assertThat(commandResult, is(false)); - Mockito.verify(sender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); + assertThat(command.execute(sender, "label", new String[0]), is(false)); + Mockito.verify(sender).sendMessage(eq(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); } @Test public void testExecuteFailsWithoutWorld() { PowerMockito.stub(PowerMockito.method(CommandUtils.class, "getWorld", CommandSender.class)).toReturn(null); - final boolean commandResult = command.execute(sender, "label", new String[0]); - assertThat(commandResult, is(false)); + assertThat(command.execute(sender, "label", new String[0]), is(false)); } @Test public void testExecuteFailsWithOneParameter() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[1]); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Usage: /setworldspawn OR /setworldspawn ")); + assertThat(command.execute(opSender, "label", new String[1]), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Usage: /setworldspawn OR /setworldspawn ")); } @Test public void testExecuteFailsWithTwoParameters() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[2]); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Usage: /setworldspawn OR /setworldspawn ")); + assertThat(command.execute(opSender, "label", new String[2]), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Usage: /setworldspawn OR /setworldspawn ")); } @Test public void testExecuteFailsWithDefaultLocation() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[0]); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Default coordinates can not be used without a physical user.")); + assertThat(command.execute(opSender, "label", new String[0]), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Default coordinates can not be used without a physical user."));; } @Test public void testExecuteFailsWithRelativeLocation() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"~2", "3", "4"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Relative coordinates can not be used without a physical user.")); + assertThat(command.execute(opSender, "label", new String[]{"~2", "3", "4"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Relative coordinates can not be used without a physical user.")); } @Test public void testExecuteFailsWithYCoordinatesTooHigh() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"2", "10000", "4"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "'10000' is too high for the current world. Max value is '50'.")); + assertThat(command.execute(opSender, "label", new String[]{"2", "10000", "4"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'10000' is too high for the current world. Max value is '50'.")); } @Test public void testExecuteFailsWithYCoordinatesTooSmall() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"2", "-10000", "4"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); + assertThat(command.execute(opSender, "label", new String[]{"2", "-10000", "4"}), is(false)); // -10001 because of the floor, it's not supposed to be negative - assertThat(captor.getValue(), is(ChatColor.RED + "The y coordinate (-10001) is too small, it must be at least 0.")); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "The y coordinate (-10001) is too small, it must be at least 0.")); } @Test public void testExecuteSucceedsWithCurrentLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[0]); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[0]), is(true)); Mockito.verify(world).setSpawnLocation(10, 20, 30); } @Test public void testExecuteSucceedsWithSpecificLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"30", "20", "10"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"30", "20", "10"}), is(true)); Mockito.verify(world).setSpawnLocation(30, 20, 10); } @Test public void testExecuteSucceedsWithRelativeLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"30", "~20", "10"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"30", "~20", "10"}), is(true)); Mockito.verify(world).setSpawnLocation(30, 41, 10); } diff --git a/src/test/java/net/glowstone/command/minecraft/SpawnPointCommandTest.java b/src/test/java/net/glowstone/command/minecraft/SpawnPointCommandTest.java index 2bf0f898fc..e0aadc2f8a 100644 --- a/src/test/java/net/glowstone/command/minecraft/SpawnPointCommandTest.java +++ b/src/test/java/net/glowstone/command/minecraft/SpawnPointCommandTest.java @@ -25,6 +25,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; @RunWith(PowerMockRunner.class) @PrepareForTest({Bukkit.class, CommandUtils.class, GlowServer.class, GlowWorld.class}) @@ -54,12 +55,13 @@ public void before() { world = PowerMockito.mock(GlowWorld.class); command = new SpawnPointCommand(); + final Location location = new Location(world, 10.5, 20.5, 30.5); Mockito.when(fakePlayer1.getName()).thenReturn("player1"); Mockito.when(fakePlayer2.getName()).thenReturn("player2"); Mockito.when(fakePlayer3.getName()).thenReturn("thePlayer3"); - Mockito.when(fakePlayer1.getLocation()).thenReturn(new Location(world, 10.5, 20.5, 30.5)); - Mockito.when(fakePlayer2.getLocation()).thenReturn(new Location(world, 10.5, 20.5, 30.5)); - Mockito.when(fakePlayer3.getLocation()).thenReturn(new Location(world, 10.5, 20.5, 30.5)); + Mockito.when(fakePlayer1.getLocation()).thenReturn(location); + Mockito.when(fakePlayer2.getLocation()).thenReturn(location); + Mockito.when(fakePlayer3.getLocation()).thenReturn(location); Mockito.when(fakePlayer1.getType()).thenReturn(EntityType.PLAYER); Mockito.when(fakePlayer2.getType()).thenReturn(EntityType.PLAYER); Mockito.when(fakePlayer3.getType()).thenReturn(EntityType.PLAYER); @@ -69,7 +71,7 @@ public void before() { Mockito.when(opPlayer.hasPermission(Mockito.anyString())).thenReturn(true); Mockito.when(opPlayer.getName()).thenReturn("ChuckNorris"); - Mockito.when(((Entity)opPlayer).getLocation()).thenReturn(new Location(world, 10.5, 20.5, 30.5)); + Mockito.when(((Entity)opPlayer).getLocation()).thenReturn(location); Mockito.doReturn(ImmutableList.of(fakePlayer1, fakePlayer2, fakePlayer3)) .when(server).getOnlinePlayers(); @@ -87,123 +89,79 @@ public void before() { @Test public void testExecuteFailsWithoutPermission() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(sender, "label", new String[0]); - - assertThat(commandResult, is(false)); - Mockito.verify(sender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); + assertThat(command.execute(sender, "label", new String[0]), is(false)); + Mockito.verify(sender).sendMessage(eq(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); } @Test public void testExecuteFailsWithTwoParameters() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[2]); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Usage: /spawnpoint OR /spawnpoint OR /spawnpoint ")); + assertThat(command.execute(opSender, "label", new String[2]), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Usage: /spawnpoint OR /spawnpoint OR /spawnpoint ")); } @Test public void testExecuteFailsWithThreeParameters() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[3]); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Usage: /spawnpoint OR /spawnpoint OR /spawnpoint ")); + assertThat(command.execute(opSender, "label", new String[3]), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Usage: /spawnpoint OR /spawnpoint OR /spawnpoint ")); } @Test public void testExecuteFailsWithSenderNotPlayer() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[0]); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "You must specify which player you wish to perform this action on.")); + assertThat(command.execute(opSender, "label", new String[0]), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "You must specify which player you wish to perform this action on.")); } @Test public void testExecuteFailsUnknownTarget() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"player"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Player 'player' cannot be found")); + assertThat(command.execute(opSender, "label", new String[]{"player"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Player 'player' cannot be found")); } @Test public void testExecuteFailsWithDefaultLocation() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"player1"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Default coordinates can not be used without a physical user.")); + assertThat(command.execute(opSender, "label", new String[]{"player1"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Default coordinates can not be used without a physical user.")); } @Test public void testExecuteFailsWithRelativeLocation() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"player1", "~2", "3", "4"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "Relative coordinates can not be used without a physical user.")); + assertThat(command.execute(opSender, "label", new String[]{"player1", "~2", "3", "4"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Relative coordinates can not be used without a physical user.")); } @Test public void testExecuteFailsWithYCoordinatesTooHigh() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"player1", "2", "10000", "4"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "'10000.5' is too high for the current world. Max value is '50'.")); + assertThat(command.execute(opSender, "label", new String[]{"player1", "2", "10000", "4"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'10000.5' is too high for the current world. Max value is '50'.")); } @Test public void testExecuteFailsWithYCoordinatesTooSmall() { - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - final boolean commandResult = command.execute(opSender, "label", new String[]{"player1", "2", "-10000", "4"}); - - assertThat(commandResult, is(false)); - Mockito.verify(opSender).sendMessage(captor.capture()); - assertThat(captor.getValue(), is(ChatColor.RED + "The y coordinate (-10000.5) is too small, it must be at least 0.")); + assertThat(command.execute(opSender, "label", new String[]{"player1", "2", "-10000", "4"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "The y coordinate (-10000.5) is too small, it must be at least 0.")); } @Test public void testExecuteSucceedsWithCurrentLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[0]); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[0]), is(true)); Mockito.verify((Player) opPlayer).setBedSpawnLocation(new Location(world, 10.5, 20.5, 30.5), true); } @Test public void testExecuteSucceedsOnAnotherPlayerWithCurrentLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"player1"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"player1"}), is(true)); Mockito.verify(Bukkit.getPlayerExact("player1")).setBedSpawnLocation(new Location(world, 10.5, 20.5, 30.5), true); } @Test public void testExecuteSucceedsOnAnotherPlayerWithSpecificLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"player1", "30", "20", "10"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"player1", "30", "20", "10"}), is(true)); Mockito.verify(Bukkit.getPlayerExact("player1")).setBedSpawnLocation(new Location(world, 30.5, 20.5, 10.5), true); } @Test public void testExecuteSucceedsAllPlayersWithCurrentLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"@a"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"@a"}), is(true)); Mockito.verify(Bukkit.getPlayerExact("player1")).setBedSpawnLocation(new Location(world, 10.5, 20.5, 30.5), true); Mockito.verify(Bukkit.getPlayerExact("player2")).setBedSpawnLocation(new Location(world, 10.5, 20.5, 30.5), true); Mockito.verify(Bukkit.getPlayerExact("thePlayer3")).setBedSpawnLocation(new Location(world, 10.5, 20.5, 30.5), true); @@ -211,9 +169,7 @@ public void testExecuteSucceedsAllPlayersWithCurrentLocation() { @Test public void testExecuteSucceedsAllPlayersWithSpecificLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"@a", "30", "20", "10"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"@a", "30", "20", "10"}), is(true)); Mockito.verify(Bukkit.getPlayerExact("player1")).setBedSpawnLocation(new Location(world, 30.5, 20.5, 10.5), true); Mockito.verify(Bukkit.getPlayerExact("player2")).setBedSpawnLocation(new Location(world, 30.5, 20.5, 10.5), true); Mockito.verify(Bukkit.getPlayerExact("thePlayer3")).setBedSpawnLocation(new Location(world, 30.5, 20.5, 10.5), true); @@ -221,9 +177,7 @@ public void testExecuteSucceedsAllPlayersWithSpecificLocation() { @Test public void testExecuteSucceedsAllPlayersWithRelativeLocation() { - final boolean commandResult = command.execute(opPlayer, "label", new String[]{"@a", "30", "~20", "10"}); - - assertThat(commandResult, is(true)); + assertThat(command.execute(opPlayer, "label", new String[]{"@a", "30", "~20", "10"}), is(true)); Mockito.verify(Bukkit.getPlayerExact("player1")).setBedSpawnLocation(new Location(world, 30.5, 41, 10.5), true); Mockito.verify(Bukkit.getPlayerExact("player2")).setBedSpawnLocation(new Location(world, 30.5, 41, 10.5), true); Mockito.verify(Bukkit.getPlayerExact("thePlayer3")).setBedSpawnLocation(new Location(world, 30.5, 41, 10.5), true); diff --git a/src/test/java/net/glowstone/command/minecraft/ToggleDownfallCommandTest.java b/src/test/java/net/glowstone/command/minecraft/ToggleDownfallCommandTest.java index dea92d5d46..0f7aed7867 100644 --- a/src/test/java/net/glowstone/command/minecraft/ToggleDownfallCommandTest.java +++ b/src/test/java/net/glowstone/command/minecraft/ToggleDownfallCommandTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; @RunWith(PowerMockRunner.class) @PrepareForTest({CommandUtils.class, GlowWorld.class}) @@ -42,37 +43,25 @@ public void before() { @Test public void testExecuteFailsWithoutPermission() { - final boolean commandResult = command.execute(sender, "label", new String[0]); - - assertThat(commandResult, is(false)); + assertThat(command.execute(sender, "label", new String[0]), is(false)); } @Test public void testExecuteSetRain() { PowerMockito.when(world.hasStorm()).thenReturn(true); - final ArgumentCaptor stormCaptor = ArgumentCaptor.forClass(Boolean.class); - final ArgumentCaptor thunderingCaptor = ArgumentCaptor.forClass(Boolean.class); - final boolean commandResult = command.execute(opSender, "label", new String[0]); - assertThat(commandResult, is(true)); - Mockito.verify(world).setStorm(stormCaptor.capture()); - Mockito.verify(world).setThundering(thunderingCaptor.capture()); - assertThat(stormCaptor.getValue(), is(false)); - assertThat(thunderingCaptor.getValue(), is(false)); + assertThat(command.execute(opSender, "label", new String[0]), is(true)); + Mockito.verify(world).setStorm(eq(false)); + Mockito.verify(world).setThundering(eq(false)); } @Test public void testExecuteClearWeather() { PowerMockito.when(world.hasStorm()).thenReturn(false); - final ArgumentCaptor stormCaptor = ArgumentCaptor.forClass(Boolean.class); - final ArgumentCaptor thunderingCaptor = ArgumentCaptor.forClass(Boolean.class); - final boolean commandResult = command.execute(opSender, "label", new String[0]); - assertThat(commandResult, is(true)); - Mockito.verify(world).setStorm(stormCaptor.capture()); - Mockito.verify(world).setThundering(thunderingCaptor.capture()); - assertThat(stormCaptor.getValue(), is(true)); - assertThat(thunderingCaptor.getValue(), is(true)); + assertThat(command.execute(opSender, "label", new String[0]), is(true)); + Mockito.verify(world).setStorm(eq(true)); + Mockito.verify(world).setThundering(eq(true)); } @Test From 4db2ccd0571f6043b0c9f8be243b9976479291e2 Mon Sep 17 00:00:00 2001 From: Florent Clarret Date: Sun, 16 Jul 2017 22:33:22 +0200 Subject: [PATCH 2/4] Add a factory for the SoundCategory enum --- .../net/glowstone/constants/GlowSound.java | 11 +++++-- .../java/net/glowstone/util/SoundUtil.java | 20 ++++++++++++ .../net/glowstone/util/SoundUtilTest.java | 31 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/test/java/net/glowstone/util/SoundUtilTest.java diff --git a/src/main/java/net/glowstone/constants/GlowSound.java b/src/main/java/net/glowstone/constants/GlowSound.java index 268f69defd..ab88f499c8 100644 --- a/src/main/java/net/glowstone/constants/GlowSound.java +++ b/src/main/java/net/glowstone/constants/GlowSound.java @@ -1,5 +1,6 @@ package net.glowstone.constants; +import com.google.common.collect.ImmutableMap; import org.bukkit.Sound; import org.bukkit.SoundCategory; @@ -8,7 +9,7 @@ public class GlowSound { - private static Map sounds = new HashMap<>(); + private static final Map SOUNDS = new HashMap<>(); static { // register vanilla sounds @@ -20,11 +21,11 @@ public class GlowSound { } public static void reg(String id, SoundCategory category) { - sounds.put(id, category); + SOUNDS.put(id, category); } public static SoundCategory getSoundCategory(String id) { - return sounds.get(id); + return SOUNDS.get(id); } public static String getVanillaId(Sound sound) { @@ -45,4 +46,8 @@ public static Sound getVanillaSound(String id) { public static SoundCategory getCategory(int category) { return SoundCategory.values()[category]; } + + public static Map getSounds() { + return (Map) ImmutableMap.builder().putAll(SOUNDS).build(); + } } diff --git a/src/main/java/net/glowstone/util/SoundUtil.java b/src/main/java/net/glowstone/util/SoundUtil.java index 72f6d74723..b05bd21e87 100644 --- a/src/main/java/net/glowstone/util/SoundUtil.java +++ b/src/main/java/net/glowstone/util/SoundUtil.java @@ -4,6 +4,7 @@ import net.glowstone.entity.GlowPlayer; import org.bukkit.Location; import org.bukkit.Sound; +import org.bukkit.SoundCategory; import java.util.Arrays; import java.util.concurrent.ThreadLocalRandom; @@ -36,4 +37,23 @@ public static float randomReal(float range) { ThreadLocalRandom rand = ThreadLocalRandom.current(); return (rand.nextFloat() - rand.nextFloat()) * range; } + + /** + * Convert a string to a SoundCategory. The comparison is done on the name and is not case-sensitive. + * @param category The string name of the category + * @return The matching SoundCategory, null if none. + */ + public static SoundCategory buildSoundCategory(final String category) { + if (category == null) { + return null; + } + + for (final SoundCategory soundCategory : SoundCategory.values()) { + if (category.equalsIgnoreCase(soundCategory.name())) { + return soundCategory; + } + } + + return null; + } } diff --git a/src/test/java/net/glowstone/util/SoundUtilTest.java b/src/test/java/net/glowstone/util/SoundUtilTest.java new file mode 100644 index 0000000000..2a63797b15 --- /dev/null +++ b/src/test/java/net/glowstone/util/SoundUtilTest.java @@ -0,0 +1,31 @@ +package net.glowstone.util; + +import org.bukkit.SoundCategory; +import org.junit.Test; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +public class SoundUtilTest { + + @Test + public void testBuildSoundCategory() { + assertThat(SoundUtil.buildSoundCategory("master"), is(SoundCategory.MASTER)); + assertThat(SoundUtil.buildSoundCategory("MaStEr"), is(SoundCategory.MASTER)); + assertThat(SoundUtil.buildSoundCategory("music"), is(SoundCategory.MUSIC)); + assertThat(SoundUtil.buildSoundCategory("records"), is(SoundCategory.RECORDS)); + assertThat(SoundUtil.buildSoundCategory("weather"), is(SoundCategory.WEATHER)); + assertThat(SoundUtil.buildSoundCategory("blocks"), is(SoundCategory.BLOCKS)); + assertThat(SoundUtil.buildSoundCategory("hostile"), is(SoundCategory.HOSTILE)); + assertThat(SoundUtil.buildSoundCategory("neutral"), is(SoundCategory.NEUTRAL)); + assertThat(SoundUtil.buildSoundCategory("players"), is(SoundCategory.PLAYERS)); + assertThat(SoundUtil.buildSoundCategory("ambient"), is(SoundCategory.AMBIENT)); + assertThat(SoundUtil.buildSoundCategory("voice"), is(SoundCategory.VOICE)); + + assertThat(SoundUtil.buildSoundCategory("noise"), nullValue()); + assertThat(SoundUtil.buildSoundCategory(""), nullValue()); + assertThat(SoundUtil.buildSoundCategory(null), nullValue()); + } + +} From 8b1fe416a03a34c5cadc9b4fc22ab8bbe182fbaa Mon Sep 17 00:00:00 2001 From: Florent Clarret Date: Mon, 17 Jul 2017 03:29:12 +0200 Subject: [PATCH 3/4] Add the /playsound command --- src/main/java/net/glowstone/GlowServer.java | 1 + .../command/minecraft/PlaySoundCommand.java | 174 ++++++++++++++ .../minecraft/PlaySoundCommandTest.java | 227 ++++++++++++++++++ 3 files changed, 402 insertions(+) create mode 100644 src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java create mode 100644 src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java diff --git a/src/main/java/net/glowstone/GlowServer.java b/src/main/java/net/glowstone/GlowServer.java index feeeee0cb7..fcef55e87f 100644 --- a/src/main/java/net/glowstone/GlowServer.java +++ b/src/main/java/net/glowstone/GlowServer.java @@ -857,6 +857,7 @@ private void loadPlugins() { commandMap.register("minecraft", new SpawnPointCommand()); commandMap.register("minecraft", new ToggleDownfallCommand()); commandMap.register("minecraft", new SetWorldSpawnCommand()); + commandMap.register("minecraft", new PlaySoundCommand()); File folder = new File(config.getString(Key.PLUGIN_FOLDER)); if (!folder.isDirectory() && !folder.mkdirs()) { diff --git a/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java b/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java new file mode 100644 index 0000000000..327f999301 --- /dev/null +++ b/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java @@ -0,0 +1,174 @@ +package net.glowstone.command.minecraft; + +import net.glowstone.command.CommandTarget; +import net.glowstone.command.CommandUtils; +import net.glowstone.constants.GlowSound; +import net.glowstone.entity.GlowPlayer; +import net.glowstone.util.SoundUtil; +import org.bukkit.*; +import org.bukkit.command.CommandSender; +import org.bukkit.command.defaults.VanillaCommand; +import org.bukkit.entity.Entity; +import org.bukkit.util.StringUtil; + +import java.util.*; +import java.util.stream.Collectors; + +public class PlaySoundCommand extends VanillaCommand { + + private static final List SOURCES = Arrays.stream(SoundCategory.values()).map(SoundCategory::name).map(String::toLowerCase).collect(Collectors.toList()); + + private static final Set SOUNDS = GlowSound.getSounds().keySet(); + + public PlaySoundCommand() { + super("playsound", "Plays a sound.", "/playsound [x] [y] [z] [volume] [pitch] [minimumVolume]", Collections.emptyList()); + setPermission("minecraft.command.playsound"); + } + + @Override + public boolean execute(CommandSender sender, String label, String[] args) { + if (!testPermission(sender)) return false; + + if (args.length < 3 || args.length == 4 || args.length == 5) { + sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); + return false; + } + + final World world = CommandUtils.getWorld(sender); + + if (world == null) { + return false; + } + + String stringSound = args[0], stringCategory = args[1], playerPattern = args[2]; + final Sound sound = GlowSound.getVanillaSound(stringSound); + final SoundCategory soundCategory = SoundUtil.buildSoundCategory(stringCategory); + List targets; + boolean relativeLocation = false; + double volume = 1, minimumVolume = 0, pitch = 1; + + if (sound == null) { + sender.sendMessage(ChatColor.RED + "'" + stringSound + "' is not a valid sound."); + return false; + } + + if (soundCategory == null) { + sender.sendMessage(ChatColor.RED + "'" + stringCategory + "' is not a valid sound category."); + return false; + } + + // Manage player(s) + if (playerPattern.startsWith("@") && playerPattern.length() > 1 && CommandUtils.isPhysical(sender)) { // Manage selectors + final Location senderLocation = CommandUtils.getLocation(sender); + final Entity[] entities = new CommandTarget(sender, args[0]).getMatched(senderLocation); + targets = Arrays.stream(entities).filter(GlowPlayer.class::isInstance).map(GlowPlayer.class::cast).collect(Collectors.toList()); + } else { + final GlowPlayer player = (GlowPlayer) Bukkit.getPlayerExact(playerPattern); + + if (player == null) { + sender.sendMessage(ChatColor.RED + "Player '" + playerPattern + "' cannot be found"); + return false; + } else { + targets = Collections.singletonList(player); + } + } + + if (args.length >= 9) { + try { + minimumVolume = Double.valueOf(args[8]); + + if (minimumVolume < 0 || minimumVolume > 1) { + sender.sendMessage(ChatColor.RED + "Minimum volume value (" + args[8] + ") must be between 0 and 1"); + return false; + } + } catch (final NumberFormatException n) { + sender.sendMessage(ChatColor.RED + "'" + args[8] + "' is not a valid number"); + return false; + } + } + + if (args.length >= 8) { + try { + pitch = Double.valueOf(args[7]); + + if (pitch < 0 || pitch > 2) { + sender.sendMessage(ChatColor.RED + "Pitch value (" + args[7] + ") must be between 0 and 2"); + return false; + } else if (pitch < 0.5) { + pitch = 0.5; + } + + } catch (final NumberFormatException n) { + sender.sendMessage(ChatColor.RED + "'" + args[7] + "' is not a valid number"); + return false; + } + } + + if (args.length >= 7) { + try { + volume = Double.valueOf(args[6]); + } catch (final NumberFormatException n) { + sender.sendMessage(ChatColor.RED + "'" + args[6] + "' is not a valid number"); + return false; + } + } + + if (args.length >= 6) { + relativeLocation = args[3].startsWith("~") || args[4].startsWith("~") || args[5].startsWith("~"); + } + + for (final GlowPlayer target : targets) { + Location soundLocation, targetLocation = target.getLocation(); + double targetVolume = volume; + + try { + if (relativeLocation) { + soundLocation = CommandUtils.getLocation(targetLocation, args[3], args[4], args[5]); + } else if (args.length >= 6) { + soundLocation = CommandUtils.getLocation(new Location(world, 0, 0, 0), args[3], args[4], args[5]); + } else { + soundLocation = targetLocation; + } + } catch (final NumberFormatException n) { + sender.sendMessage(ChatColor.RED + "The position (" + args[3] + "," + args[4] + "," + args[5] + ") is invalid"); + return false; + } + + // If the target is outside the normal audible sphere + if (targetLocation.distanceSquared(soundLocation) > Math.pow(volume, 2)) { + if (minimumVolume <= 0) { + sender.sendMessage(ChatColor.RED + target.getName() + " is too far away to hear the sound"); + return false; + } else { + final double deltaX = soundLocation.getX() - targetLocation.getX(), + deltaY = soundLocation.getX() - targetLocation.getY(), + deltaZ = soundLocation.getX() - targetLocation.getZ(); + final double delta = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2) + Math.pow(deltaZ, 2)); + + soundLocation = targetLocation; + soundLocation.add(deltaX / delta, deltaY / delta, deltaZ / delta); + targetVolume = minimumVolume; + } + } + + target.playSound(soundLocation, sound, soundCategory, (float) targetVolume, (float) pitch); + } + + return true; + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + if (args == null) { + return Collections.emptyList(); + } else if (args.length == 1) { + return StringUtil.copyPartialMatches(args[0], SOUNDS, new ArrayList(SOUNDS.size())); + } else if (args.length == 2) { + return StringUtil.copyPartialMatches(args[1], SOURCES, new ArrayList(SOURCES.size())); + } else if (args.length == 3) { + return super.tabComplete(sender, alias, args); + } else { + return Collections.emptyList(); + } + } +} diff --git a/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java b/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java new file mode 100644 index 0000000000..45a1908906 --- /dev/null +++ b/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java @@ -0,0 +1,227 @@ +package net.glowstone.command.minecraft; + +import com.google.common.collect.ImmutableList; +import net.glowstone.GlowServer; +import net.glowstone.GlowWorld; +import net.glowstone.command.CommandUtils; +import net.glowstone.entity.GlowPlayer; +import org.bukkit.*; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +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 java.util.Collections; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, CommandUtils.class, GlowServer.class, GlowWorld.class}) +public class PlaySoundCommandTest { + + private Player fakePlayer1, fakePlayer2, fakePlayer3; + + private GlowWorld world; + + private GlowServer server; + + private CommandSender sender, opSender, opPlayer; + + private Command command; + + @Before + public void before() { + command = new PlaySoundCommand(); + sender = PowerMockito.mock(CommandSender.class); + opSender = PowerMockito.mock(CommandSender.class); + opPlayer = PowerMockito.mock(Player.class); + server = PowerMockito.mock(GlowServer.class); + world = PowerMockito.mock(GlowWorld.class); + + fakePlayer1 = PowerMockito.mock(GlowPlayer.class); + fakePlayer2 = PowerMockito.mock(GlowPlayer.class); + fakePlayer3 = PowerMockito.mock(GlowPlayer.class); + + final Location location = new Location(world, 10.5, 20.5, 30.5); + Mockito.when(fakePlayer1.getName()).thenReturn("player1"); + Mockito.when(fakePlayer2.getName()).thenReturn("player2"); + Mockito.when(fakePlayer3.getName()).thenReturn("thePlayer3"); + Mockito.when(fakePlayer1.getLocation()).thenReturn(location); + Mockito.when(fakePlayer2.getLocation()).thenReturn(location); + Mockito.when(fakePlayer3.getLocation()).thenReturn(location); + Mockito.when(fakePlayer1.getType()).thenReturn(EntityType.PLAYER); + Mockito.when(fakePlayer2.getType()).thenReturn(EntityType.PLAYER); + Mockito.when(fakePlayer3.getType()).thenReturn(EntityType.PLAYER); + + Mockito.when(opSender.hasPermission(Mockito.anyString())).thenReturn(true); + Mockito.when(opSender.getServer()).thenReturn(server); + + Mockito.when(opPlayer.hasPermission(Mockito.anyString())).thenReturn(true); + Mockito.when(opPlayer.getName()).thenReturn("ChuckNorris"); + Mockito.when(((Entity)opPlayer).getLocation()).thenReturn(location); + + Mockito.doReturn(ImmutableList.of(fakePlayer1, fakePlayer2, fakePlayer3)) + .when(server).getOnlinePlayers(); + + Mockito.when(world.getEntities()).thenReturn(ImmutableList.of(fakePlayer1, fakePlayer2, fakePlayer3)); + + PowerMockito.mockStatic(Bukkit.class); + Mockito.when(Bukkit.getPlayerExact("player1")).thenReturn(fakePlayer1); + Mockito.when(Bukkit.getPlayerExact("player2")).thenReturn(fakePlayer2); + Mockito.when(Bukkit.getPlayerExact("thePlayer3")).thenReturn(fakePlayer3); + + PowerMockito.stub(PowerMockito.method(CommandUtils.class, "getWorld", CommandSender.class)).toReturn(world); + } + + @Test + public void testExecuteFailsWithoutPermission() { + assertThat(command.execute(sender, "label", new String[0]), is(false)); + Mockito.verify(sender).sendMessage(eq(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.")); + } + + @Test + public void testExecuteFailsWithIncorrectSound() { + assertThat(command.execute(opSender, "label", new String[]{"noise", "source", "player"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'noise' is not a valid sound.")); + } + + @Test + public void testExecuteFailsWithIncorrectSoundCategory() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "source", "player"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'source' is not a valid sound category.")); + } + + @Test + public void testExecuteFailsUnknownTarget() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Player 'player' cannot be found")); + } + + @Test + public void testExecuteFailsMinimumVolumeOutOfRange() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "300", "2", "300"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Minimum volume value (300) must be between 0 and 1")); + } + + @Test + public void testExecuteFailsMinimumVolumeInvalid() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "300", "2", "volume"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'volume' is not a valid number")); + } + + @Test + public void testExecuteFailsPitchOutOfRange() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "300", "300", "1"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "Pitch value (300) must be between 0 and 2")); + } + + @Test + public void testExecuteFailsPitchInvalid() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "300", "pitch", "1"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'pitch' is not a valid number")); + } + + @Test + public void testExecuteFailsVolumeInvalid() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "volume", "1", "1"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "'volume' is not a valid number")); + } + + @Test + public void testExecuteFailsPositionInvalid() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "Y", "30", "1", "1"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "The position (0,0,Y) is invalid")); + } + + @Test + public void testExecuteFailsPlayerTooFarAway() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "100000", "100000", "100000"}), is(false)); + Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "player1 is too far away to hear the sound")); + } + + @Test + public void testExecuteSucceedsOnAnotherPlayerWithCurrentLocation() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 10.5, 20.5, 30.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 1, 1); + } + + @Test + public void testExecuteSucceedsOnAllPlayersWithCurrentLocation() { + assertThat(command.execute(opPlayer, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "@a"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 10.5, 20.5, 30.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 1, 1); + Mockito.verify(Bukkit.getPlayerExact("player2")).playSound(new Location(world, 10.5, 20.5, 30.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 1, 1); + Mockito.verify(Bukkit.getPlayerExact("thePlayer3")).playSound(new Location(world, 10.5, 20.5, 30.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 1, 1); + } + + @Test + public void testExecuteSucceedsOnAnotherPlayerWithSpecificLocation() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "200"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 0.5, 0.5, 0.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, 1); + } + + @Test + public void testExecuteSucceedsOnAllPlayersWithSpecificLocation() { + assertThat(command.execute(opPlayer, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "@a", "0", "0", "0", "200"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 0.5, 0.5, 0.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, 1); + Mockito.verify(Bukkit.getPlayerExact("player2")).playSound(new Location(world, 0.5, 0.5, 0.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, 1); + Mockito.verify(Bukkit.getPlayerExact("thePlayer3")).playSound(new Location(world, 0.5, 0.5, 0.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, 1); + } + + @Test + public void testExecuteSucceedsOnAnotherPlayerWithRelativeLocation() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "~20", "~20", "~5", "200"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 31, 41, 36), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, 1); + } + + @Test + public void testExecuteSucceedsOnAnotherPlayerWithSmallPitch() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "200", "0.05"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 0.5, 0.5, 0.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, (float) 0.5); + } + + @Test + public void testExecuteSucceedsOnAnotherPlayerWithSpecificPitch() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "200", "0.6"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 0.5, 0.5, 0.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 200, (float) 0.6); + } + + @Test + public void testExecuteSucceedsOnAnotherPlayerWithMinimumVolume() { + assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1", "0", "0", "0", "10", "0.6", "1"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(any(Location.class), eq(Sound.ENTITY_PARROT_IMITATE_WITHER), eq(SoundCategory.MASTER), eq((float) 1), eq((float) 0.6)); + } + + @Test + public void testTabComplete() { + assertThat(command.tabComplete(null, null, null), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[0]), is(Collections.emptyList())); + + assertThat(command.tabComplete(opSender, "alias", new String[]{"minecraft:entity.parrot.imitate.wither"}), + is(ImmutableList.of("minecraft:entity.parrot.imitate.wither", "minecraft:entity.parrot.imitate.wither.skeleton"))); + + assertThat(command.tabComplete(opSender, "alias", new String[]{"sound", "hosti"}), is(ImmutableList.of("hostile"))); + + assertThat(command.tabComplete(opSender, "alias", new String[]{"sound", "hostile", ""}), is(ImmutableList.of("player1", "player2", "thePlayer3"))); + assertThat(command.tabComplete(opSender, "alias", new String[]{"sound", "hostile", "play"}), is(ImmutableList.of("player1", "player2"))); + assertThat(command.tabComplete(opSender, "alias", new String[]{"sound", "hostile", "the"}), is(ImmutableList.of("thePlayer3"))); + + assertThat(command.tabComplete(opSender, "alias", new String[4]), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[5]), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[6]), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[7]), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[8]), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[9]), is(Collections.emptyList())); + assertThat(command.tabComplete(opSender, "alias", new String[10]), is(Collections.emptyList())); + } +} From ad8c0216421632eb7b9ba6ef93a4d74100ec5d5d Mon Sep 17 00:00:00 2001 From: Florent Clarret Date: Sat, 22 Jul 2017 20:27:58 +0200 Subject: [PATCH 4/4] Update the /playsound command to deal with the 'minecraft:' prefix --- .../glowstone/command/minecraft/PlaySoundCommand.java | 11 +++++++++-- .../command/minecraft/PlaySoundCommandTest.java | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java b/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java index 327f999301..2f88edfcce 100644 --- a/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java +++ b/src/main/java/net/glowstone/command/minecraft/PlaySoundCommand.java @@ -41,7 +41,7 @@ public boolean execute(CommandSender sender, String label, String[] args) { } String stringSound = args[0], stringCategory = args[1], playerPattern = args[2]; - final Sound sound = GlowSound.getVanillaSound(stringSound); + final Sound sound = GlowSound.getVanillaSound(stringSound.startsWith("minecraft:") ? stringSound : "minecraft:" + stringSound); final SoundCategory soundCategory = SoundUtil.buildSoundCategory(stringCategory); List targets; boolean relativeLocation = false; @@ -162,7 +162,14 @@ public List tabComplete(CommandSender sender, String alias, String[] arg if (args == null) { return Collections.emptyList(); } else if (args.length == 1) { - return StringUtil.copyPartialMatches(args[0], SOUNDS, new ArrayList(SOUNDS.size())); + String sound = args[0]; + + if (!sound.startsWith("minecraft:")) { + final int colonIndex = sound.indexOf(':'); + sound = "minecraft:" + sound.substring(colonIndex == -1 ? 0 : (colonIndex + 1)); + } + + return StringUtil.copyPartialMatches(sound, SOUNDS, new ArrayList(SOUNDS.size())); } else if (args.length == 2) { return StringUtil.copyPartialMatches(args[1], SOURCES, new ArrayList(SOURCES.size())); } else if (args.length == 3) { diff --git a/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java b/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java index 45a1908906..1ebc04a959 100644 --- a/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java +++ b/src/test/java/net/glowstone/command/minecraft/PlaySoundCommandTest.java @@ -150,6 +150,12 @@ public void testExecuteFailsPlayerTooFarAway() { Mockito.verify(opSender).sendMessage(eq(ChatColor.RED + "player1 is too far away to hear the sound")); } + @Test + public void testExecuteSucceedsWithoutMinecraftPrefix() { + assertThat(command.execute(opSender, "label", new String[]{"entity.parrot.imitate.wither", "master", "player1"}), is(true)); + Mockito.verify(Bukkit.getPlayerExact("player1")).playSound(new Location(world, 10.5, 20.5, 30.5), Sound.ENTITY_PARROT_IMITATE_WITHER, SoundCategory.MASTER, 1, 1); + } + @Test public void testExecuteSucceedsOnAnotherPlayerWithCurrentLocation() { assertThat(command.execute(opSender, "label", new String[]{"minecraft:entity.parrot.imitate.wither", "master", "player1"}), is(true)); @@ -209,6 +215,10 @@ public void testTabComplete() { assertThat(command.tabComplete(opSender, "alias", new String[]{"minecraft:entity.parrot.imitate.wither"}), is(ImmutableList.of("minecraft:entity.parrot.imitate.wither", "minecraft:entity.parrot.imitate.wither.skeleton"))); + assertThat(command.tabComplete(opSender, "alias", new String[]{"entity.parrot.imitate.wither"}), + is(ImmutableList.of("minecraft:entity.parrot.imitate.wither", "minecraft:entity.parrot.imitate.wither.skeleton"))); + assertThat(command.tabComplete(opSender, "alias", new String[]{"chuckNorris:entity.parrot.imitate.wither"}), + is(ImmutableList.of("minecraft:entity.parrot.imitate.wither", "minecraft:entity.parrot.imitate.wither.skeleton"))); assertThat(command.tabComplete(opSender, "alias", new String[]{"sound", "hosti"}), is(ImmutableList.of("hostile")));