more commands, fixes

This commit is contained in:
Sen 2025-06-10 10:56:55 +02:00
parent e7aab16773
commit e625ead56d
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
11 changed files with 208 additions and 186 deletions

View file

@ -75,6 +75,8 @@ import proxy.handler.HandshakeHandler;
import proxy.handler.ProxyHandler;
import proxy.handler.Handler.ThreadQuickExitException;
import proxy.network.Connection;
import proxy.packet.C01PacketChatMessage;
import proxy.packet.S02PacketChat;
import proxy.packet.S38PacketPlayerListItem;
import proxy.packet.S38PacketPlayerListItem.Action;
import proxy.packet.S40PacketDisconnect;
@ -322,8 +324,7 @@ public class Proxy {
final String cmd = line;
Proxy.this.schedule(new Runnable() {
public void run() {
String msg = Formatter.filterSpaces(cmd);
Proxy.this.runCommand(null, msg.isEmpty() ? new String[] {"phelp"} : msg.split(" "), msg);
Proxy.this.run(null, cmd);
}
});
}
@ -629,9 +630,39 @@ public class Proxy {
this.register(new CommandSave());
this.register(new CommandSeed());
for(String cmd : new String[] {"?", "about", "ban", "ban-ip", "banlist", "icanhasbukkit", "me", "pardon", "pardon-ip", "pl", "plugins", "restart", "rl", "say", "scoreboard", "stop", "tell", "tellraw", "timings", "title", "toggledownfall", "trigger", "ver", "version", "whitelist", "clone", "debug", "fill", "testfor", "testforblock", "testforblocks", "setidletimeout", "stats", "save-off", "save-on", "save-all"}) {
for(String cmd : new String[] {"?", "about", "ban", "ban-ip", "banlist", "icanhasbukkit", "me", "pardon", "pardon-ip", "pl", "plugins", "restart", "rl", "say", "scoreboard", "stop", "tell", "tellraw", "timings", "title", "toggledownfall", "trigger", "ver", "version", "whitelist", "clone", "debug", "fill", "testfor", "testforblock", "testforblocks", "setidletimeout", "stats", "save-off", "save-on", "save-all", "spreadplayers"}) {
this.register(new CommandDummy(cmd));
}
this.register(new CommandPass("achievement", "<give|take> <stat_name|*> [player]", "Gives takes achievements to players or takes them"));
this.register(new CommandPass("blockdata", "<x> <y> <z> <dataTag>", "Sets data of a tile entity"));
this.register(new CommandPass("clear", "[player] [item] [data] [maxCount] [dataTag]", "Clears items in the inventory of a player"));
this.register(new CommandPass("defaultgamemode", "<mode>", "Sets the default game mode of the server"));
this.register(new CommandPass("deop", "<player>", "Removes a player from the operator list"));
this.register(new CommandPass("difficulty", "<new difficulty>", "Sets the difficulty of the server"));
this.register(new CommandPass("effect", "<player> <effect> [seconds] [amplifier] [hideParticles] OR /effect <player> clear", "Gives entities status effects or removes them"));
this.register(new CommandPass("enchant", "<player> <enchantment ID> [level]", "Enchants the item in the hand of a player"));
this.register(new CommandPass("entitydata", "<entity> <dataTag>", "Sets data of an entity"));
this.register(new CommandPass("execute", "<entity> <x> <y> <z> <command> OR /execute <entity> <x> <y> <z> detect <x> <y> <z> <block> <data> <command>", "Runs a command as another entity"));
this.register(new CommandPass("gamemode", "<mode> [player]", "Sets the gamemode of a player"));
this.register(new CommandPass("gamerule", "<rule name> [value]", "Sets a gamerule of the server"));
this.register(new CommandPass("give", "<player> <item> [amount] [data] [dataTag]", "Gives an item to a player"));
this.register(new CommandPass("kill", "[player|entity]", "Kills entities"));
this.register(new CommandPass("op", "<player>", "Adds a player to the operator list"));
this.register(new CommandPass("particle", "<name> <x> <y> <z> <xd> <yd> <zd> <speed> [count] [mode]", "Displays particle effects to players"));
this.register(new CommandPass("playsound", "<sound> <player> [x] [y] [z] [volume] [pitch] [minimumVolume]", "Plays sound effects to players"));
this.register(new CommandPass("replaceitem", "<entity|block> ...", "Replaces an item in the inventory of an entity"));
this.register(new CommandPass("setblock", "<x> <y> <z> <TileName> [dataValue] [oldBlockHandling] [dataTag]", "Sets a block in the world"));
this.register(new CommandPass("setworldspawn", "[<x> <y> <z>]", "Sets the spawn point of the world"));
this.register(new CommandPass("spawnpoint", "[player] [<x> <y> <z>]", "Sets the spawn point of a player"));
this.register(new CommandPass("summon", "<EntityName> [x] [y] [z] [dataTag]", "Creates a new entity"));
this.register(new CommandPass("time", "<set|add|query> <value>", "Sets the time of the world or displays it"));
this.register(new CommandPass("tp", "[target player] <destination player> OR /tp [target player] <x> <y> <z> [<y-rot> <x-rot>]", "Teleports entities to antother entity or a position"));
this.register(new CommandPass("weather", "<clear|rain|thunder> [duration in seconds]", "Changes the current weather of the world"));
this.register(new CommandPass("worldborder", "<set|center|damage|warning|get|add> ...", "Sets parameters of the world border"));
this.register(new CommandPass("xp", "<amount> [player] OR /xp <amount>L [player]", "Gives experience to player or takes it"));
this.register(new CommandPass("tps", null, "Displays the current ticks per second of the server"));
}
public Map<String, Command> getCommands() {
@ -666,7 +697,7 @@ public class Proxy {
this.running = false;
}
public boolean runCommand(ProxyHandler player, String[] args, String line) {
private boolean runCommand(ProxyHandler player, String[] args, String line) {
if(args.length == 0)
return false;
Command cmd = this.commands.get(args[0].toLowerCase(Locale.US));
@ -711,4 +742,82 @@ public class Proxy {
}
return true;
}
public void run(ProxyHandler player, String line) {
String msg = Formatter.filterSpaces(line);
if(msg.isEmpty())
return;
if(msg.startsWith("/")) {
msg = msg.substring(1);
String[] args = msg.split(" ");
if(args[0].indexOf(':') != -1) {
if(player != null)
player.sendToServer(new C01PacketChatMessage("/"));
return;
}
if(!this.runCommand(player, args, msg) && player != null)
player.sendToServer(new C01PacketChatMessage(line));
}
else {
msg = String.format(Formatter.BLUE + "%s" + Formatter.DARK_GRAY + ": " + Formatter.GRAY + "%s", player != null ? player.getUsername() : "#CONSOLE#", line);
this.sendPacket(new S02PacketChat(msg, false));
Log.info(Formatter.strip(msg));
}
}
private List<String> getCompletions(ProxyHandler player, String[] args, String[] serverMatches) {
if(args.length <= 1)
return null;
Command cmd = this.commands.get(args[0].toLowerCase(Locale.US));
if(cmd == null)
return null;
List<String> list = Lists.<String>newArrayList();
if(!cmd.canUse(player))
return list;
String[] argv = new String[args.length - 1];
System.arraycopy(args, 1, argv, 0, argv.length);
Iterable<String> comps = cmd.complete(this, player, argv, serverMatches);
if(comps == null)
return list;
String param = args[args.length - 1];
for(String comp : comps) {
if(comp.regionMatches(true, 0, param, 0, param.length()))
list.add(comp);
}
return list;
}
public List<String> complete(ProxyHandler player, String completion, String[] serverMatches) {
List<String> list = null;
if(completion.startsWith("/")) {
if(completion.indexOf(' ') == -1) {
list = completion.indexOf(':') != -1 ? Lists.newArrayList() : Lists.newArrayList(serverMatches);
for(Iterator<String> iter = list.iterator(); iter.hasNext();) {
String cmd = iter.next();
if(cmd.isEmpty() || cmd.indexOf(':') != -1 || this.commands.containsKey(cmd.substring(1).toLowerCase(Locale.US)))
iter.remove();
}
for(Command cmd : this.commands.values()) {
String command = "/" + cmd.getName();
if(cmd.canUse(player) && command.regionMatches(true, 0, completion, 0, completion.length()))
list.add(command);
}
Collections.sort(list);
}
else {
String[] args = completion.substring(1).split(" ", -1);
list = args[0].indexOf(':') != -1 ? Lists.newArrayList() : this.getCompletions(player, args, serverMatches);
}
}
else {
String[] args = completion.split(" ", -1);
String param = args[args.length - 1];
list = Lists.newArrayList();
for(ProxyHandler plr : this.players.values()) {
if(plr.getUsername().regionMatches(true, 0, param, 0, param.length()))
list.add(plr.getUsername());
}
}
return list;
}
}

View file

@ -12,7 +12,7 @@ public abstract class Command {
return null;
}
public abstract void run(Proxy proxy, ProxyHandler player, String[] args);
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return null;
}
public int getRedactedLogArg(int args) {

View file

@ -47,7 +47,7 @@ public class CommandAdmin extends Command {
sendInfo(player, "%s is now an admin", user.getUsername());
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return args.length == 1 ? Collections2.filter(proxy.getUserNames(), user -> !proxy.getUser(user).isAdmin()) : null;
}
}

View file

@ -33,7 +33,7 @@ public class CommandDelete extends Command {
sendInfo(player, "The profile of %s was deleted", user.getUsername());
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return args.length == 1 ? (player == null ? proxy.getUserNames() : Collections2.filter(proxy.getUserNames(), user -> !proxy.getUser(user).isAdmin())) : null;
}
}

View file

@ -10,11 +10,11 @@ import proxy.util.Formatter;
public class CommandHelp extends Command {
public String getName() {
return "phelp";
return "help";
}
public String getHelp() {
return "Displays proxy command help";
return "Displays proxy and server command help";
}
public String getArgs() {
@ -43,7 +43,7 @@ public class CommandHelp extends Command {
sendMessage(player, formatCommand(cmd, player != null));
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return args.length == 1 ? Collections2.filter(proxy.getCommands().keySet(), name -> proxy.getCommands().get(name).canUse(player)) : null;
}
}

View file

@ -32,7 +32,7 @@ public class CommandKick extends Command {
plr.disconnect(args.length <= 1 ? "Kicked from server" : Formatter.joinSpace(1, args));
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return args.length == 1 ? (player == null ? proxy.getPlayerNames() : Collections2.filter(proxy.getPlayerNames(), name -> !proxy.getPlayer(name).isAdmin())) : null;
}
}

View file

@ -0,0 +1,44 @@
package proxy.command;
import com.google.common.collect.Lists;
import proxy.Proxy;
import proxy.handler.ProxyHandler;
import proxy.packet.C01PacketChatMessage;
import proxy.util.Formatter;
public class CommandPass extends Command {
private final String name;
private final String args;
private final String help;
public CommandPass(String name, String args, String help) {
this.name = name;
this.args = args;
this.help = help;
}
public String getName() {
return this.name;
}
public String getArgs() {
return this.args;
}
public String getHelp() {
return this.help;
}
public boolean canUse(ProxyHandler player) {
return player != null && super.canUse(player);
}
public void run(Proxy proxy, ProxyHandler player, String[] args) {
player.sendToServer(new C01PacketChatMessage("/" + this.name + (args.length != 0 ? " " + Formatter.joinSpace(0, args) : "")));
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return Lists.newArrayList(serverMatches);
}
}

View file

@ -28,7 +28,7 @@ public class CommandPing extends Command {
sendInfo(player, (plr == player ? "Your latency" : "Latency of %s") + ": %d ms", plr == player ? plr.getPing() : plr.getUsername(), plr.getPing());
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return args.length == 1 && (player == null || player.hasPermission(Permissions.PING_OTHERS)) ? proxy.getPlayerNames() : null;
}
}

View file

@ -38,7 +38,7 @@ public class CommandRevoke extends Command {
sendInfo(player, "%s is no longer an admin", user.getUsername());
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args, String[] serverMatches) {
return args.length == 1 ? Collections2.filter(proxy.getUserNames(), user -> proxy.getUser(user).isAdmin()) : null;
}
}

View file

@ -1,21 +1,16 @@
package proxy.handler;
import io.netty.buffer.Unpooled;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import java.net.IDN;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.collect.Lists;
import proxy.Proxy;
import proxy.command.Command;
import proxy.network.Connection;
import proxy.network.Packet;
import proxy.network.PacketBuffer;
@ -142,10 +137,11 @@ public class ProxyHandler extends User implements Handler {
public void setupPlayer(int id) {
this.spoofedId = id;
this.sendToClient(new S01PacketJoinGame(id, true));
this.sendToClient(new S3FPacketCustomPayload("MC|Brand", (new PacketBuffer(Unpooled.buffer())).writeString(Proxy.NAME)));
this.sendToClient(new S03PacketTimeUpdate(3000L, false));
this.sendToClient(new S26PacketMapChunkBulk(0, 64, 0));
this.sendToClient(new S08PacketPlayerPosLook(0.5, 65.0, 0.5, 0.0f, 0.0f));
this.sendMessage(Formatter.DARK_PURPLE + "Welcome %s, please log in using the sign gui ...", this.username);
// this.sendMessage(Formatter.DARK_PURPLE + "Welcome %s, please log in using the sign gui ...", this.username);
}
public void sendMessage(String message) {
@ -382,59 +378,23 @@ public class ProxyHandler extends User implements Handler {
this.sendToServer(packetIn);
}
public List<String> getCompletions(String[] args) {
if(args.length <= 1)
return null;
Command cmd = this.proxy.getCommands().get(args[0].toLowerCase(Locale.US));
if(cmd == null)
return null;
List<String> list = Lists.<String>newArrayList();
if(!cmd.canUse(this))
return list;
String[] argv = new String[args.length - 1];
System.arraycopy(args, 1, argv, 0, argv.length);
Iterable<String> comps = cmd.complete(this.proxy, this, argv);
if(comps == null)
return list;
String param = args[args.length - 1];
for(String comp : comps) {
if(comp.regionMatches(true, 0, param, 0, param.length()))
list.add(comp);
}
return list;
}
public void processChatMessage(C01PacketChatMessage packetIn) {
if(this.connected) {
Handler.syncToMain(packetIn, this, this.proxy);
String msg = packetIn.getMessage();
if(!isValidString(msg))
return;
msg = Formatter.filterSpaces(msg);
if(msg.isEmpty())
return;
if(msg.startsWith("/")) {
msg = msg.substring(1);
String[] args = msg.split(" ");
if(args[0].indexOf(':') != -1) {
this.sendToServer(new C01PacketChatMessage("/"));
return;
}
if(!this.proxy.runCommand(this, args, msg))
this.sendToServer(packetIn);
}
else {
msg = String.format(Formatter.BLUE + "%s" + Formatter.DARK_GRAY + ": " + Formatter.GRAY + "%s", this.username, packetIn.getMessage());
this.proxy.sendPacket(new S02PacketChat(msg, false));
Log.info(Formatter.strip(msg));
}
this.proxy.run(this, msg);
}
}
public void processTabComplete(C14PacketTabComplete packetIn) {
if(this.connected) {
Handler.syncToMain(packetIn, this, this.proxy);
this.completion = packetIn.getMessage();
String msg = packetIn.getMessage();
if(!isValidString(msg))
return;
this.completion = msg;
this.sendToServer(packetIn);
}
}
@ -445,36 +405,7 @@ public class ProxyHandler extends User implements Handler {
this.sendToClient(new S3APacketTabComplete(new String[0]));
return;
}
List<String> list = null;
if(this.completion.startsWith("/")) {
if(this.completion.indexOf(' ') == -1) {
list = this.completion.indexOf(':') != -1 ? Lists.newArrayList() : Lists.newArrayList(packetIn.getMatches());
for(Iterator<String> iter = list.iterator(); iter.hasNext();) {
String cmd = iter.next();
if(cmd.isEmpty() || cmd.indexOf(':') != -1 || this.proxy.getCommands().containsKey(cmd.substring(1).toLowerCase(Locale.US)))
iter.remove();
}
for(Command cmd : this.proxy.getCommands().values()) {
String command = "/" + cmd.getName();
if(cmd.canUse(this) && command.regionMatches(true, 0, this.completion, 0, this.completion.length()))
list.add(command);
}
Collections.sort(list);
}
else {
String[] args = this.completion.substring(1).split(" ", -1);
list = args[0].indexOf(':') != -1 ? Lists.newArrayList() : this.getCompletions(args);
}
}
else {
String[] args = this.completion.split(" ", -1);
String param = args[args.length - 1];
list = Lists.newArrayList();
for(ProxyHandler player : this.proxy.getPlayers()) {
if(player.getUsername().regionMatches(true, 0, param, 0, param.length()))
list.add(player.getUsername());
}
}
List<String> list = this.proxy.complete(this, this.completion, packetIn.getMatches());
this.sendToClient(list != null ? new S3APacketTabComplete(list.toArray(new String[list.size()])) : packetIn);
this.completion = null;
}
@ -587,8 +518,6 @@ public class ProxyHandler extends User implements Handler {
finally {
packetbuffer.release();
}
return;
}
else if("MC|BSign".equals(packetIn.getChannelName())) {
PacketBuffer packetbuffer = packetIn.getBufferData();
@ -610,8 +539,6 @@ public class ProxyHandler extends User implements Handler {
finally {
packetbuffer.release();
}
return;
}
else if("MC|TrSel".equals(packetIn.getChannelName())) {
PacketBuffer packetbuffer = packetIn.getBufferData();
@ -897,10 +824,6 @@ public class ProxyHandler extends User implements Handler {
this.sendToClient(packetIn);
}
public void handleTitle(S45PacketTitle packetIn) {
this.sendToClient(packetIn);
}
public void handleRemoveEntityEffect(S1EPacketRemoveEntityEffect packetIn) {
this.sendToClient(packetIn.replaceEntityId(this.realId, this.spoofedId));
}
@ -918,7 +841,8 @@ public class ProxyHandler extends User implements Handler {
}
public void handleCustomPayload(S3FPacketCustomPayload packetIn) {
this.sendToClient(packetIn);
if("MC|TrList".equals(packetIn.getChannelName()) || "MC|BOpen".equals(packetIn.getChannelName()))
this.sendToClient(packetIn);
}
public void handleParticles(S2APacketParticles packetIn) {

View file

@ -6,94 +6,39 @@ import proxy.handler.ProxyHandler;
import proxy.network.Packet;
import proxy.network.PacketBuffer;
public class S45PacketTitle implements Packet<ProxyHandler>
{
private S45PacketTitle.Type type;
private String message;
private int fadeInTime;
private int displayTime;
private int fadeOutTime;
public class S45PacketTitle implements Packet<ProxyHandler> {
private static enum Type {
TITLE, SUBTITLE, TIMES, CLEAR, RESET;
}
/**
* Reads the raw packet data from the data stream.
*/
public void readPacketData(PacketBuffer buf) throws IOException
{
this.type = (S45PacketTitle.Type)buf.readEnumValue(S45PacketTitle.Type.class);
private Type type;
private String message;
private int fadeInTime;
private int displayTime;
private int fadeOutTime;
if (this.type == S45PacketTitle.Type.TITLE || this.type == S45PacketTitle.Type.SUBTITLE)
{
this.message = buf.readChatComponent();
}
public void readPacketData(PacketBuffer buf) throws IOException {
this.type = buf.readEnumValue(Type.class);
if(this.type == Type.TITLE || this.type == Type.SUBTITLE)
this.message = buf.readChatComponent();
else if(this.type == Type.TIMES) {
this.fadeInTime = buf.readInt();
this.displayTime = buf.readInt();
this.fadeOutTime = buf.readInt();
}
}
if (this.type == S45PacketTitle.Type.TIMES)
{
this.fadeInTime = buf.readInt();
this.displayTime = buf.readInt();
this.fadeOutTime = buf.readInt();
}
}
public void writePacketData(PacketBuffer buf) throws IOException {
buf.writeEnumValue(this.type);
if(this.type == Type.TITLE || this.type == Type.SUBTITLE)
buf.writeChatComponent(this.message);
else if(this.type == Type.TIMES) {
buf.writeInt(this.fadeInTime);
buf.writeInt(this.displayTime);
buf.writeInt(this.fadeOutTime);
}
}
/**
* Writes the raw packet data to the data stream.
*/
public void writePacketData(PacketBuffer buf) throws IOException
{
buf.writeEnumValue(this.type);
if (this.type == S45PacketTitle.Type.TITLE || this.type == S45PacketTitle.Type.SUBTITLE)
{
buf.writeChatComponent(this.message);
}
if (this.type == S45PacketTitle.Type.TIMES)
{
buf.writeInt(this.fadeInTime);
buf.writeInt(this.displayTime);
buf.writeInt(this.fadeOutTime);
}
}
/**
* Passes this Packet on to the NetHandler for processing.
*/
public void processPacket(ProxyHandler handler)
{
handler.handleTitle(this);
}
public static enum Type
{
TITLE,
SUBTITLE,
TIMES,
CLEAR,
RESET;
public static S45PacketTitle.Type byName(String name)
{
for (S45PacketTitle.Type s45packettitle$type : values())
{
if (s45packettitle$type.name().equalsIgnoreCase(name))
{
return s45packettitle$type;
}
}
return TITLE;
}
public static String[] getNames()
{
String[] astring = new String[values().length];
int i = 0;
for (S45PacketTitle.Type s45packettitle$type : values())
{
astring[i++] = s45packettitle$type.name().toLowerCase();
}
return astring;
}
}
public void processPacket(ProxyHandler handler) {
}
}