diff --git a/src/main/java/com/loohp/limbo/Limbo.java b/src/main/java/com/loohp/limbo/Limbo.java index 38769e1..f2b2fa4 100644 --- a/src/main/java/com/loohp/limbo/Limbo.java +++ b/src/main/java/com/loohp/limbo/Limbo.java @@ -37,6 +37,7 @@ import org.json.simple.parser.ParseException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.loohp.limbo.commands.CommandSender; +import com.loohp.limbo.commands.Defaults; import com.loohp.limbo.consolegui.GUI; import com.loohp.limbo.events.EventsManager; import com.loohp.limbo.file.ServerProperties; @@ -291,14 +292,14 @@ public class Limbo { pluginFolder = new File("plugins"); pluginFolder.mkdirs(); - File defaultCommandsJar = new File(pluginFolder, "LimboDefaultCmd.jar"); - defaultCommandsJar.delete(); - console.sendMessage("Loading limbo default commands module..."); - try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("LimboDefaultCmd.jar")) { - Files.copy(in, defaultCommandsJar.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } +// File defaultCommandsJar = new File(pluginFolder, "LimboDefaultCmd.jar"); +// defaultCommandsJar.delete(); +// console.sendMessage("Loading limbo default commands module..."); +// try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("LimboDefaultCmd.jar")) { +// Files.copy(in, defaultCommandsJar.toPath()); +// } catch (IOException e) { +// e.printStackTrace(); +// } pluginManager = new PluginManager(pluginFolder); try { @@ -322,7 +323,9 @@ public class Limbo { Runtime.getRuntime().addShutdownHook(new Thread(() -> { Limbo.getInstance().terminate(); })); - + console.sendMessage("Enabling Commands"); + registerDefaultCommands(); + console.sendMessage("Default Commands Enabled"); console.run(); } @@ -412,6 +415,11 @@ public class Limbo { } } + public void registerDefaultCommands() { + LimboPlugin plug = new LimboPlugin(); + getPluginManager().registerCommands(plug, new Defaults()); + } + public ServerProperties getServerProperties() { return properties; } diff --git a/src/main/java/com/loohp/limbo/commands/Defaults.java b/src/main/java/com/loohp/limbo/commands/Defaults.java new file mode 100644 index 0000000..9bbb1cc --- /dev/null +++ b/src/main/java/com/loohp/limbo/commands/Defaults.java @@ -0,0 +1,179 @@ +package com.loohp.limbo.commands; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.loohp.limbo.Limbo; +import com.loohp.limbo.player.Player; +import com.loohp.limbo.utils.GameMode; + +import net.md_5.bungee.api.ChatColor; + +public class Defaults implements CommandExecutor, TabCompletor { + public List tabComplete(CommandSender sender, String[] args) { + List tab = new ArrayList<>(); + switch (args.length) { + case 0: + if (sender.hasPermission("limboserver.spawn")) + tab.add("spawn"); + if (sender.hasPermission("limboserver.kick")) + tab.add("kick"); + if (sender.hasPermission("limboserver.stop")) + tab.add("stop"); + if (sender.hasPermission("limboserver.say")) + tab.add("say"); + if (sender.hasPermission("limboserver.gamemode")) + tab.add("gamemode"); + break; + case 1: + if (sender.hasPermission("limboserver.spawn") && + "spawn".startsWith(args[0].toLowerCase())) + tab.add("spawn"); + if (sender.hasPermission("limboserver.kick") && + "kick".startsWith(args[0].toLowerCase())) + tab.add("kick"); + if (sender.hasPermission("limboserver.stop") && + "stop".startsWith(args[0].toLowerCase())) + tab.add("stop"); + if (sender.hasPermission("limboserver.say") && + "say".startsWith(args[0].toLowerCase())) + tab.add("say"); + if (sender.hasPermission("limboserver.gamemode") && + "gamemode".startsWith(args[0].toLowerCase())) + tab.add("gamemode"); + break; + case 2: + if (sender.hasPermission("limboserver.kick") && + args[0].equalsIgnoreCase("kick")) + for (Player player : Limbo.getInstance().getPlayers()) { + if (player.getName().toLowerCase().startsWith(args[1].toLowerCase())) + tab.add(player.getName()); + } + if (sender.hasPermission("limboserver.gamemode") && + args[0].equalsIgnoreCase("gamemode")) { + byte b; + int i; + GameMode[] arrayOfGameMode; + for (i = (arrayOfGameMode = GameMode.values()).length, b = 0; b < i; ) { + GameMode mode = arrayOfGameMode[b]; + if (mode.getName().toLowerCase().startsWith(args[1].toLowerCase())) + tab.add(mode.getName()); + b++; + } + } + break; + case 3: + if (sender.hasPermission("limboserver.gamemode") && + args[0].equalsIgnoreCase("gamemode")) + for (Player player : Limbo.getInstance().getPlayers()) { + if (player.getName().toLowerCase().startsWith(args[2].toLowerCase())) + tab.add(player.getName()); + } + break; + } + return tab; + } + + public void execute(CommandSender sender, String[] args) { + if (args.length == 0) + return; + if (args[0].equalsIgnoreCase("spawn")) { + if (sender.hasPermission("limboserver.spawn")) { + if (args.length == 1 && sender instanceof Player) { + Player player = (Player)sender; + player.teleport(Limbo.getInstance().getServerProperties().getWorldSpawn()); + player.sendMessage(ChatColor.GOLD + "Teleporting you to spawn!"); + } else if (args.length == 2) { + Player player = Limbo.getInstance().getPlayer(args[1]); + if (player != null) { + player.teleport(Limbo.getInstance().getServerProperties().getWorldSpawn()); + sender.sendMessage(ChatColor.GOLD + "Teleporting " + player.getName() + " to spawn!"); + } else { + sender.sendMessage(ChatColor.RED + "Player not found!"); + } + } else { + sender.sendMessage(ChatColor.RED + "Invalid command usage!"); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!"); + } + return; + } + if (args[0].equalsIgnoreCase("stop")) { + if (sender.hasPermission("limboserver.stop")) { + Limbo.getInstance().stopServer(); + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!"); + } + return; + } + if (args[0].equalsIgnoreCase("kick")) { + if (sender.hasPermission("limboserver.kick")) { + String reason = "Disconnected!"; + Player player = (args.length > 1) ? Limbo.getInstance().getPlayer(args[1]) : null; + if (player != null) { + if (args.length < 2) { + player.disconnect(); + } else { + reason = String.join(" ", Arrays.copyOfRange((CharSequence[])args, 2, args.length)); + player.disconnect(reason); + } + sender.sendMessage(ChatColor.RED + "Kicked the player " + args[1] + " for the reason: " + reason); + } else { + sender.sendMessage(ChatColor.RED + "Player is not online!"); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!"); + } + return; + } + if (args[0].equalsIgnoreCase("gamemode")) { + if (sender.hasPermission("limboserver.gamemode")) { + if (args.length > 1) { + Player player = (args.length > 2) ? Limbo.getInstance().getPlayer(args[2]) : ((sender instanceof Player) ? (Player)sender : null); + if (player != null) { + try { + player.setGamemode(GameMode.fromId(Integer.parseInt(args[1]))); + } catch (Exception e) { + try { + player.setGamemode(GameMode.fromName(args[1])); + } catch (Exception e1) { + sender.sendMessage(ChatColor.RED + "Invalid usage!"); + return; + } + } + sender.sendMessage(ChatColor.GOLD + "Updated gamemode to " + player.getGamemode().getName()); + } else { + sender.sendMessage(ChatColor.RED + "Player is not online!"); + } + } else { + sender.sendMessage(ChatColor.RED + "Invalid usage!"); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!"); + } + return; + } + if (args[0].equalsIgnoreCase("say")) { + if (sender.hasPermission("limboserver.say")) { + if (sender instanceof com.loohp.limbo.Console) { + if (args.length > 1) { + String message = "[Server] " + String.join(" ", Arrays.copyOfRange((CharSequence[])args, 1, args.length)); + Limbo.getInstance().getConsole().sendMessage(message); + for (Player each : Limbo.getInstance().getPlayers()) + each.sendMessage(message); + } + } else if (args.length > 1) { + String message = "[" + sender.getName() + "] " + String.join(" ", Arrays.copyOfRange((CharSequence[])args, 1, args.length)); + Limbo.getInstance().getConsole().sendMessage(message); + for (Player each : Limbo.getInstance().getPlayers()) + each.sendMessage(message); + } + } else { + sender.sendMessage(ChatColor.RED + "You do not have permission to use that command!"); + } + return; + } + } +} diff --git a/src/main/java/com/loohp/limbo/file/ServerProperties.java b/src/main/java/com/loohp/limbo/file/ServerProperties.java index c6a2828..0dcb547 100644 --- a/src/main/java/com/loohp/limbo/file/ServerProperties.java +++ b/src/main/java/com/loohp/limbo/file/ServerProperties.java @@ -55,6 +55,9 @@ public class ServerProperties { private boolean resourcePackRequired; private String resourcePackPromptJson; + private String tabHeader; + private String tabFooter; + Optional favicon; public ServerProperties(File file) throws IOException { @@ -133,6 +136,9 @@ public class ServerProperties { resourcePackRequired = Boolean.parseBoolean(prop.getProperty("required-resource-pack")); resourcePackPromptJson = prop.getProperty("resource-pack-prompt"); + tabHeader = prop.getProperty("tab-header"); + tabFooter = prop.getProperty("tab-footer"); + File png = new File("server-icon.png"); if (png.exists()) { try { @@ -268,5 +274,13 @@ public class ServerProperties { public String getResourcePackPromptJson() { return resourcePackPromptJson; } + + public String getTabHeader() { + return tabHeader; + } + + public String getTabFooter() { + return tabFooter; + } } diff --git a/src/main/java/com/loohp/limbo/player/Player.java b/src/main/java/com/loohp/limbo/player/Player.java index e24d9fe..5887273 100644 --- a/src/main/java/com/loohp/limbo/player/Player.java +++ b/src/main/java/com/loohp/limbo/player/Player.java @@ -17,6 +17,7 @@ import com.loohp.limbo.server.ClientConnection; import com.loohp.limbo.server.packets.PacketPlayOutChat; import com.loohp.limbo.server.packets.PacketPlayOutGameState; import com.loohp.limbo.server.packets.PacketPlayOutHeldItemChange; +import com.loohp.limbo.server.packets.PacketPlayOutPlayerListHeaderFooter; import com.loohp.limbo.server.packets.PacketPlayOutPositionAndLook; import com.loohp.limbo.server.packets.PacketPlayOutResourcePackSend; import com.loohp.limbo.server.packets.PacketPlayOutRespawn; @@ -282,5 +283,38 @@ public class Player extends LivingEntity implements CommandSender { e.printStackTrace(); } } + + public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { + try { + PacketPlayOutPlayerListHeaderFooter packsend = new PacketPlayOutPlayerListHeaderFooter( + ComponentSerializer.toString(header), + ComponentSerializer.toString(footer)); + clientConnection.sendPacket(packsend); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void setPlayerListHeader(BaseComponent[] header) { + try { + PacketPlayOutPlayerListHeaderFooter packsend = new PacketPlayOutPlayerListHeaderFooter( + ComponentSerializer.toString(header), + null); + clientConnection.sendPacket(packsend); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void setPlayerListFooter(BaseComponent[] footer) { + try { + PacketPlayOutPlayerListHeaderFooter packsend = new PacketPlayOutPlayerListHeaderFooter( + null, + ComponentSerializer.toString(footer)); + clientConnection.sendPacket(packsend); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/src/main/java/com/loohp/limbo/server/ClientConnection.java b/src/main/java/com/loohp/limbo/server/ClientConnection.java index 6e284f4..8a68656 100644 --- a/src/main/java/com/loohp/limbo/server/ClientConnection.java +++ b/src/main/java/com/loohp/limbo/server/ClientConnection.java @@ -421,6 +421,8 @@ public class ClientConnection extends Thread { sendPacket(state); } + // RESOURCEPACK CODE ADDED BY GAMERDUCK123 + if (properties.getResourcePackLink() != null && !properties.getResourcePackLink().equalsIgnoreCase("")) { if (properties.getResourcePackSHA1() != null && !properties.getResourcePackSHA1().equalsIgnoreCase("")) { //SEND RESOURCEPACK @@ -434,6 +436,20 @@ public class ClientConnection extends Thread { } else { //RESOURCEPACK NOT ENABLED } + + // PLAYER LIST HEADER AND FOOTER CODE ADDED BY GAMERDUCK123 + // Sadly due to the limitations of minecraft (?) I cannot get the footer to work alone, it needs a header to have a footer, BUT + // You can have just a header with no footer (which is weird!) + String tabHeader = ""; + String tabFooter = ""; + if (properties.getTabHeader() != null && !properties.getTabHeader().equalsIgnoreCase("")) { + tabHeader = properties.getTabHeader(); + } + if (properties.getTabFooter() != null && !properties.getTabFooter().equalsIgnoreCase("")) { + tabFooter = properties.getTabFooter(); + } + player.setPlayerListHeaderFooter(ComponentSerializer.parse(tabHeader), + ComponentSerializer.parse(tabFooter)); ready = true; diff --git a/src/main/java/com/loohp/limbo/server/packets/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/com/loohp/limbo/server/packets/PacketPlayOutPlayerListHeaderFooter.java new file mode 100644 index 0000000..76c4e91 --- /dev/null +++ b/src/main/java/com/loohp/limbo/server/packets/PacketPlayOutPlayerListHeaderFooter.java @@ -0,0 +1,40 @@ +package com.loohp.limbo.server.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import com.loohp.limbo.utils.DataTypeIO; + +public class PacketPlayOutPlayerListHeaderFooter extends PacketOut{ + + private String header; + private String footer; + + public PacketPlayOutPlayerListHeaderFooter(String header, String footer) { + this.header = header; + this.footer = footer; + } + + public String getHeader() { + return header; + } + + public String getFooter() { + return footer; + } + + + @Override + public byte[] serializePacket() throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + DataOutputStream output = new DataOutputStream(buffer); + output.writeByte(Packet.getPlayOut().get(getClass())); + DataTypeIO.writeString(output, header, StandardCharsets.UTF_8); + DataTypeIO.writeString(output, footer, StandardCharsets.UTF_8); + return buffer.toByteArray(); + } + +} diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index 6dde965..8b59b8f 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -45,6 +45,7 @@ "PacketPlayOutSpawnEntity": "0x00", "PacketPlayOutSpawnEntityLiving": "0x02", "PacketPlayOutHeldItemChange": "0x48", + "PacketPlayOutPlayerListHeaderFooter": "0x5E", "PacketPlayOutResourcePackSend": "0x3C" }, "StatusIn": { diff --git a/src/main/resources/server.properties b/src/main/resources/server.properties index 9b0c5d6..00b36e7 100644 --- a/src/main/resources/server.properties +++ b/src/main/resources/server.properties @@ -59,6 +59,12 @@ motd={"text":"","extra":[{"text":"Limbo Server!","color":"yellow"}]} #Server list version as string version=Limbo! +#Tab-List Header (May be left blank) +tab-header= + +#Tab-List Footer (May be left blank) +tab-footer= + #Server resource pack url (May be left blank) resource-pack=