more commands, config loading

This commit is contained in:
Sen 2025-06-09 19:38:41 +02:00
parent 29e9ab8cb8
commit e7aab16773
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
14 changed files with 324 additions and 30 deletions

View file

@ -29,5 +29,5 @@ application {
tasks.shadowJar { tasks.shadowJar {
destinationDirectory = rootProject.file("dev") destinationDirectory = rootProject.file("dev")
archiveFileName = "vloginproxy.jar" archiveFileName = "vproxy.jar"
} }

View file

@ -28,6 +28,8 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.IDN; import java.net.IDN;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Collection; import java.util.Collection;
@ -36,6 +38,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue; import java.util.Queue;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -76,9 +79,11 @@ import proxy.packet.S38PacketPlayerListItem;
import proxy.packet.S38PacketPlayerListItem.Action; import proxy.packet.S38PacketPlayerListItem.Action;
import proxy.packet.S40PacketDisconnect; import proxy.packet.S40PacketDisconnect;
import proxy.packet.ServerInfo; import proxy.packet.ServerInfo;
import proxy.util.Config;
import proxy.util.Formatter; import proxy.util.Formatter;
import proxy.util.User; import proxy.util.User;
import proxy.util.Log; import proxy.util.Log;
import proxy.util.Option;
public class Proxy { public class Proxy {
public static final String NAME = "VProxy"; public static final String NAME = "VProxy";
@ -99,6 +104,7 @@ public class Proxy {
private volatile boolean isAlive; private volatile boolean isAlive;
private volatile boolean running = true; private volatile boolean running = true;
private final Map<String, Option> options = Maps.newTreeMap();
private final List<ChannelFuture> endpoints = Collections.<ChannelFuture>synchronizedList(Lists.newArrayList()); private final List<ChannelFuture> endpoints = Collections.<ChannelFuture>synchronizedList(Lists.newArrayList());
private final List<Connection> networkManagers = Collections.<Connection>synchronizedList(Lists.newArrayList()); private final List<Connection> networkManagers = Collections.<Connection>synchronizedList(Lists.newArrayList());
private final Queue<FutureTask<?>> futureTaskQueue = Queues.<FutureTask<?>>newArrayDeque(); private final Queue<FutureTask<?>> futureTaskQueue = Queues.<FutureTask<?>>newArrayDeque();
@ -106,24 +112,43 @@ public class Proxy {
private final Map<String, ProxyHandler> players = Maps.newTreeMap(); private final Map<String, ProxyHandler> players = Maps.newTreeMap();
private final Map<String, Command> commands = Maps.newTreeMap(); private final Map<String, Command> commands = Maps.newTreeMap();
private final Thread serverThread; private final Thread serverThread;
private final ServerInfo status = new ServerInfo(NAME + " 1.8.9", 47);
@Config
private int compression = -1; private int compression = -1;
@Config
private boolean epoll = true; private boolean epoll = true;
@Config
private boolean register = true; private boolean register = true;
@Config
private boolean checkCase = true; private boolean checkCase = true;
@Config
private boolean kickOnConnect = true; private boolean kickOnConnect = true;
@Config
private String forwardHost = "127.0.0.1"; private String forwardHost = "127.0.0.1";
@Config
private int forwardPort = 25563; private int forwardPort = 25563;
@Config
private String proxyHost = ""; private String proxyHost = "";
@Config
private int proxyPort = 25564; private int proxyPort = 25564;
@Config
private int minPassLength = 8; private int minPassLength = 8;
@Config
private int maxAttempts = 5; private int maxAttempts = 5;
@Config
private int maxPlayers = 64; private int maxPlayers = 64;
@Config
private int pingInterval = 5; private int pingInterval = 5;
@Config
private String defaultSkinTexture = "ewogICJ0aW1lc3RhbXAiIDogMTc0OTEyOTgyODQ2MCwKICAicHJvZmlsZUlkIiA6ICJlYjcxMWNlYmNjMWM0ZGQwYTc5MmE3ZGM2Y2Q3NzcyZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJTZW5qaXVuIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzk5ZGMxYmU3ODQ1N2ViODk3Zjk3MTYxYzZjYTEyOTFlMjkxN2IzYzI4ZWIzMTc4OGY3MGEzYWY4ZGIwMGEyN2IiCiAgICB9CiAgfQp9"; private String defaultSkinTexture = "ewogICJ0aW1lc3RhbXAiIDogMTc0OTEyOTgyODQ2MCwKICAicHJvZmlsZUlkIiA6ICJlYjcxMWNlYmNjMWM0ZGQwYTc5MmE3ZGM2Y2Q3NzcyZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJTZW5qaXVuIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzk5ZGMxYmU3ODQ1N2ViODk3Zjk3MTYxYzZjYTEyOTFlMjkxN2IzYzI4ZWIzMTc4OGY3MGEzYWY4ZGIwMGEyN2IiCiAgICB9CiAgfQp9";
@Config
private String defaultSkinSignature = "uX4TdWeMU7nQZp4ZZY5d4GUOg3e+KzgndM3UhcQHZuxpfJqg5l9vZ6KmHpYpUf5hZqEzTLxWefhxLpurm3nd2kzL51GVHMQuquiISqXXGBY33bfCJtl0iVijKhAuvVWrwvBZo5tI/zCz3OQBEdW+DkNAfX7ZXntrl+0JWqhxg2+suzL4pnW7ye45/p4rVhiZ4pU/n0jTF8q6Jv6Rx4L8AoemsQ4MWmC/J5rT24gUD6DuuAc06KjUJy9g1gHNwVJ5uUjzaJ/li6as22Io09B0MdyVe5ryO9WbRKriUComNDWp/YdQrpp/hZThSNTAeJphAS5+YslRod/ZJPknrgx1yLauYaYDoHaVfQx9ZZGvJFOO+tIPQGBIefO1W3QgBqz+hdgFwsevtcqsewcdT/1khAAA2nESahOX5OuVZZhphmbfcUXK4FPn2H4jqcquP5VcsEpq3+IgE/+Nt8qFi4uANB6of/bPDWP/oDzISvtFVj/Odh+kZ/Y+OEYxn9ALYiVz5QF5gww2mtwiOh5/P9kJNc88ZrLgtnf/PggLDr6rET6L2t9DN2biwbm8NlMEB0oMa3wF/E166HRgXsxvTGvYxod1L4c70uaiyU/FlA0fL+K03bxIKYRuH7yht2E2MnzxeuPDIU/26DUG56Ek00eYdHVk9NuyUEX/96uMCArjpZ0="; private String defaultSkinSignature = "uX4TdWeMU7nQZp4ZZY5d4GUOg3e+KzgndM3UhcQHZuxpfJqg5l9vZ6KmHpYpUf5hZqEzTLxWefhxLpurm3nd2kzL51GVHMQuquiISqXXGBY33bfCJtl0iVijKhAuvVWrwvBZo5tI/zCz3OQBEdW+DkNAfX7ZXntrl+0JWqhxg2+suzL4pnW7ye45/p4rVhiZ4pU/n0jTF8q6Jv6Rx4L8AoemsQ4MWmC/J5rT24gUD6DuuAc06KjUJy9g1gHNwVJ5uUjzaJ/li6as22Io09B0MdyVe5ryO9WbRKriUComNDWp/YdQrpp/hZThSNTAeJphAS5+YslRod/ZJPknrgx1yLauYaYDoHaVfQx9ZZGvJFOO+tIPQGBIefO1W3QgBqz+hdgFwsevtcqsewcdT/1khAAA2nESahOX5OuVZZhphmbfcUXK4FPn2H4jqcquP5VcsEpq3+IgE/+Nt8qFi4uANB6of/bPDWP/oDzISvtFVj/Odh+kZ/Y+OEYxn9ALYiVz5QF5gww2mtwiOh5/P9kJNc88ZrLgtnf/PggLDr6rET6L2t9DN2biwbm8NlMEB0oMa3wF/E166HRgXsxvTGvYxod1L4c70uaiyU/FlA0fL+K03bxIKYRuH7yht2E2MnzxeuPDIU/26DUG56Ek00eYdHVk9NuyUEX/96uMCArjpZ0=";
@Config
private String[] motds = new String[0];
@Config
private String[] info = new String[0];
private ServerInfo status;
private long lastPingSync; private long lastPingSync;
private static String getIcon(File file) { private static String getIcon(File file) {
@ -160,6 +185,14 @@ public class Proxy {
public Proxy() { public Proxy() {
this.serverThread = Thread.currentThread(); this.serverThread = Thread.currentThread();
this.isAlive = true; this.isAlive = true;
for(Field field : Proxy.class.getDeclaredFields()) {
if(field.isAnnotationPresent(Config.class)) {
field.setAccessible(true);
if(Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers()))
throw new IllegalArgumentException(field.getName() + ": is static or final");
this.options.put(field.getName(), new Option(field, this));
}
}
this.registerCommands(); this.registerCommands();
} }
@ -189,28 +222,40 @@ public class Proxy {
return elem.getAsJsonObject(); return elem.getAsJsonObject();
} }
private void loadConfig() { public void loadConfig() {
JsonObject obj = loadFile(new File("vproxy.json")); JsonObject obj = loadFile(new File("vproxy.json"));
// ...
obj = loadFile(new File("users.json")); for(Entry<String, JsonElement> entry : obj.entrySet()) {
if(!this.options.containsKey(entry.getKey()))
continue;
if(!this.options.get(entry.getKey()).set(entry.getValue()))
Log.warn("Could not set option %s", entry.getKey());
}
this.status.setCapacity(this.maxPlayers);
this.status.getMotds().clear();
this.status.getIcons().clear();
this.status.getList().clear();
Collections.addAll(this.status.getMotds(), this.motds);
Collections.addAll(this.status.getList(), this.info);
File[] icons = new File("icons").listFiles(file -> file.isFile() && file.getName().endsWith(".png"));
if(icons != null) {
for(File file : icons) {
String icon = getIcon(file);
if(file != null)
this.status.getIcons().add(icon);
}
}
}
private void loadUsers() {
JsonObject obj = loadFile(new File("users.json"));
if(obj.has("users") && obj.get("users").isJsonArray()) { if(obj.has("users") && obj.get("users").isJsonArray()) {
for(User user : User.fromJson(obj.get("users").getAsJsonArray())) { for(User user : User.fromJson(obj.get("users").getAsJsonArray())) {
this.users.put(user.getUsername().toLowerCase(Locale.US), user); this.users.put(user.getUsername().toLowerCase(Locale.US), user);
} }
} }
// ... // ...
this.status = new ServerInfo(NAME + " 1.8.9", 47);
this.status.setCapacity(this.maxPlayers);
Collections.addAll(this.status.getMotds(), Formatter.DARK_RED + "Miau\n" + Formatter.YELLOW + "Test??", Formatter.AQUA + "Server\n" + Formatter.GREEN + "Test!!");
String icon = getIcon(new File("icon1.png"));
if(icon != null)
this.status.getIcons().add(icon);
icon = getIcon(new File("icon2.png"));
if(icon != null)
this.status.getIcons().add(icon);
Collections.addAll(this.status.getList(), Formatter.DARK_GREEN + "TESTTTT", "Test 2!", Formatter.BLUE + "Test numbah 3!!!!!");
} }
private static void saveFile(JsonObject obj, File file) { private static void saveFile(JsonObject obj, File file) {
@ -229,7 +274,11 @@ public class Proxy {
public void saveConfig() { public void saveConfig() {
JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
// ...
for(Entry<String, Option> entry : this.options.entrySet()) {
obj.add(entry.getKey(), entry.getValue().get());
}
saveFile(obj, new File("vproxy.json")); saveFile(obj, new File("vproxy.json"));
} }
@ -242,6 +291,7 @@ public class Proxy {
public void run() { public void run() {
this.loadConfig(); this.loadConfig();
this.loadUsers();
Log.info("Hosting proxy on %s:%d", this.proxyHost.isEmpty() ? "0.0.0.0" : this.proxyHost, this.proxyPort); Log.info("Hosting proxy on %s:%d", this.proxyHost.isEmpty() ? "0.0.0.0" : this.proxyHost, this.proxyPort);
try { try {
this.addLanEndpoint(this.proxyHost.isEmpty() ? null : InetAddress.getByName(IDN.toASCII(this.proxyHost)), this.proxyPort); this.addLanEndpoint(this.proxyHost.isEmpty() ? null : InetAddress.getByName(IDN.toASCII(this.proxyHost)), this.proxyPort);
@ -561,19 +611,27 @@ public class Proxy {
private void register(Command cmd) { private void register(Command cmd) {
if(this.commands.containsKey(cmd.getName())) if(this.commands.containsKey(cmd.getName()))
throw new IllegalArgumentException("Command '" + cmd.getName() + "' ist already registered"); throw new IllegalArgumentException("Command '" + cmd.getName() + "' is already registered");
this.commands.put(cmd.getName(), cmd); this.commands.put(cmd.getName(), cmd);
} }
private void registerCommands() { private void registerCommands() {
this.register(new CommandHelp()); this.register(new CommandHelp());
this.register(new CommandExit()); this.register(new CommandExit());
this.register(new CommandReload());
this.register(new CommandAdmin()); this.register(new CommandAdmin());
this.register(new CommandRevoke()); this.register(new CommandRevoke());
this.register(new CommandRegister()); this.register(new CommandRegister());
this.register(new CommandDelete()); this.register(new CommandDelete());
this.register(new CommandList()); this.register(new CommandList());
this.register(new CommandPing()); this.register(new CommandPing());
this.register(new CommandKick());
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"}) {
this.register(new CommandDummy(cmd));
}
} }
public Map<String, Command> getCommands() { public Map<String, Command> getCommands() {
@ -617,8 +675,11 @@ public class Proxy {
Log.error("Command '%s' not found", args[0]); Log.error("Command '%s' not found", args[0]);
return false; return false;
} }
if(player != null && (cmd.getPermission() == null || (cmd.getPermission().isEmpty() && !player.isAdmin()) || !player.hasPermission(cmd.getPermission()))) { if(!cmd.canUse(player)) {
player.sendMessage(Formatter.DARK_RED + "You are not allowed to execute this command"); if(player == null)
Log.error("The console can not use this command");
else
player.sendMessage(Formatter.DARK_RED + "You are not allowed to execute this command");
return true; return true;
} }
String[] argv = new String[args.length - 1]; String[] argv = new String[args.length - 1];

View file

@ -21,6 +21,9 @@ public abstract class Command {
public String getPermission() { public String getPermission() {
return "vproxy.cmd." + this.getName(); return "vproxy.cmd." + this.getName();
} }
public boolean canUse(ProxyHandler player) {
return player == null || (this.getPermission() != null && (this.getPermission().isEmpty() ? player.isAdmin() : player.hasPermission(this.getPermission())));
}
protected static void sendMessage(ProxyHandler player, String msg) { protected static void sendMessage(ProxyHandler player, String msg) {
if(player != null) if(player != null)

View file

@ -0,0 +1,27 @@
package proxy.command;
import proxy.Proxy;
import proxy.handler.ProxyHandler;
public class CommandDummy extends Command {
private final String name;
public CommandDummy(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public String getHelp() {
return null;
}
public boolean canUse(ProxyHandler player) {
return false;
}
public void run(Proxy proxy, ProxyHandler player, String[] args) {
}
}

View file

@ -20,7 +20,7 @@ public class CommandExit extends Command {
} }
public void run(Proxy proxy, ProxyHandler player, String[] args) { public void run(Proxy proxy, ProxyHandler player, String[] args) {
String msg = args.length == 0 ? "Proxy stopped" : Formatter.joinSpace(args); String msg = args.length == 0 ? "Proxy stopped" : Formatter.joinSpace(0, args);
for(ProxyHandler plr : Lists.newArrayList(proxy.getPlayers())) { for(ProxyHandler plr : Lists.newArrayList(proxy.getPlayers())) {
plr.disconnect(msg); plr.disconnect(msg);
} }

View file

@ -2,6 +2,8 @@ package proxy.command;
import java.util.Locale; import java.util.Locale;
import com.google.common.collect.Collections2;
import proxy.Proxy; import proxy.Proxy;
import proxy.handler.ProxyHandler; import proxy.handler.ProxyHandler;
import proxy.util.Formatter; import proxy.util.Formatter;
@ -28,17 +30,20 @@ public class CommandHelp extends Command {
public void run(Proxy proxy, ProxyHandler player, String[] args) { public void run(Proxy proxy, ProxyHandler player, String[] args) {
if(args.length == 0) { if(args.length == 0) {
for(Command cmd : proxy.getCommands().values()) { for(Command cmd : proxy.getCommands().values()) {
sendMessage(player, formatCommand(cmd, player != null)); if(cmd.canUse(player))
sendMessage(player, formatCommand(cmd, player != null));
} }
return; return;
} }
Command cmd = proxy.getCommands().get(args[0].toLowerCase(Locale.US)); Command cmd = proxy.getCommands().get(args[0].toLowerCase(Locale.US));
if(cmd == null) if(cmd == null)
throw new RunException("Command '%s' not found", args[0]); throw new RunException("Command '%s' not found", args[0]);
if(!cmd.canUse(player))
throw new RunException("Command '%s' can not be used", args[0]);
sendMessage(player, formatCommand(cmd, player != null)); 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) {
return args.length == 1 ? proxy.getCommands().keySet() : null; return args.length == 1 ? Collections2.filter(proxy.getCommands().keySet(), name -> proxy.getCommands().get(name).canUse(player)) : null;
} }
} }

View file

@ -0,0 +1,38 @@
package proxy.command;
import com.google.common.collect.Collections2;
import proxy.Proxy;
import proxy.handler.ProxyHandler;
import proxy.util.Formatter;
public class CommandKick extends Command {
public String getName() {
return "kick";
}
public String getHelp() {
return "Kicks a player off the server";
}
public String getArgs() {
return "<player> [reason ...]";
}
public void run(Proxy proxy, ProxyHandler player, String[] args) {
if(args.length < 1)
throw new RunException("Please provide a player name");
ProxyHandler plr = proxy.getPlayer(args[0]);
if(plr == null)
throw new RunException("'%s' is not online", args[0]);
if(plr == player)
throw new RunException("You cannot kick yourself");
if(player != null && plr.isAdmin())
throw new RunException("Admins can only be kicked by the console");
plr.disconnect(args.length <= 1 ? "Kicked from server" : Formatter.joinSpace(1, args));
}
public Iterable<String> complete(Proxy proxy, ProxyHandler player, String[] args) {
return args.length == 1 ? (player == null ? proxy.getPlayerNames() : Collections2.filter(proxy.getPlayerNames(), name -> !proxy.getPlayer(name).isAdmin())) : null;
}
}

View file

@ -0,0 +1,19 @@
package proxy.command;
import proxy.Proxy;
import proxy.handler.ProxyHandler;
public class CommandReload extends Command {
public String getName() {
return "reload";
}
public String getHelp() {
return "Reloads the proxy config";
}
public void run(Proxy proxy, ProxyHandler player, String[] args) {
proxy.loadConfig();
sendInfo(player, "Configuration reloaded");
}
}

View file

@ -0,0 +1,23 @@
package proxy.command;
import proxy.Proxy;
import proxy.handler.ProxyHandler;
import proxy.packet.C01PacketChatMessage;
public class CommandSave extends Command {
public String getName() {
return "save";
}
public String getHelp() {
return "Saves all worlds";
}
public boolean canUse(ProxyHandler player) {
return player != null && super.canUse(player);
}
public void run(Proxy proxy, ProxyHandler player, String[] args) {
player.sendToServer(new C01PacketChatMessage("/save-all"));
}
}

View file

@ -0,0 +1,23 @@
package proxy.command;
import proxy.Proxy;
import proxy.handler.ProxyHandler;
import proxy.packet.C01PacketChatMessage;
public class CommandSeed extends Command {
public String getName() {
return "seed";
}
public String getHelp() {
return "Displays the world seed";
}
public boolean canUse(ProxyHandler player) {
return player != null && super.canUse(player);
}
public void run(Proxy proxy, ProxyHandler player, String[] args) {
player.sendToServer(new C01PacketChatMessage("/seed"));
}
}

View file

@ -389,7 +389,7 @@ public class ProxyHandler extends User implements Handler {
if(cmd == null) if(cmd == null)
return null; return null;
List<String> list = Lists.<String>newArrayList(); List<String> list = Lists.<String>newArrayList();
if(cmd.getPermission() == null || (cmd.getPermission().isEmpty() && !this.isAdmin()) || !this.hasPermission(cmd.getPermission())) if(!cmd.canUse(this))
return list; return list;
String[] argv = new String[args.length - 1]; String[] argv = new String[args.length - 1];
System.arraycopy(args, 1, argv, 0, argv.length); System.arraycopy(args, 1, argv, 0, argv.length);
@ -456,7 +456,7 @@ public class ProxyHandler extends User implements Handler {
} }
for(Command cmd : this.proxy.getCommands().values()) { for(Command cmd : this.proxy.getCommands().values()) {
String command = "/" + cmd.getName(); String command = "/" + cmd.getName();
if(cmd.getPermission() != null && (!cmd.getPermission().isEmpty() || this.isAdmin()) && command.regionMatches(true, 0, this.completion, 0, this.completion.length())) if(cmd.canUse(this) && command.regionMatches(true, 0, this.completion, 0, this.completion.length()))
list.add(command); list.add(command);
} }
Collections.sort(list); Collections.sort(list);

View file

@ -0,0 +1,12 @@
package proxy.util;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(FIELD)
public @interface Config {
}

View file

@ -78,16 +78,16 @@ public enum Formatter {
return sb.toString().trim(); return sb.toString().trim();
} }
public static String joinSpace(String ... objs) { public static String joinSpace(int index, String ... objs) {
return joinSpace((Object[])objs); return joinSpace(index, (Object[])objs);
} }
public static String joinSpace(Object ... objs) { public static String joinSpace(int index, Object ... objs) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for(Object obj : objs) { for(int z = index; z < objs.length; z++) {
if(sb.length() != 0) if(sb.length() != 0)
sb.append(' '); sb.append(' ');
sb.append(obj); sb.append(objs[z]);
} }
return sb.toString(); return sb.toString();
} }

View file

@ -0,0 +1,83 @@
package proxy.util;
import java.lang.reflect.Field;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
public class Option {
private final Field field;
private final Object object;
public Option(Field field, Object object) {
this.field = field;
if(this.field.getType() != int.class && this.field.getType() != boolean.class && this.field.getType() != String.class && this.field.getType() != String[].class)
throw new IllegalArgumentException(field.getName() + ": is not int, boolean, String or String[]");
this.object = object;
}
public JsonElement get() {
Object obj;
try {
obj = this.field.get(this.object);
}
catch(IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
if(this.field.getType() == int.class)
return new JsonPrimitive((Integer)obj);
if(this.field.getType() == boolean.class)
return new JsonPrimitive((Boolean)obj);
if(this.field.getType() == String.class)
return new JsonPrimitive((String)obj);
JsonArray arr = new JsonArray();
for(String str : (String[])obj) {
arr.add(new JsonPrimitive(str));
}
return arr;
}
public boolean set(JsonElement data) {
Object value;
if(this.field.getType() == int.class) {
if(!data.isJsonPrimitive())
return false;
value = data.getAsNumber().intValue();
}
else if(this.field.getType() == boolean.class) {
if(!data.isJsonPrimitive())
return false;
value = data.getAsBoolean();
}
else if(this.field.getType() == String.class) {
if(!data.isJsonPrimitive())
return false;
value = data.getAsString();
}
else {
if(data.isJsonPrimitive()) {
value = data.getAsString();
}
else {
if(!data.isJsonArray())
return false;
JsonArray arr = data.getAsJsonArray();
String[] strs = new String[arr.size()];
for(int z = 0; z < strs.length; z++) {
if(!arr.get(z).isJsonPrimitive())
return false;
strs[z] = arr.get(z).getAsString();
}
value = strs;
}
}
try {
this.field.set(this.object, value);
}
catch(IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
return true;
}
}