diff --git a/src/main/java/com/garbagemule/MobArena/things/CommandThing.java b/src/main/java/com/garbagemule/MobArena/things/CommandThing.java new file mode 100644 index 0000000..f30e25c --- /dev/null +++ b/src/main/java/com/garbagemule/MobArena/things/CommandThing.java @@ -0,0 +1,68 @@ +package com.garbagemule.MobArena.things; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.Objects; + +public class CommandThing implements Thing { + private final String command; + private final String title; + + public CommandThing(String command) { + this(command, null); + } + + public CommandThing(String command, String title) { + this.command = trimSlash(command); + this.title = title; + } + + @Override + public boolean giveTo(Player player) { + return Bukkit.getServer().dispatchCommand( + Bukkit.getConsoleSender(), + command.replace("", player.getName()) + ); + } + + @Override + public boolean takeFrom(Player player) { + return false; + } + + @Override + public boolean heldBy(Player player) { + return false; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof CommandThing)) return false; + + CommandThing other = (CommandThing) o; + return Objects.equals(command, other.command) + && Objects.equals(title, other.title); + } + + @Override + public int hashCode() { + return Objects.hash(command, title); + } + + @Override + public String toString() { + if (title != null) { + return title; + } + return "/" + command; + } + + private String trimSlash(String command) { + if (command.startsWith("/")) { + return command.substring(1); + } + return command; + } +} diff --git a/src/main/java/com/garbagemule/MobArena/things/CommandThingParser.java b/src/main/java/com/garbagemule/MobArena/things/CommandThingParser.java new file mode 100644 index 0000000..7e8af61 --- /dev/null +++ b/src/main/java/com/garbagemule/MobArena/things/CommandThingParser.java @@ -0,0 +1,66 @@ +package com.garbagemule.MobArena.things; + +class CommandThingParser implements ThingParser { + private static final String PREFIX_LONG = "command"; + private static final String PREFIX_SHORT = "cmd"; + + @Override + public CommandThing parse(String s) { + String trimmed = trimPrefix(s); + if (trimmed == null) { + return null; + } + if (trimmed.startsWith(":")) { + return untitledCommand(trimmed); + } + if (trimmed.startsWith("(")) { + return titledCommand(s, trimmed); + } + return null; + } + + private String trimPrefix(String s) { + if (s.startsWith(PREFIX_SHORT)) { + return s.substring(PREFIX_SHORT.length()).trim(); + } + if (s.startsWith(PREFIX_LONG)) { + return s.substring(PREFIX_LONG.length()).trim(); + } + return null; + } + + private CommandThing untitledCommand(String trimmed) { + String command = trimmed.substring(1).trim(); + return new CommandThing(command); + + } + + private CommandThing titledCommand(String s, String trimmed) { + int end = findCloseParenthesis(trimmed); + if (end == -1) { + throw new IllegalArgumentException("Missing close parenthesis in " + s); + } + if (trimmed.length() <= end || trimmed.charAt(end + 1) != ':') { + throw new IllegalArgumentException("Expected 'cmd():' but got " + s); + } + + String title = trimmed.substring(1, end); + String command = trimmed.substring(end + 2).trim(); + + return new CommandThing(command, title); + } + + private int findCloseParenthesis(String trimmed) { + int stack = 1; + for (int i = 1; i < trimmed.length() - 1; i++) { + switch (trimmed.charAt(i)) { + case '(': stack++; break; + case ')': stack--; break; + } + if (stack == 0) { + return i; + } + } + return -1; + } +} diff --git a/src/main/java/com/garbagemule/MobArena/things/ThingManager.java b/src/main/java/com/garbagemule/MobArena/things/ThingManager.java index 7711c7c..730721f 100644 --- a/src/main/java/com/garbagemule/MobArena/things/ThingManager.java +++ b/src/main/java/com/garbagemule/MobArena/things/ThingManager.java @@ -10,6 +10,7 @@ public class ThingManager implements ThingParser { public ThingManager(MobArena plugin) { parsers = new ArrayList<>(); + parsers.add(new CommandThingParser()); parsers.add(new MoneyThingParser(plugin)); parsers.add(new ItemStackThingParser()); } diff --git a/src/test/java/com/garbagemule/MobArena/things/CommandThingParserTest.java b/src/test/java/com/garbagemule/MobArena/things/CommandThingParserTest.java new file mode 100644 index 0000000..fffa4f9 --- /dev/null +++ b/src/test/java/com/garbagemule/MobArena/things/CommandThingParserTest.java @@ -0,0 +1,91 @@ +package com.garbagemule.MobArena.things; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class CommandThingParserTest { + + private CommandThingParser subject; + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Before + public void setup() { + subject = new CommandThingParser(); + } + + @Test + public void emptyStringReturnsNull() { + Thing result = subject.parse(""); + + assertThat(result, is(nullValue())); + } + + @Test + public void commandWithoutPrefixReturnsNull() { + Thing result = subject.parse("/give dirt"); + + assertThat(result, is(nullValue())); + } + + @Test + public void barePrefixReturnsNull() { + Thing result = subject.parse("cmd"); + + assertThat(result, is(nullValue())); + } + + @Test + public void commandWithShortPrefix() { + String command = "/give dirt"; + + Thing result = subject.parse("cmd:" + command); + + Thing expected = new CommandThing(command); + assertThat(result, equalTo(expected)); + } + + @Test + public void commandWithLongPrefix() { + String command = "/give dirt"; + + Thing result = subject.parse("command:" + command); + + Thing expected = new CommandThing(command); + assertThat(result, equalTo(expected)); + } + + @Test + public void commandWithTitle() { + String command = "/give dirt"; + String title = "the best command"; + + Thing result = subject.parse("cmd(" + title + "):" + command); + + Thing expected = new CommandThing(command, title); + assertThat(result, equalTo(expected)); + } + + @Test + public void missingCloseParenThrows() { + exception.expect(IllegalArgumentException.class); + + subject.parse("cmd(name:/give dirt"); + } + + @Test + public void missingColonAfterTitleThrows() { + exception.expect(IllegalArgumentException.class); + + subject.parse("cmd(name)"); + } + +}