From 3c85ef439fa8ab5ad9e3a658078701672444d184 Mon Sep 17 00:00:00 2001 From: LOOHP Date: Fri, 7 Aug 2020 22:26:00 +0800 Subject: [PATCH] Added Events, Commands and Plugins --- .classpath | 20 -- .project | 23 -- modules/LimboDefaultCmd.jar | Bin 0 -> 3841 bytes .../loohp/limbo/Commands/CommandExecutor.java | 7 + .../loohp/limbo/Commands/CommandSender.java | 17 ++ .../loohp/limbo/Commands/TabCompletor.java | 9 + src/com/loohp/limbo/Console.java | 211 ++++++++++++++---- src/com/loohp/limbo/DeclareCommands.java | 39 +++- src/com/loohp/limbo/Events/Cancellable.java | 9 + src/com/loohp/limbo/Events/Event.java | 5 + src/com/loohp/limbo/Events/EventHandler.java | 14 ++ src/com/loohp/limbo/Events/EventPriority.java | 37 +++ src/com/loohp/limbo/Events/EventsManager.java | 58 +++++ src/com/loohp/limbo/Events/Listener.java | 5 + .../loohp/limbo/Events/PlayerChatEvent.java | 49 ++++ src/com/loohp/limbo/Events/PlayerEvent.java | 11 + .../loohp/limbo/Events/PlayerJoinEvent.java | 16 ++ .../loohp/limbo/Events/PlayerLoginEvent.java | 41 ++++ .../loohp/limbo/Events/PlayerQuitEvent.java | 16 ++ .../loohp/limbo/File/FileConfiguration.java | 22 +- src/com/loohp/limbo/Limbo.java | 91 +++++++- .../limbo/Permissions/PermissionsManager.java | 64 ++++++ src/com/loohp/limbo/Player/Player.java | 22 +- src/com/loohp/limbo/Plugins/LimboPlugin.java | 48 ++++ src/com/loohp/limbo/Plugins/PluginInfo.java | 41 ++++ .../loohp/limbo/Plugins/PluginManager.java | 140 ++++++++++++ .../loohp/limbo/Server/ClientConnection.java | 106 ++++----- .../Packets/PacketPlayOutTabComplete.java | 1 + src/permission.yml | 11 + 29 files changed, 965 insertions(+), 168 deletions(-) delete mode 100644 .classpath delete mode 100644 .project create mode 100644 modules/LimboDefaultCmd.jar create mode 100644 src/com/loohp/limbo/Commands/CommandExecutor.java create mode 100644 src/com/loohp/limbo/Commands/CommandSender.java create mode 100644 src/com/loohp/limbo/Commands/TabCompletor.java create mode 100644 src/com/loohp/limbo/Events/Cancellable.java create mode 100644 src/com/loohp/limbo/Events/Event.java create mode 100644 src/com/loohp/limbo/Events/EventHandler.java create mode 100644 src/com/loohp/limbo/Events/EventPriority.java create mode 100644 src/com/loohp/limbo/Events/EventsManager.java create mode 100644 src/com/loohp/limbo/Events/Listener.java create mode 100644 src/com/loohp/limbo/Events/PlayerChatEvent.java create mode 100644 src/com/loohp/limbo/Events/PlayerEvent.java create mode 100644 src/com/loohp/limbo/Events/PlayerJoinEvent.java create mode 100644 src/com/loohp/limbo/Events/PlayerLoginEvent.java create mode 100644 src/com/loohp/limbo/Events/PlayerQuitEvent.java create mode 100644 src/com/loohp/limbo/Permissions/PermissionsManager.java create mode 100644 src/com/loohp/limbo/Plugins/LimboPlugin.java create mode 100644 src/com/loohp/limbo/Plugins/PluginInfo.java create mode 100644 src/com/loohp/limbo/Plugins/PluginManager.java create mode 100644 src/permission.yml diff --git a/.classpath b/.classpath deleted file mode 100644 index ef141e6..0000000 --- a/.classpath +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index 5c6b9c0..0000000 --- a/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - Limbo - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - org.eclipse.jdt.core.javanature - - diff --git a/modules/LimboDefaultCmd.jar b/modules/LimboDefaultCmd.jar new file mode 100644 index 0000000000000000000000000000000000000000..df820869227377fcc9a6594f432920728fd0e955 GIT binary patch literal 3841 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 tabComplete(CommandSender sender, String[] args); + +} diff --git a/src/com/loohp/limbo/Console.java b/src/com/loohp/limbo/Console.java index 4436eb1..d5c9851 100644 --- a/src/com/loohp/limbo/Console.java +++ b/src/com/loohp/limbo/Console.java @@ -1,6 +1,8 @@ package com.loohp.limbo; import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -10,19 +12,54 @@ import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.Locale; +import java.util.stream.Collectors; -import com.loohp.limbo.Player.Player; +import com.loohp.limbo.Commands.CommandSender; import com.loohp.limbo.Utils.CustomStringUtils; -public class Console { +import net.md_5.bungee.api.chat.BaseComponent; + +public class Console implements CommandSender { private InputStream in; private PrintStream out; + @SuppressWarnings("unused") + private PrintStream err; + protected PrintStream logs; - public Console(InputStream in, PrintStream out) { + private final String CONSOLE = "CONSOLE"; + + public Console(InputStream in, PrintStream out, PrintStream err) throws FileNotFoundException { + String fileName = new SimpleDateFormat("yyyy'-'MM'-'dd'_'HH'-'mm'-'ss'_'zzz'.log'").format(new Date()); + File dir = new File("logs"); + dir.mkdirs(); + File logs = new File(dir, fileName); + this.logs = new PrintStream(logs); + + System.setIn(in); this.in = in; - System.setOut(new ConsoleOutputStream(out)); + System.setOut(new ConsoleOutputStream(out, this.logs)); this.out = System.out; + System.setErr(new ConsoleErrorStream(err, this.logs)); + this.err = System.err; + } + + public String getName() { + return CONSOLE; + } + + @Override + public void sendMessage(BaseComponent component) { + sendMessage(new BaseComponent[] {component}); + } + + @Override + public void sendMessage(BaseComponent[] component) { + sendMessage(String.join("", Arrays.asList(component).stream().map(each -> each.toLegacyText()).collect(Collectors.toList()))); + } + + public boolean hasPermission(String permission) { + return Limbo.getInstance().getPermissionsManager().hasPermission(this, permission); } public void sendMessage(String message) { @@ -33,115 +70,199 @@ public class Console { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); while (true) { try { - String[] input = CustomStringUtils.splitStringToArgs(reader.readLine()); - - if (input[0].equalsIgnoreCase("stop")) { - Limbo.getInstance().stopServer(); - } else if (input[0].equalsIgnoreCase("say")) { - if (input.length > 1) { - String message = "[Server] " + String.join(" ", Arrays.copyOfRange(input, 1, input.length)); - sendMessage(message); - for (Player each : Limbo.getInstance().getPlayers()) { - each.sendMessage(message); - } - } - } else if (input[0].equalsIgnoreCase("kick")) { - String reason = "Disconnected!"; - Player player = input.length > 1 ? Limbo.getInstance().getPlayer(input[1]) : null; - if (player != null) { - if (input.length < 2) { - player.disconnect(); - } else { - reason = String.join(" ", Arrays.copyOfRange(input, 2, input.length)); - player.disconnect(reason); - } - sendMessage("Kicked the player " + input[1] + " for the reason: " + reason); - } else { - sendMessage("Player is not online!"); - } - } + String[] input = CustomStringUtils.splitStringToArgs(reader.readLine()); + Limbo.getInstance().dispatchCommand(this, input); } catch (IOException e) { e.printStackTrace(); } } } - public class ConsoleOutputStream extends PrintStream { + public static class ConsoleOutputStream extends PrintStream { - public ConsoleOutputStream(OutputStream out) { + private PrintStream logs; + + public ConsoleOutputStream(OutputStream out, PrintStream logs) { super(out); + this.logs = logs; } @Override public PrintStream printf(Locale l, String format, Object... args) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - return super.printf(l, "[" + date + "] " + format, args); + logs.printf(l, "[" + date + " INFO]" + format, args); + return super.printf(l, "[" + date + " INFO]" + format, args); } @Override public PrintStream printf(String format, Object... args) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - return super.printf("[" + date + "] " + format, args); + logs.printf("[" + date + " INFO]" + format, args); + return super.printf("[" + date + " INFO]" + format, args); } @Override public void println() { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] "); + logs.println("[" + date + " INFO]"); + super.println("[" + date + " INFO]"); } @Override public void println(boolean x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(char x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(char[] x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + String.valueOf(x)); + logs.println("[" + date + " INFO]" + String.valueOf(x)); + super.println("[" + date + " INFO]" + String.valueOf(x)); } @Override public void println(double x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(float x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(int x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(long x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(Object x) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + x); + logs.println("[" + date + " INFO]" + x); + super.println("[" + date + " INFO]" + x); } @Override public void println(String string) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); - super.println("[" + date + "] " + string); + logs.println("[" + date + " INFO] " + string); + super.println("[" + date + " INFO] " + string); + } + } + + public static class ConsoleErrorStream extends PrintStream { + + private PrintStream logs; + + public ConsoleErrorStream(OutputStream out, PrintStream logs) { + super(out); + this.logs = logs; + } + + @Override + public PrintStream printf(Locale l, String format, Object... args) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.printf(l, "[" + date + " Error]" + format, args); + return super.printf(l, "[" + date + " Error]" + format, args); + } + + @Override + public PrintStream printf(String format, Object... args) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.printf("[" + date + " Error]" + format, args); + return super.printf("[" + date + " Error]" + format, args); + } + + @Override + public void println() { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]"); + super.println("[" + date + " Error]"); + } + + @Override + public void println(boolean x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(char x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(char[] x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + String.valueOf(x)); + super.println("[" + date + " Error]" + String.valueOf(x)); + } + + @Override + public void println(double x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(float x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(int x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(long x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(Object x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error]" + x); + super.println("[" + date + " Error]" + x); + } + + @Override + public void println(String string) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + logs.println("[" + date + " Error] " + string); + super.println("[" + date + " Error] " + string); } } diff --git a/src/com/loohp/limbo/DeclareCommands.java b/src/com/loohp/limbo/DeclareCommands.java index 5eed47f..c2553f6 100644 --- a/src/com/loohp/limbo/DeclareCommands.java +++ b/src/com/loohp/limbo/DeclareCommands.java @@ -2,27 +2,50 @@ package com.loohp.limbo; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.List; +import com.loohp.limbo.Commands.CommandSender; import com.loohp.limbo.Server.Packets.PacketPlayOutDeclareCommands; import com.loohp.limbo.Utils.DataTypeIO; public class DeclareCommands { - public static PacketPlayOutDeclareCommands getDeclareCommandPacket() throws IOException { + public static PacketPlayOutDeclareCommands getDeclareCommandsPacket(CommandSender sender) throws Exception { + List commands = Limbo.getInstance().getPluginManager().getTabOptions(sender, new String[0]); + + if (commands.isEmpty()) { + return null; + } + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(buffer); - DataTypeIO.writeVarInt(output, 2); + DataTypeIO.writeVarInt(output, commands.size() * 2 + 1); output.writeByte(0); - DataTypeIO.writeVarInt(output, 1); - DataTypeIO.writeVarInt(output, 1); + DataTypeIO.writeVarInt(output, commands.size()); + for (int i = 1; i <= commands.size() * 2; i++) { + DataTypeIO.writeVarInt(output, i++); + } - output.writeByte(1 | 0x04); - DataTypeIO.writeVarInt(output, 0); - DataTypeIO.writeString(output, "spawn", StandardCharsets.UTF_8); + int i = 1; + for (String label : commands) { + output.writeByte(1 | 0x04); + DataTypeIO.writeVarInt(output, 1); + DataTypeIO.writeVarInt(output, i + 1); + DataTypeIO.writeString(output, label, StandardCharsets.UTF_8); + i++; + + output.writeByte(2 | 0x04 | 0x10); + DataTypeIO.writeVarInt(output, 1); + DataTypeIO.writeVarInt(output, i); + DataTypeIO.writeString(output, "arg", StandardCharsets.UTF_8); + DataTypeIO.writeString(output, "brigadier:string", StandardCharsets.UTF_8); + DataTypeIO.writeVarInt(output, 0); + DataTypeIO.writeString(output, "minecraft:ask_server", StandardCharsets.UTF_8); + i++; + } DataTypeIO.writeVarInt(output, 0); diff --git a/src/com/loohp/limbo/Events/Cancellable.java b/src/com/loohp/limbo/Events/Cancellable.java new file mode 100644 index 0000000..4dbb8fd --- /dev/null +++ b/src/com/loohp/limbo/Events/Cancellable.java @@ -0,0 +1,9 @@ +package com.loohp.limbo.Events; + +public interface Cancellable { + + public void setCancelled(boolean cancelled); + + public boolean isCancelled(); + +} diff --git a/src/com/loohp/limbo/Events/Event.java b/src/com/loohp/limbo/Events/Event.java new file mode 100644 index 0000000..f5086fd --- /dev/null +++ b/src/com/loohp/limbo/Events/Event.java @@ -0,0 +1,5 @@ +package com.loohp.limbo.Events; + +public abstract class Event { + +} diff --git a/src/com/loohp/limbo/Events/EventHandler.java b/src/com/loohp/limbo/Events/EventHandler.java new file mode 100644 index 0000000..02bf719 --- /dev/null +++ b/src/com/loohp/limbo/Events/EventHandler.java @@ -0,0 +1,14 @@ +package com.loohp.limbo.Events; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface EventHandler { + EventPriority priority() default EventPriority.NORMAL; +} \ No newline at end of file diff --git a/src/com/loohp/limbo/Events/EventPriority.java b/src/com/loohp/limbo/Events/EventPriority.java new file mode 100644 index 0000000..77a31e0 --- /dev/null +++ b/src/com/loohp/limbo/Events/EventPriority.java @@ -0,0 +1,37 @@ +package com.loohp.limbo.Events; + +public enum EventPriority { + LOWEST(0), + LOW(1), + NORMAL(2), + HIGH(3), + HIGHEST(4), + MONITOR(5); + + int order; + + EventPriority(int order) { + this.order = order; + } + + public int getOrder() { + return order; + } + + public static EventPriority getByOrder(int order) { + for (EventPriority each : EventPriority.values()) { + if (each.getOrder() == order) { + return each; + } + } + return null; + } + + public static EventPriority[] getPrioritiesInOrder() { + EventPriority[] array = new EventPriority[EventPriority.values().length]; + for (int i = 0; i < array.length; i++) { + array[i] = EventPriority.getByOrder(i); + } + return array; + } +} \ No newline at end of file diff --git a/src/com/loohp/limbo/Events/EventsManager.java b/src/com/loohp/limbo/Events/EventsManager.java new file mode 100644 index 0000000..e3ed46d --- /dev/null +++ b/src/com/loohp/limbo/Events/EventsManager.java @@ -0,0 +1,58 @@ +package com.loohp.limbo.Events; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import com.loohp.limbo.Plugins.LimboPlugin; + +public class EventsManager { + + private List listeners; + + public EventsManager() { + listeners = new ArrayList<>(); + } + + public Event callEvent(Event event) { + for (EventPriority priority : EventPriority.getPrioritiesInOrder()) { + for (ListenerPair entry : listeners) { + Listener listener = entry.listener; + for (Method method : listener.getClass().getMethods()) { + if (method.isAnnotationPresent(EventHandler.class)) { + if (method.getAnnotation(EventHandler.class).priority().equals(priority)) { + if (method.getParameterCount() == 1 && method.getParameterTypes()[0].equals(event.getClass())) { + try { + method.invoke(listener, event); + } catch (Exception e) { + System.err.println("Error while passing " + event.getClass().getCanonicalName() + " to the plugin \"" + entry.plugin.getName() + "\""); + e.printStackTrace(); + } + } + } + } + } + } + } + return event; + } + + public void registerEvents(LimboPlugin plugin, Listener listener) { + listeners.add(new ListenerPair(plugin, listener)); + } + + public void unregisterAllListeners(LimboPlugin plugin) { + listeners.removeIf(each -> each.plugin.equals(plugin)); + } + + protected static class ListenerPair { + public LimboPlugin plugin; + public Listener listener; + + public ListenerPair(LimboPlugin plugin, Listener listener) { + this.plugin = plugin; + this.listener = listener; + } + } + +} diff --git a/src/com/loohp/limbo/Events/Listener.java b/src/com/loohp/limbo/Events/Listener.java new file mode 100644 index 0000000..030230b --- /dev/null +++ b/src/com/loohp/limbo/Events/Listener.java @@ -0,0 +1,5 @@ +package com.loohp.limbo.Events; + +public interface Listener { + +} diff --git a/src/com/loohp/limbo/Events/PlayerChatEvent.java b/src/com/loohp/limbo/Events/PlayerChatEvent.java new file mode 100644 index 0000000..2b28017 --- /dev/null +++ b/src/com/loohp/limbo/Events/PlayerChatEvent.java @@ -0,0 +1,49 @@ +package com.loohp.limbo.Events; + +import com.loohp.limbo.Player.Player; + +public class PlayerChatEvent extends PlayerEvent implements Cancellable { + + private String prefix; + private String message; + private boolean cancelled; + + public PlayerChatEvent(Player player, String prefix, String message, boolean cancelled) { + this.player = player; + this.prefix = prefix; + this.message = message; + this.cancelled = cancelled; + } + + @Override + public Player getPlayer() { + return player; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + +} diff --git a/src/com/loohp/limbo/Events/PlayerEvent.java b/src/com/loohp/limbo/Events/PlayerEvent.java new file mode 100644 index 0000000..888dd3d --- /dev/null +++ b/src/com/loohp/limbo/Events/PlayerEvent.java @@ -0,0 +1,11 @@ +package com.loohp.limbo.Events; + +import com.loohp.limbo.Player.Player; + +public abstract class PlayerEvent extends Event { + + protected Player player; + + public abstract Player getPlayer(); + +} diff --git a/src/com/loohp/limbo/Events/PlayerJoinEvent.java b/src/com/loohp/limbo/Events/PlayerJoinEvent.java new file mode 100644 index 0000000..5698234 --- /dev/null +++ b/src/com/loohp/limbo/Events/PlayerJoinEvent.java @@ -0,0 +1,16 @@ +package com.loohp.limbo.Events; + +import com.loohp.limbo.Player.Player; + +public class PlayerJoinEvent extends PlayerEvent { + + public PlayerJoinEvent(Player player) { + this.player = player; + } + + @Override + public Player getPlayer() { + return player; + } + +} diff --git a/src/com/loohp/limbo/Events/PlayerLoginEvent.java b/src/com/loohp/limbo/Events/PlayerLoginEvent.java new file mode 100644 index 0000000..781c8d4 --- /dev/null +++ b/src/com/loohp/limbo/Events/PlayerLoginEvent.java @@ -0,0 +1,41 @@ +package com.loohp.limbo.Events; + +import com.loohp.limbo.Server.ClientConnection; + +import net.md_5.bungee.api.chat.BaseComponent; + +public class PlayerLoginEvent extends Event implements Cancellable { + + private ClientConnection connection; + private boolean cancelled; + private BaseComponent[] cancelReason; + + public PlayerLoginEvent(ClientConnection connection, boolean cancelled, BaseComponent... cancelReason) { + this.connection = connection; + this.cancelled = cancelled; + this.cancelReason = cancelReason; + } + + public ClientConnection getConnection() { + return connection; + } + + public BaseComponent[] getCancelReason() { + return cancelReason; + } + + public void setCancelReason(BaseComponent... cancelReason) { + this.cancelReason = cancelReason; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + +} diff --git a/src/com/loohp/limbo/Events/PlayerQuitEvent.java b/src/com/loohp/limbo/Events/PlayerQuitEvent.java new file mode 100644 index 0000000..26760c8 --- /dev/null +++ b/src/com/loohp/limbo/Events/PlayerQuitEvent.java @@ -0,0 +1,16 @@ +package com.loohp.limbo.Events; + +import com.loohp.limbo.Player.Player; + +public class PlayerQuitEvent extends PlayerEvent { + + public PlayerQuitEvent(Player player) { + this.player = player; + } + + @Override + public Player getPlayer() { + return player; + } + +} diff --git a/src/com/loohp/limbo/File/FileConfiguration.java b/src/com/loohp/limbo/File/FileConfiguration.java index b9e0a46..66949ad 100644 --- a/src/com/loohp/limbo/File/FileConfiguration.java +++ b/src/com/loohp/limbo/File/FileConfiguration.java @@ -3,27 +3,26 @@ package com.loohp.limbo.File; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.InputStream; import java.util.Map; import org.yaml.snakeyaml.Yaml; public class FileConfiguration { - File file; Map mapping; public FileConfiguration(File file) throws FileNotFoundException { - this.file = file; - reloadConfig(); + reloadConfig(new FileInputStream(file)); } - public FileConfiguration reloadConfig() { - try { - Yaml yml = new Yaml(); - mapping = yml.load(new FileInputStream(file)); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } + public FileConfiguration(InputStream input){ + reloadConfig(input); + } + + public FileConfiguration reloadConfig(InputStream input) { + Yaml yml = new Yaml(); + mapping = yml.load(input); return this; } @@ -35,6 +34,9 @@ public class FileConfiguration { for (int i = 0; i < tree.length - 1; i++) { map = (Map) map.get(tree[i]); } + if (returnType.equals(String.class)) { + return (T) map.get(tree[tree.length - 1]).toString(); + } return returnType.cast(map.get(tree[tree.length - 1])); } catch (Exception e) { return null; diff --git a/src/com/loohp/limbo/Limbo.java b/src/com/loohp/limbo/Limbo.java index 311a9cf..51f86ea 100644 --- a/src/com/loohp/limbo/Limbo.java +++ b/src/com/loohp/limbo/Limbo.java @@ -19,13 +19,19 @@ import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import com.loohp.limbo.Commands.CommandSender; +import com.loohp.limbo.Events.EventsManager; import com.loohp.limbo.File.ServerProperties; import com.loohp.limbo.Location.Location; +import com.loohp.limbo.Permissions.PermissionsManager; import com.loohp.limbo.Player.Player; +import com.loohp.limbo.Plugins.LimboPlugin; +import com.loohp.limbo.Plugins.PluginManager; import com.loohp.limbo.Server.ServerConnection; import com.loohp.limbo.Server.Packets.Packet; import com.loohp.limbo.Server.Packets.PacketIn; import com.loohp.limbo.Server.Packets.PacketOut; +import com.loohp.limbo.Utils.CustomStringUtils; import com.loohp.limbo.Utils.ImageUtils; import com.loohp.limbo.Utils.NetworkUtils; import com.loohp.limbo.World.Schematic; @@ -57,13 +63,18 @@ public class Limbo { private ServerProperties properties; - public AtomicInteger entityCount = new AtomicInteger(); + private PluginManager pluginManager; + private EventsManager eventsManager; + private PermissionsManager permissionManager; + private File pluginFolder; + + public AtomicInteger entityIdCount = new AtomicInteger(); @SuppressWarnings("unchecked") public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException { instance = this; - console = new Console(System.in, System.out); + console = new Console(System.in, System.out, System.err); String spName = "server.properties"; File sp = new File(spName); @@ -170,11 +181,52 @@ public class Limbo { System.exit(2); } + String permissionName = "permission.yml"; + File permissionFile = new File(permissionName); + if (!permissionFile.exists()) { + try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) { + Files.copy(in, permissionFile.toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + permissionManager = new PermissionsManager(); + permissionManager.loadDefaultPermissionFile(permissionFile); + + eventsManager = new EventsManager(); + + pluginFolder = new File("plugins"); + pluginFolder.mkdirs(); + + pluginManager = new PluginManager(pluginFolder); + + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { + console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); + plugin.onEnable(); + } + server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); console.run(); } + public EventsManager getEventsManager() { + return eventsManager; + } + + public PermissionsManager getPermissionsManager() { + return permissionManager; + } + + public File getPluginFolder() { + return pluginFolder; + } + + public PluginManager getPluginManager() { + return pluginManager; + } + private World loadDefaultWorld() throws IOException { console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); @@ -260,7 +312,13 @@ public class Limbo { } public void stopServer() { - Limbo.getInstance().getConsole().sendMessage("Stopping Server..."); + console.sendMessage("Stopping Server..."); + + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { + console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); + plugin.onDisable(); + } + for (Player player : getPlayers()) { player.disconnect("Server closed"); } @@ -271,7 +329,34 @@ public class Limbo { e.printStackTrace(); } } + console.logs.close(); System.exit(0); } + + public int getNextEntityId() { + if (entityIdCount.get() == Integer.MAX_VALUE) { + return entityIdCount.getAndSet(0); + } else { + return entityIdCount.getAndIncrement(); + } + } + + public void dispatchCommand(CommandSender sender, String str) { + String[] command; + if (str.startsWith("/")) { + command = CustomStringUtils.splitStringToArgs(str.substring(1)); + } else { + command = CustomStringUtils.splitStringToArgs(str); + } + dispatchCommand(sender, command); + } + + public void dispatchCommand(CommandSender sender, String... args) { + try { + Limbo.getInstance().getPluginManager().fireExecutors(sender, args); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/src/com/loohp/limbo/Permissions/PermissionsManager.java b/src/com/loohp/limbo/Permissions/PermissionsManager.java new file mode 100644 index 0000000..0378bda --- /dev/null +++ b/src/com/loohp/limbo/Permissions/PermissionsManager.java @@ -0,0 +1,64 @@ +package com.loohp.limbo.Permissions; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.loohp.limbo.Console; +import com.loohp.limbo.Commands.CommandSender; +import com.loohp.limbo.File.FileConfiguration; +import com.loohp.limbo.Player.Player; + +public class PermissionsManager { + + private Map> users; + private Map> permissions; + + public PermissionsManager() { + users = new HashMap<>(); + permissions = new HashMap<>(); + } + + @SuppressWarnings("unchecked") + public void loadDefaultPermissionFile(File file) throws FileNotFoundException { + FileConfiguration config = new FileConfiguration(file); + for (Object obj : config.get("groups", Map.class).keySet()) { + String key = (String) obj; + List nodes = new ArrayList<>(); + nodes.addAll(config.get("groups." + key, List.class)); + permissions.put(key, nodes); + } + for (Object obj : config.get("players", Map.class).keySet()) { + String key = (String) obj; + List groups = new ArrayList<>(); + groups.addAll(config.get("players." + key, List.class)); + users.put(key, groups); + } + } + + public boolean hasPermission(CommandSender sender, String permission) { + if (sender instanceof Console) { + return true; + } else if (sender instanceof Player) { + Player player = (Player) sender; + if (users.get(player.getName()).stream().anyMatch(each -> permissions.get(each).stream().anyMatch(node -> node.equalsIgnoreCase(permission)))) { + return true; + } else { + return permissions.get("default").stream().anyMatch(node -> node.equalsIgnoreCase(permission)); + } + } + return false; + } + + public Map> getUsers() { + return users; + } + + public Map> getPermissions() { + return permissions; + } + +} diff --git a/src/com/loohp/limbo/Player/Player.java b/src/com/loohp/limbo/Player/Player.java index 51a25c5..920fc4b 100644 --- a/src/com/loohp/limbo/Player/Player.java +++ b/src/com/loohp/limbo/Player/Player.java @@ -3,6 +3,9 @@ package com.loohp.limbo.Player; import java.io.IOException; import java.util.UUID; +import com.loohp.limbo.Limbo; +import com.loohp.limbo.Commands.CommandSender; +import com.loohp.limbo.Events.PlayerChatEvent; import com.loohp.limbo.Location.Location; import com.loohp.limbo.Server.ClientConnection; import com.loohp.limbo.Server.Packets.PacketPlayOutChat; @@ -13,7 +16,7 @@ import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; -public class Player { +public class Player implements CommandSender { public final ClientConnection clientConnection; @@ -59,6 +62,10 @@ public class Player { public UUID getUUID() { return uuid; } + + public boolean hasPermission(String permission) { + return Limbo.getInstance().getPermissionsManager().hasPermission(this, permission); + } public void sendMessage(String message) { sendMessage(TextComponent.fromLegacyText(message)); @@ -78,6 +85,7 @@ public class Player { } } + @Override public void sendMessage(BaseComponent[] component) { try { PacketPlayOutChat chat = new PacketPlayOutChat(ComponentSerializer.toString(component), 0, new UUID(0, 0)); @@ -102,5 +110,17 @@ public class Player { public void disconnect(BaseComponent[] reason) { clientConnection.disconnect(reason); } + + public void chat(String message) { + String prefix = "<" + username + "> "; + PlayerChatEvent event = (PlayerChatEvent) Limbo.getInstance().getEventsManager().callEvent(new PlayerChatEvent(this, prefix, message, false)); + if (!event.isCancelled()) { + String chat = event.getPrefix() + event.getMessage(); + Limbo.getInstance().getConsole().sendMessage(chat); + for (Player each : Limbo.getInstance().getPlayers()) { + each.sendMessage(chat); + } + } + } } diff --git a/src/com/loohp/limbo/Plugins/LimboPlugin.java b/src/com/loohp/limbo/Plugins/LimboPlugin.java new file mode 100644 index 0000000..3216233 --- /dev/null +++ b/src/com/loohp/limbo/Plugins/LimboPlugin.java @@ -0,0 +1,48 @@ +package com.loohp.limbo.Plugins; + +import java.io.File; + +import com.loohp.limbo.Limbo; +import com.loohp.limbo.File.FileConfiguration; + +public class LimboPlugin { + + private String name; + private File dataFolder; + private PluginInfo info; + + public final void setInfo(FileConfiguration file) { + info = new PluginInfo(file); + name = info.getName(); + dataFolder = new File(Limbo.getInstance().getPluginFolder(), name); + } + + public void onLoad() { + + } + + public void onEnable() { + + } + + public void onDisable() { + + } + + public String getName() { + return name; + } + + public File getDataFolder() { + return new File(dataFolder.getAbsolutePath()); + } + + public PluginInfo getInfo() { + return info; + } + + public Limbo getServer() { + return Limbo.getInstance(); + } + +} diff --git a/src/com/loohp/limbo/Plugins/PluginInfo.java b/src/com/loohp/limbo/Plugins/PluginInfo.java new file mode 100644 index 0000000..e27c163 --- /dev/null +++ b/src/com/loohp/limbo/Plugins/PluginInfo.java @@ -0,0 +1,41 @@ +package com.loohp.limbo.Plugins; + +import com.loohp.limbo.File.FileConfiguration; + +public class PluginInfo { + + private String name; + private String description; + private String author; + private String version; + private String main; + + public PluginInfo(FileConfiguration file) { + name = file.get("name", String.class); + description = file.get("description", String.class) == null ? "" : file.get("description", String.class); + author = file.get("author", String.class); + version = file.get("version", String.class); + main = file.get("main", String.class); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getAuthor() { + return author; + } + + public String getVersion() { + return version; + } + + public String getMainClass() { + return main; + } + +} diff --git a/src/com/loohp/limbo/Plugins/PluginManager.java b/src/com/loohp/limbo/Plugins/PluginManager.java new file mode 100644 index 0000000..b52e1a7 --- /dev/null +++ b/src/com/loohp/limbo/Plugins/PluginManager.java @@ -0,0 +1,140 @@ +package com.loohp.limbo.Plugins; + +import java.io.File; +import java.io.FileInputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import com.loohp.limbo.Limbo; +import com.loohp.limbo.Commands.CommandExecutor; +import com.loohp.limbo.Commands.CommandSender; +import com.loohp.limbo.Commands.TabCompletor; +import com.loohp.limbo.File.FileConfiguration; + +public class PluginManager { + + private Map plugins; + private List executors; + private File pluginFolder; + + public PluginManager(File pluginFolder) { + this.pluginFolder = pluginFolder; + this.executors = new ArrayList<>(); + + this.plugins = new LinkedHashMap<>(); + + for (File file : pluginFolder.listFiles()) { + if (file.isFile() && file.getName().endsWith(".jar")) { + boolean found = false; + try (ZipInputStream zip = new ZipInputStream(new FileInputStream(file))) { + while (true) { + ZipEntry entry = zip.getNextEntry(); + if (entry == null) { + break; + } + String name = entry.getName(); + if (name.endsWith("plugin.yml")) { + found = true; + + FileConfiguration pluginYaml = new FileConfiguration(zip); + String main = pluginYaml.get("main", String.class); + String pluginName = pluginYaml.get("name", String.class); + + if (plugins.containsKey(pluginName)) { + System.err.println("Ambiguous plugin name in " + file.getName() + " with the plugin \"" + plugins.get(pluginName).getClass().getName() + "\""); + break; + } + + URLClassLoader url = new URLClassLoader(new URL[] {file.toURI().toURL()}); + Class plugin = url.loadClass(main); + LimboPlugin clazz = (LimboPlugin) plugin.getDeclaredConstructor().newInstance(); + clazz.setInfo(pluginYaml); + plugins.put(clazz.getName(), clazz); + clazz.onLoad(); + System.out.println("Loading plugin " + file.getName() + " " + clazz.getInfo().getVersion() + " by " + clazz.getInfo().getAuthor()); + url.close(); + break; + } + } + } catch (Exception e) { + System.err.println("Unable to load plugin \"" + file.getName() + "\""); + e.printStackTrace(); + } + if (!found) { + System.err.println("Jar file " + file.getName() + " has no plugin.yml!"); + } + } + } + } + + public List getPlugins() { + return new ArrayList<>(plugins.values()); + } + + public LimboPlugin getPlugin(String name) { + return plugins.get(name); + } + + public void fireExecutors(CommandSender sender, String[] args) throws Exception { + Limbo.getInstance().getConsole().sendMessage(sender.getName() + " executed server command: /" + String.join(" ", args)); + for (Executor entry : executors) { + try { + entry.executor.execute(sender, args); + } catch (Exception e) { + System.err.println("Error while passing command \"" + args[0] + "\" to the plugin \"" + entry.plugin.getName() + "\""); + e.printStackTrace(); + } + } + } + + public List getTabOptions(CommandSender sender, String[] args) throws Exception { + List options = new ArrayList<>(); + for (Executor entry : executors) { + if (entry.tab.isPresent()) { + try { + options.addAll(entry.tab.get().tabComplete(sender, args)); + } catch (Exception e) { + System.err.println("Error while passing tab completion \"" + args[0] + "\" to the plugin \"" + entry.plugin.getName() + "\""); + e.printStackTrace(); + } + } + } + return options; + } + + public void registerCommands(LimboPlugin plugin, CommandExecutor executor) { + executors.add(new Executor(plugin, executor)); + } + + public void unregsiterAllCommands(LimboPlugin plugin) { + executors.removeIf(each -> each.plugin.equals(plugin)); + } + + public File getPluginFolder() { + return new File(pluginFolder.getAbsolutePath()); + } + + protected static class Executor { + public LimboPlugin plugin; + public CommandExecutor executor; + public Optional tab; + + public Executor(LimboPlugin plugin, CommandExecutor executor) { + this.plugin = plugin; + this.executor = executor; + if (executor instanceof TabCompletor) { + this.tab = Optional.of((TabCompletor) executor); + } else { + this.tab = Optional.empty(); + } + } + } + +} diff --git a/src/com/loohp/limbo/Server/ClientConnection.java b/src/com/loohp/limbo/Server/ClientConnection.java index 336eff6..f5243cc 100644 --- a/src/com/loohp/limbo/Server/ClientConnection.java +++ b/src/com/loohp/limbo/Server/ClientConnection.java @@ -11,9 +11,13 @@ import java.util.List; import java.util.Optional; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import com.loohp.limbo.DeclareCommands; import com.loohp.limbo.Limbo; +import com.loohp.limbo.Events.PlayerJoinEvent; +import com.loohp.limbo.Events.PlayerLoginEvent; +import com.loohp.limbo.Events.PlayerQuitEvent; import com.loohp.limbo.File.ServerProperties; import com.loohp.limbo.Location.Location; import com.loohp.limbo.Player.Player; @@ -73,7 +77,7 @@ public class ClientConnection extends Thread { DISCONNECTED; } - private Socket client_socket; + private final Socket client_socket; private boolean running; private ClientState state; @@ -83,15 +87,15 @@ public class ClientConnection extends Thread { protected DataOutputStream output; protected DataInputStream input; - private InetAddress iNetAddress; + private InetAddress inetAddress; public ClientConnection(Socket client_socket) { this.client_socket = client_socket; - this.iNetAddress = client_socket.getInetAddress(); + this.inetAddress = client_socket.getInetAddress(); } - public InetAddress getiNetAddress() { - return iNetAddress; + public InetAddress getInetAddress() { + return inetAddress; } public long getLastKeepAlivePayLoad() { @@ -131,14 +135,10 @@ public class ClientConnection extends Thread { DataTypeIO.writeVarInt(output, packetByte.length); output.write(packetByte); output.flush(); - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException e) {} try { client_socket.close(); - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException e) {} } public void disconnectDuringLogin(BaseComponent[] reason) { @@ -148,14 +148,10 @@ public class ClientConnection extends Thread { DataTypeIO.writeVarInt(output, packetByte.length); output.write(packetByte); output.flush(); - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException e) {} try { client_socket.close(); - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException e) {} } @Override @@ -210,7 +206,7 @@ public class ClientConnection extends Thread { String ip = data[1]; bungeeUUID = UUID.fromString(data[2].replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5")); - iNetAddress = InetAddress.getByName(ip); + inetAddress = InetAddress.getByName(ip); String skinJson = data[3]; @@ -240,7 +236,7 @@ public class ClientConnection extends Thread { state = ClientState.PLAY; - player = new Player(this, username, uuid, Limbo.getInstance().entityCount.getAndIncrement(), Limbo.getInstance().getServerProperties().getWorldSpawn()); + player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn()); Limbo.getInstance().addPlayer(player); break; @@ -248,6 +244,12 @@ public class ClientConnection extends Thread { input.skipBytes(size - DataTypeIO.getVarIntLength(packetId)); } } + + PlayerLoginEvent event = (PlayerLoginEvent) Limbo.getInstance().getEventsManager().callEvent(new PlayerLoginEvent(this, false)); + if (event.isCancelled()) { + disconnectDuringLogin(event.getCancelReason()); + } + break; } @@ -276,13 +278,6 @@ public class ClientConnection extends Thread { } } - PacketPlayOutSpawnPosition spawnPos = new PacketPlayOutSpawnPosition(BlockPosition.from(s)); - sendPacket(spawnPos); - - PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch(), 1); - player.setLocation(new Location(world, s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch())); - sendPacket(positionLook); - SkinResponse skinresponce = isBungeecord ? bungeeSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName()); PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null; PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(PlayerInfoAction.ADD_PLAYER, player.getUUID(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), Optional.ofNullable(skin), p.getDefaultGamemode(), 0, false, Optional.empty())); @@ -309,15 +304,26 @@ public class ClientConnection extends Thread { String str = client_socket.getInetAddress().getHostName() + ":" + client_socket.getPort() + "|" + player.getName(); Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!"); - PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandPacket(); - sendPacket(declare); + PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandsPacket(player); + if (declare != null) { + sendPacket(declare); + } + + Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player)); + + PacketPlayOutSpawnPosition spawnPos = new PacketPlayOutSpawnPosition(BlockPosition.from(s)); + sendPacket(spawnPos); + + PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch(), 1); + player.setLocation(new Location(world, s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch())); + sendPacket(positionLook); while (client_socket.isConnected()) { try { int size = DataTypeIO.readVarInt(input); int packetId = DataTypeIO.readVarInt(input); Class packetType = Packet.getPlayIn().get(packetId); - //System.out.println(packetType); + //System.out.println(packetId + " -> " + packetType); if (packetType == null) { input.skipBytes(size - DataTypeIO.getVarIntLength(packetId)); } else if (packetType.equals(PacketPlayInPositionAndLook.class)) { @@ -346,24 +352,13 @@ public class ClientConnection extends Thread { } } else if (packetType.equals(PacketPlayInTabComplete.class)) { PacketPlayInTabComplete request = new PacketPlayInTabComplete(input); - String[] command = CustomStringUtils.splitStringToArgs(request.getText()); - System.out.println(request.getText()); + String[] command = CustomStringUtils.splitStringToArgs(request.getText().substring(1)); + List matches = new ArrayList(); - TabCompleteMatches spawn = new TabCompleteMatches("spawn", new TextComponent(ChatColor.GOLD + "Teleports you back to the Limbo spawn!")); + matches.addAll(Limbo.getInstance().getPluginManager().getTabOptions(player, command).stream().map(each -> new TabCompleteMatches(each)).collect(Collectors.toList())); - switch (command.length) { - case 0: - matches.add(spawn); - break; - case 1: - if ("spawn".startsWith(command[0])) { - matches.add(spawn); - } - break; - } - - int start = CustomStringUtils.getIndexOfArg(request.getText(), command.length - 1); + int start = CustomStringUtils.getIndexOfArg(request.getText(), command.length - 1) + 1; int length = command[command.length - 1].length(); PacketPlayOutTabComplete response = new PacketPlayOutTabComplete(request.getId(), start, length, matches.toArray(new TabCompleteMatches[matches.size()])); @@ -371,19 +366,9 @@ public class ClientConnection extends Thread { } else if (packetType.equals(PacketPlayInChat.class)) { PacketPlayInChat chat = new PacketPlayInChat(input); if (chat.getMessage().startsWith("/")) { - //TO-DO COMMANDS - String[] command = CustomStringUtils.splitStringToArgs(chat.getMessage().substring(1)); - if (command[0].equalsIgnoreCase("spawn")) { - player.teleport(p.getWorldSpawn()); - Limbo.getInstance().getConsole().sendMessage(player.getName() + " executed server command: /spawn"); - player.sendMessage(new TextComponent(ChatColor.GOLD + "Teleporting you to spawn!")); - } + Limbo.getInstance().dispatchCommand(player, chat.getMessage()); } else { - String message = "<" + player.getName() + "> " + chat.getMessage(); - Limbo.getInstance().getConsole().sendMessage(message); - for (Player each : Limbo.getInstance().getPlayers()) { - each.sendMessage(message); - } + player.chat(chat.getMessage()); } } else { input.skipBytes(size - DataTypeIO.getVarIntLength(packetId)); @@ -393,8 +378,12 @@ public class ClientConnection extends Thread { break; } } - str = client_socket.getInetAddress().getHostName() + ":" + client_socket.getPort() + "|" + player.getName(); - Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had disconnected!"); + + Limbo.getInstance().getEventsManager().callEvent(new PlayerQuitEvent(player)); + + str = client_socket.getInetAddress().getHostName() + ":" + client_socket.getPort() + "|" + player.getName(); + Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had disconnected!"); + } } catch (Exception e) {} @@ -403,6 +392,7 @@ public class ClientConnection extends Thread { client_socket.close(); } catch (IOException e) {} state = ClientState.DISCONNECTED; + if (player != null) { Limbo.getInstance().removePlayer(player); } diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayOutTabComplete.java b/src/com/loohp/limbo/Server/Packets/PacketPlayOutTabComplete.java index 1ebf700..d0fea22 100644 --- a/src/com/loohp/limbo/Server/Packets/PacketPlayOutTabComplete.java +++ b/src/com/loohp/limbo/Server/Packets/PacketPlayOutTabComplete.java @@ -22,6 +22,7 @@ public class PacketPlayOutTabComplete extends PacketOut { this.id = id; this.start = start; this.length = length; + this.matches = matches; } public int getId() { diff --git a/src/permission.yml b/src/permission.yml new file mode 100644 index 0000000..88d2981 --- /dev/null +++ b/src/permission.yml @@ -0,0 +1,11 @@ +groups: + admin: + - limboserver.stop + - limboserver.kick + - limboserver.say + default: + - limboserver.spawn + +players: + LOOHP: + - admin \ No newline at end of file