mirror of
https://github.com/songoda/SongodaCore.git
synced 2024-12-25 01:47:39 +01:00
Overhaul
This commit is contained in:
parent
c914f25ad5
commit
7f86b708c3
2
pom.xml
2
pom.xml
@ -28,7 +28,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot</artifactId>
|
<artifactId>spigot</artifactId>
|
||||||
<version>1.14-pre5-2</version>
|
<version>1.14</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -13,6 +13,8 @@ public class Plugin {
|
|||||||
private List<Module> modules = new ArrayList<>();
|
private List<Module> modules = new ArrayList<>();
|
||||||
private String latestVersion;
|
private String latestVersion;
|
||||||
private String notification;
|
private String notification;
|
||||||
|
private String changeLog;
|
||||||
|
private String marketplaceLink;
|
||||||
private JSONObject json;
|
private JSONObject json;
|
||||||
|
|
||||||
public Plugin(JavaPlugin javaPlugin, int songodaId) {
|
public Plugin(JavaPlugin javaPlugin, int songodaId) {
|
||||||
@ -36,6 +38,22 @@ public class Plugin {
|
|||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getChangeLog() {
|
||||||
|
return changeLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChangeLog(String changeLog) {
|
||||||
|
this.changeLog = changeLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMarketplaceLink() {
|
||||||
|
return marketplaceLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarketplaceLink(String marketplaceLink) {
|
||||||
|
this.marketplaceLink = marketplaceLink;
|
||||||
|
}
|
||||||
|
|
||||||
public JSONObject getJson() {
|
public JSONObject getJson() {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package com.songoda.update;
|
package com.songoda.update;
|
||||||
|
|
||||||
|
import com.songoda.update.command.CommandManager;
|
||||||
import com.songoda.update.listeners.LoginListener;
|
import com.songoda.update.listeners.LoginListener;
|
||||||
|
import com.songoda.update.utils.ServerVersion;
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
@ -17,25 +20,30 @@ import java.util.List;
|
|||||||
|
|
||||||
public class SongodaUpdate {
|
public class SongodaUpdate {
|
||||||
|
|
||||||
|
private static String prefix = "[SongodaUpdate] ";
|
||||||
|
|
||||||
|
private ServerVersion serverVersion = ServerVersion.fromPackageName(Bukkit.getServer().getClass().getPackage().getName());
|
||||||
|
|
||||||
|
|
||||||
private static int version = 1;
|
private static int version = 1;
|
||||||
|
|
||||||
private static List<Plugin> registeredPlugins = new ArrayList<>();
|
private static List<Plugin> registeredPlugins = new ArrayList<>();
|
||||||
|
|
||||||
private static SongodaUpdate INSTANCE;
|
private static SongodaUpdate INSTANCE;
|
||||||
|
|
||||||
|
private static JavaPlugin hijackedPlugin;
|
||||||
|
|
||||||
public SongodaUpdate() {
|
public SongodaUpdate() {
|
||||||
JavaPlugin hijackedPlugin = registeredPlugins.get(0).getJavaPlugin();
|
hijackedPlugin = registeredPlugins.get(0).getJavaPlugin();
|
||||||
Bukkit.getPluginManager().registerEvents(new LoginListener(this), hijackedPlugin);
|
Bukkit.getPluginManager().registerEvents(new LoginListener(this), hijackedPlugin);
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(hijackedPlugin, this::update, 20L);
|
|
||||||
|
new CommandManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update(Plugin plugin) {
|
||||||
for (Plugin plugin : registeredPlugins) {
|
|
||||||
try {
|
try {
|
||||||
JavaPlugin javaPlugin = plugin.getJavaPlugin();
|
URL url = new URL("http://update.songoda.com/index.php?plugin=" + plugin.getSongodaId() +
|
||||||
System.out.println("Establishing connection with the Songoda update server.");
|
"&version=" + plugin.getJavaPlugin().getDescription().getVersion());
|
||||||
URL url = new URL("http://update.songoda.com/index.php?plugin=" + javaPlugin.getName() +
|
|
||||||
"&version=" + javaPlugin.getDescription().getVersion());
|
|
||||||
URLConnection urlConnection = url.openConnection();
|
URLConnection urlConnection = url.openConnection();
|
||||||
InputStream is = urlConnection.getInputStream();
|
InputStream is = urlConnection.getInputStream();
|
||||||
InputStreamReader isr = new InputStreamReader(is);
|
InputStreamReader isr = new InputStreamReader(is);
|
||||||
@ -50,7 +58,9 @@ public class SongodaUpdate {
|
|||||||
JSONObject json = (JSONObject) new JSONParser().parse(jsonString);
|
JSONObject json = (JSONObject) new JSONParser().parse(jsonString);
|
||||||
|
|
||||||
plugin.setLatestVersion((String) json.get("latestVersion"));
|
plugin.setLatestVersion((String) json.get("latestVersion"));
|
||||||
|
plugin.setMarketplaceLink((String) json.get("link"));
|
||||||
plugin.setNotification((String) json.get("notification"));
|
plugin.setNotification((String) json.get("notification"));
|
||||||
|
plugin.setChangeLog((String) json.get("changeLog"));
|
||||||
|
|
||||||
plugin.setJson(json);
|
plugin.setJson(json);
|
||||||
|
|
||||||
@ -58,22 +68,37 @@ public class SongodaUpdate {
|
|||||||
module.run(plugin);
|
module.run(plugin);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("Connection failed...");
|
System.out.println("Connection with Songoda servers failed...");
|
||||||
e.printStackTrace(); //ToDo: This cannot be here in final.
|
e.printStackTrace(); //ToDo: This cannot be here in final.
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
System.out.println("Failed to parse json.");
|
System.out.println("Failed to parse json.");
|
||||||
e.printStackTrace(); //ToDo: This cannot be here in final.
|
e.printStackTrace(); //ToDo: This cannot be here in final.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static Plugin load(Plugin plugin) {
|
public static Plugin load(Plugin plugin) {
|
||||||
registeredPlugins.add(plugin);
|
registeredPlugins.add(plugin);
|
||||||
System.out.println("Hooked " + plugin.getJavaPlugin().getName() + ".");
|
System.out.println(prefix + "Hooked " + plugin.getJavaPlugin().getName() + ".");
|
||||||
if (INSTANCE == null) INSTANCE = new SongodaUpdate();
|
if (INSTANCE == null) INSTANCE = new SongodaUpdate();
|
||||||
|
getInstance().update(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ServerVersion getServerVersion() {
|
||||||
|
return serverVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isServerVersion(ServerVersion version) {
|
||||||
|
return serverVersion == version;
|
||||||
|
}
|
||||||
|
public boolean isServerVersion(ServerVersion... versions) {
|
||||||
|
return ArrayUtils.contains(versions, serverVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isServerVersionAtLeast(ServerVersion version) {
|
||||||
|
return serverVersion.ordinal() >= version.ordinal();
|
||||||
|
}
|
||||||
|
|
||||||
public List<Plugin> getPlugins() {
|
public List<Plugin> getPlugins() {
|
||||||
return new ArrayList<>(registeredPlugins);
|
return new ArrayList<>(registeredPlugins);
|
||||||
}
|
}
|
||||||
@ -82,6 +107,14 @@ public class SongodaUpdate {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPrefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JavaPlugin getHijackedPlugin() {
|
||||||
|
return hijackedPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
public static SongodaUpdate getInstance() {
|
public static SongodaUpdate getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.songoda.update.command;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbstractCommand {
|
||||||
|
|
||||||
|
private final boolean noConsole;
|
||||||
|
private AbstractCommand parent = null;
|
||||||
|
private boolean hasArgs = false;
|
||||||
|
private String command;
|
||||||
|
|
||||||
|
private List<String> subCommand = new ArrayList<>();
|
||||||
|
|
||||||
|
protected AbstractCommand(AbstractCommand parent, boolean noConsole, String... command) {
|
||||||
|
if (parent != null) {
|
||||||
|
this.subCommand = Arrays.asList(command);
|
||||||
|
} else {
|
||||||
|
this.command = Arrays.asList(command).get(0);
|
||||||
|
}
|
||||||
|
this.parent = parent;
|
||||||
|
this.noConsole = noConsole;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractCommand(boolean noConsole, boolean hasArgs, String... command) {
|
||||||
|
this.command = Arrays.asList(command).get(0);
|
||||||
|
|
||||||
|
this.hasArgs = hasArgs;
|
||||||
|
this.noConsole = noConsole;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractCommand getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getSubCommand() {
|
||||||
|
return subCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSubCommand(String command) {
|
||||||
|
subCommand.add(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ReturnType runCommand(SongodaUpdate instance, CommandSender sender, String... args);
|
||||||
|
|
||||||
|
protected abstract List<String> onTab(SongodaUpdate instance, CommandSender sender, String... args);
|
||||||
|
|
||||||
|
public abstract String getPermissionNode();
|
||||||
|
|
||||||
|
public abstract String getSyntax();
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public boolean hasArgs() {
|
||||||
|
return hasArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNoConsole() {
|
||||||
|
return noConsole;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ReturnType {SUCCESS, FAILURE, SYNTAX_ERROR}
|
||||||
|
}
|
116
src/main/java/com/songoda/update/command/CommandManager.java
Normal file
116
src/main/java/com/songoda/update/command/CommandManager.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package com.songoda.update.command;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.command.commands.CommandDiag;
|
||||||
|
import com.songoda.update.command.commands.CommandSongoda;
|
||||||
|
import com.songoda.update.utils.Methods;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.*;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CommandManager implements CommandExecutor {
|
||||||
|
|
||||||
|
private SongodaUpdate instance;
|
||||||
|
private TabManager tabManager;
|
||||||
|
|
||||||
|
private List<AbstractCommand> commands = new ArrayList<>();
|
||||||
|
|
||||||
|
public CommandManager(SongodaUpdate instance) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.tabManager = new TabManager(this);
|
||||||
|
|
||||||
|
registerCommandDynamically("songoda", this);
|
||||||
|
|
||||||
|
AbstractCommand commandSongoda = addCommand(new CommandSongoda());
|
||||||
|
addCommand(new CommandDiag(commandSongoda));
|
||||||
|
|
||||||
|
for (AbstractCommand abstractCommand : commands) {
|
||||||
|
if (abstractCommand.getParent() != null) continue;
|
||||||
|
//instance.getCommand(abstractCommand.getCommand()).setTabCompleter(tabManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractCommand addCommand(AbstractCommand abstractCommand) {
|
||||||
|
commands.add(abstractCommand);
|
||||||
|
return abstractCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
|
||||||
|
for (AbstractCommand abstractCommand : commands) {
|
||||||
|
if (abstractCommand.getCommand() != null && abstractCommand.getCommand().equalsIgnoreCase(command.getName().toLowerCase())) {
|
||||||
|
if (strings.length == 0 || abstractCommand.hasArgs()) {
|
||||||
|
processRequirements(abstractCommand, commandSender, strings);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (strings.length != 0 && abstractCommand.getParent() != null && abstractCommand.getParent().getCommand().equalsIgnoreCase(command.getName())) {
|
||||||
|
String cmd = strings[0];
|
||||||
|
String cmd2 = strings.length >= 2 ? String.join(" ", strings[0], strings[1]) : null;
|
||||||
|
for (String cmds : abstractCommand.getSubCommand()) {
|
||||||
|
if (cmd.equalsIgnoreCase(cmds) || (cmd2 != null && cmd2.equalsIgnoreCase(cmds))) {
|
||||||
|
processRequirements(abstractCommand, commandSender, strings);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commandSender.sendMessage(instance.getPrefix() + Methods.formatText("&7The command you entered does not exist or is spelt incorrectly."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processRequirements(AbstractCommand command, CommandSender sender, String[] strings) {
|
||||||
|
if (!(sender instanceof Player) && command.isNoConsole()) {
|
||||||
|
sender.sendMessage("You must be a player to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) {
|
||||||
|
AbstractCommand.ReturnType returnType = command.runCommand(instance, sender, strings);
|
||||||
|
if (returnType == AbstractCommand.ReturnType.SYNTAX_ERROR) {
|
||||||
|
sender.sendMessage(instance.getPrefix() + Methods.formatText("&cInvalid Syntax!"));
|
||||||
|
sender.sendMessage(instance.getPrefix() + Methods.formatText("&7The valid syntax is: &6" + command.getSyntax() + "&7."));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sender.sendMessage(instance.getPrefix() + "You do not have permission to run this command.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AbstractCommand> getCommands() {
|
||||||
|
return Collections.unmodifiableList(commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerCommandDynamically(String command, CommandExecutor executor) {
|
||||||
|
try {
|
||||||
|
// Retrieve the SimpleCommandMap from the server
|
||||||
|
Class<?> classCraftServer = Bukkit.getServer().getClass();
|
||||||
|
Field fieldCommandMap = classCraftServer.getDeclaredField("commandMap");
|
||||||
|
fieldCommandMap.setAccessible(true);
|
||||||
|
SimpleCommandMap commandMap = (SimpleCommandMap) fieldCommandMap.get(Bukkit.getServer());
|
||||||
|
|
||||||
|
// Construct a new Command object
|
||||||
|
Constructor<PluginCommand> constructorPluginCommand = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
|
||||||
|
constructorPluginCommand.setAccessible(true);
|
||||||
|
PluginCommand commandObject = constructorPluginCommand.newInstance(command, SongodaUpdate.getHijackedPlugin());
|
||||||
|
commandObject.setExecutor(executor);
|
||||||
|
|
||||||
|
// Set tab complete
|
||||||
|
commandObject.setTabCompleter(tabManager);
|
||||||
|
|
||||||
|
// Register the command
|
||||||
|
Field fieldKnownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
|
||||||
|
fieldKnownCommands.setAccessible(true);
|
||||||
|
Map<String, Command> knownCommands = (Map<String, Command>) fieldKnownCommands.get(commandMap);
|
||||||
|
knownCommands.put(command, commandObject);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
src/main/java/com/songoda/update/command/TabManager.java
Normal file
63
src/main/java/com/songoda/update/command/TabManager.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package com.songoda.update.command;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TabManager implements TabCompleter {
|
||||||
|
|
||||||
|
private final CommandManager commandManager;
|
||||||
|
|
||||||
|
TabManager(CommandManager commandManager) {
|
||||||
|
this.commandManager = commandManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] strings) {
|
||||||
|
for (AbstractCommand abstractCommand : commandManager.getCommands()) {
|
||||||
|
if (abstractCommand.getCommand() != null && abstractCommand.getCommand().equalsIgnoreCase(command.getName()) && !abstractCommand.hasArgs()) {
|
||||||
|
if (strings.length == 1) {
|
||||||
|
List<String> subs = new ArrayList<>();
|
||||||
|
for (AbstractCommand ac : commandManager.getCommands()) {
|
||||||
|
if (ac.getSubCommand() == null) continue;
|
||||||
|
subs.addAll(ac.getSubCommand());
|
||||||
|
}
|
||||||
|
subs.removeIf(s -> !s.toLowerCase().startsWith(strings[0].toLowerCase()));
|
||||||
|
return subs;
|
||||||
|
}
|
||||||
|
} else if (strings.length != 0
|
||||||
|
&& abstractCommand.getCommand() != null
|
||||||
|
&& abstractCommand.getCommand().equalsIgnoreCase(command.getName().toLowerCase())) {
|
||||||
|
String cmd = strings[0];
|
||||||
|
String cmd2 = strings.length >= 2 ? String.join(" ", strings[0], strings[1]) : null;
|
||||||
|
if (abstractCommand.hasArgs()) {
|
||||||
|
return onCommand(abstractCommand, strings, sender);
|
||||||
|
} else {
|
||||||
|
for (String cmds : abstractCommand.getSubCommand()) {
|
||||||
|
if (cmd.equalsIgnoreCase(cmds) || (cmd2 != null && cmd2.equalsIgnoreCase(cmds))) {
|
||||||
|
return onCommand(abstractCommand, strings, sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<String> onCommand(AbstractCommand abstractCommand, String[] strings, CommandSender sender) {
|
||||||
|
List<String> list = abstractCommand.onTab(SongodaUpdate.getInstance(), sender, strings);
|
||||||
|
String str = strings[strings.length - 1];
|
||||||
|
if (list != null && str != null && str.length() >= 1) {
|
||||||
|
try {
|
||||||
|
list.removeIf(s -> !s.toLowerCase().startsWith(str.toLowerCase()));
|
||||||
|
} catch (UnsupportedOperationException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.songoda.update.command.commands;
|
||||||
|
|
||||||
|
import com.songoda.update.Plugin;
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.command.AbstractCommand;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CommandDiag extends AbstractCommand {
|
||||||
|
|
||||||
|
private final String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||||
|
private final String version = name.substring(name.lastIndexOf('.') + 1);
|
||||||
|
|
||||||
|
private final DecimalFormat format = new DecimalFormat("##.##");
|
||||||
|
|
||||||
|
private Object serverInstance;
|
||||||
|
private Field tpsField;
|
||||||
|
|
||||||
|
|
||||||
|
public CommandDiag(AbstractCommand parent) {
|
||||||
|
super(parent, false, "diag");
|
||||||
|
|
||||||
|
try {
|
||||||
|
serverInstance = getNMSClass("MinecraftServer").getMethod("getServer").invoke(null);
|
||||||
|
tpsField = serverInstance.getClass().getField("recentTps");
|
||||||
|
} catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException
|
||||||
|
| InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ReturnType runCommand(SongodaUpdate instance, CommandSender sender, String... args) {
|
||||||
|
|
||||||
|
sender.sendMessage("");
|
||||||
|
sender.sendMessage("Songoda Diagnostics Information");
|
||||||
|
sender.sendMessage("");
|
||||||
|
sender.sendMessage("Plugins:");
|
||||||
|
for (Plugin plugin : instance.getPlugins()) {
|
||||||
|
sender.sendMessage(plugin.getJavaPlugin().getName()
|
||||||
|
+ " (" + plugin.getJavaPlugin().getDescription().getVersion() + ")");
|
||||||
|
}
|
||||||
|
sender.sendMessage("");
|
||||||
|
sender.sendMessage("Server Version: " + Bukkit.getVersion());
|
||||||
|
sender.sendMessage("Operating System: " + System.getProperty("os.name"));
|
||||||
|
sender.sendMessage("Allocated Memory: " + format.format(Runtime.getRuntime().maxMemory() / (1024 * 1024)) + "Mb");
|
||||||
|
sender.sendMessage("Online Players: " + Bukkit.getOnlinePlayers().size());
|
||||||
|
try {
|
||||||
|
double[] tps = ((double[]) tpsField.get(serverInstance));
|
||||||
|
|
||||||
|
sender.sendMessage("TPS from last 1m, 5m, 15m: " + format.format(tps[0]) + ", "
|
||||||
|
+ format.format(tps[1]) + ", " + format.format(tps[2]));
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReturnType.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> onTab(SongodaUpdate instance, CommandSender sender, String... args) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPermissionNode() {
|
||||||
|
return "songoda.admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSyntax() {
|
||||||
|
return "/songoda diag";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Display diagnostics information.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class<?> getNMSClass(String className) {
|
||||||
|
try {
|
||||||
|
return Class.forName("net.minecraft.server." + version + "." + className);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.songoda.update.command.commands;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.command.AbstractCommand;
|
||||||
|
import com.songoda.update.gui.GUIOverview;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CommandSongoda extends AbstractCommand {
|
||||||
|
|
||||||
|
public CommandSongoda() {
|
||||||
|
super(true, false, "songoda");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ReturnType runCommand(SongodaUpdate instance, CommandSender sender, String... args) {
|
||||||
|
new GUIOverview(instance, (Player) sender);
|
||||||
|
return ReturnType.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> onTab(SongodaUpdate instance, CommandSender sender, String... args) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPermissionNode() {
|
||||||
|
return "songoda.admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSyntax() {
|
||||||
|
return "/songoda";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Displays this interface.";
|
||||||
|
}
|
||||||
|
}
|
52
src/main/java/com/songoda/update/gui/GUIOverview.java
Normal file
52
src/main/java/com/songoda/update/gui/GUIOverview.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package com.songoda.update.gui;
|
||||||
|
|
||||||
|
import com.songoda.update.Plugin;
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.utils.gui.AbstractGUI;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GUIOverview extends AbstractGUI {
|
||||||
|
|
||||||
|
private final SongodaUpdate update;
|
||||||
|
|
||||||
|
public GUIOverview(SongodaUpdate update, Player player) {
|
||||||
|
super(player);
|
||||||
|
this.update = update;
|
||||||
|
|
||||||
|
init("Songoda Update", 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void constructGUI() {
|
||||||
|
List<Plugin> plugins = update.getPlugins();
|
||||||
|
for (int i = 0; i < plugins.size(); i++) {
|
||||||
|
Plugin plugin = plugins.get(i);
|
||||||
|
|
||||||
|
createButton(i + 9, Material.STONE, "&6" + plugin.getJavaPlugin().getName(),
|
||||||
|
"&7Latest Version: " + plugin.getLatestVersion(),
|
||||||
|
"&7Installed Version: " + plugin.getJavaPlugin().getDescription().getVersion(),
|
||||||
|
"",
|
||||||
|
"Change log:",
|
||||||
|
plugin.getChangeLog(),
|
||||||
|
"",
|
||||||
|
"&6Click for the marketplace page link.");
|
||||||
|
|
||||||
|
registerClickable(i + 9, ((player1, inventory1, cursor, slot, type) ->
|
||||||
|
player.sendMessage(plugin.getMarketplaceLink())));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerClickables() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerOnCloses() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.songoda.update.utils;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class AbstractChatConfirm implements Listener {
|
||||||
|
|
||||||
|
private static final List<UUID> registered = new ArrayList<>();
|
||||||
|
|
||||||
|
private final Player player;
|
||||||
|
private final ChatConfirmHandler handler;
|
||||||
|
|
||||||
|
private OnClose onClose = null;
|
||||||
|
private Listener listener;
|
||||||
|
|
||||||
|
public AbstractChatConfirm(Player player, ChatConfirmHandler hander) {
|
||||||
|
this.player = player;
|
||||||
|
this.handler = hander;
|
||||||
|
player.closeInventory();
|
||||||
|
initializeListeners(SongodaUpdate.getHijackedPlugin());
|
||||||
|
registered.add(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRegistered(Player player) {
|
||||||
|
return registered.contains(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean unregister(Player player) {
|
||||||
|
return registered.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeListeners(JavaPlugin plugin) {
|
||||||
|
|
||||||
|
this.listener = new Listener() {
|
||||||
|
@EventHandler
|
||||||
|
public void onChat(AsyncPlayerChatEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (!AbstractChatConfirm.isRegistered(player)) return;
|
||||||
|
|
||||||
|
AbstractChatConfirm.unregister(player);
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
ChatConfirmEvent chatConfirmEvent = new ChatConfirmEvent(player, event.getMessage());
|
||||||
|
|
||||||
|
handler.onChat(chatConfirmEvent);
|
||||||
|
|
||||||
|
if (onClose != null) {
|
||||||
|
onClose.onClose();
|
||||||
|
}
|
||||||
|
HandlerList.unregisterAll(listener);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(listener, SongodaUpdate.getHijackedPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnClose(OnClose onClose) {
|
||||||
|
this.onClose = onClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ChatConfirmHandler {
|
||||||
|
void onChat(ChatConfirmEvent event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnClose {
|
||||||
|
void onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChatConfirmEvent {
|
||||||
|
|
||||||
|
private final Player player;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
public ChatConfirmEvent(Player player, String message) {
|
||||||
|
this.player = player;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
src/main/java/com/songoda/update/utils/Methods.java
Normal file
19
src/main/java/com/songoda/update/utils/Methods.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.songoda.update.utils;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
|
public class Methods {
|
||||||
|
|
||||||
|
public static String formatText(String text) {
|
||||||
|
return formatText(text, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatText(String text, boolean cap) {
|
||||||
|
if (text == null || text.equals(""))
|
||||||
|
return "";
|
||||||
|
if (cap)
|
||||||
|
text = text.substring(0, 1).toUpperCase() + text.substring(1);
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', text);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
src/main/java/com/songoda/update/utils/ServerVersion.java
Normal file
27
src/main/java/com/songoda/update/utils/ServerVersion.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.songoda.update.utils;
|
||||||
|
|
||||||
|
public enum ServerVersion {
|
||||||
|
|
||||||
|
UNKNOWN("unknown_server_version"),
|
||||||
|
V1_7("org.bukkit.craftbukkit.v1_7"),
|
||||||
|
V1_8("org.bukkit.craftbukkit.v1_8"),
|
||||||
|
V1_9("org.bukkit.craftbukkit.v1_9"),
|
||||||
|
V1_10("org.bukkit.craftbukkit.v1_10"),
|
||||||
|
V1_11("org.bukkit.craftbukkit.v1_11"),
|
||||||
|
V1_12("org.bukkit.craftbukkit.v1_12"),
|
||||||
|
V1_13("org.bukkit.craftbukkit.v1_13"),
|
||||||
|
V1_14("org.bukkit.craftbukkit.v1_14");
|
||||||
|
|
||||||
|
|
||||||
|
private final String packagePrefix;
|
||||||
|
|
||||||
|
private ServerVersion(String packagePrefix) {
|
||||||
|
this.packagePrefix = packagePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerVersion fromPackageName(String packageName) {
|
||||||
|
for (ServerVersion version : values())
|
||||||
|
if (packageName.startsWith(version.packagePrefix)) return version;
|
||||||
|
return ServerVersion.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
304
src/main/java/com/songoda/update/utils/gui/AbstractAnvilGUI.java
Normal file
304
src/main/java/com/songoda/update/utils/gui/AbstractAnvilGUI.java
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
package com.songoda.update.utils.gui;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.utils.version.NMSUtil;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AbstractAnvilGUI {
|
||||||
|
|
||||||
|
private static Class<?> BlockPositionClass;
|
||||||
|
private static Class<?> PacketPlayOutOpenWindowClass;
|
||||||
|
private static Class<?> IChatBaseComponentClass;
|
||||||
|
private static Class<?> ICraftingClass;
|
||||||
|
private static Class<?> ContainerAnvilClass;
|
||||||
|
private static Class<?> ChatMessageClass;
|
||||||
|
private static Class<?> EntityHumanClass;
|
||||||
|
private static Class<?> ContainerClass;
|
||||||
|
private static Class<?> ContainerAccessClass;
|
||||||
|
private static Class<?> WorldClass;
|
||||||
|
private static Class<?> PlayerInventoryClass;
|
||||||
|
private static Class<?> ContainersClass;
|
||||||
|
|
||||||
|
private Player player;
|
||||||
|
private Map<AnvilSlot, ItemStack> items = new HashMap<>();
|
||||||
|
private OnClose onClose = null;
|
||||||
|
private Inventory inv;
|
||||||
|
private Listener listener;
|
||||||
|
|
||||||
|
private Sound closeSound = Sound.ENTITY_PLAYER_LEVELUP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
BlockPositionClass = NMSUtil.getNMSClass("BlockPosition");
|
||||||
|
PacketPlayOutOpenWindowClass = NMSUtil.getNMSClass("PacketPlayOutOpenWindow");
|
||||||
|
IChatBaseComponentClass = NMSUtil.getNMSClass("IChatBaseComponent");
|
||||||
|
ICraftingClass = NMSUtil.getNMSClass("ICrafting");
|
||||||
|
ContainerAnvilClass = NMSUtil.getNMSClass("ContainerAnvil");
|
||||||
|
EntityHumanClass = NMSUtil.getNMSClass("EntityHuman");
|
||||||
|
ChatMessageClass = NMSUtil.getNMSClass("ChatMessage");
|
||||||
|
ContainerClass = NMSUtil.getNMSClass("Container");
|
||||||
|
WorldClass = NMSUtil.getNMSClass("World");
|
||||||
|
PlayerInventoryClass = NMSUtil.getNMSClass("PlayerInventory");
|
||||||
|
|
||||||
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
|
ContainerAccessClass = NMSUtil.getNMSClass("ContainerAccess");
|
||||||
|
ContainersClass = NMSUtil.getNMSClass("Containers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractAnvilGUI(final Player player, final AnvilClickEventHandler handler) {
|
||||||
|
this.player = player;
|
||||||
|
|
||||||
|
this.listener = new Listener() {
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
|
if (event.getWhoClicked() instanceof Player) {
|
||||||
|
|
||||||
|
if (event.getInventory().equals(inv)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
ItemStack item = event.getCurrentItem();
|
||||||
|
int slot = event.getRawSlot();
|
||||||
|
String name = "";
|
||||||
|
|
||||||
|
if (item != null) {
|
||||||
|
if (item.hasItemMeta()) {
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
|
||||||
|
if (meta != null && meta.hasDisplayName()) {
|
||||||
|
name = meta.getDisplayName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnvilClickEvent clickEvent = new AnvilClickEvent(AnvilSlot.bySlot(slot), name);
|
||||||
|
|
||||||
|
handler.onAnvilClick(clickEvent);
|
||||||
|
|
||||||
|
if (clickEvent.getWillClose()) {
|
||||||
|
event.getWhoClicked().closeInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clickEvent.getWillDestroy()) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onInventoryClose(InventoryCloseEvent event) {
|
||||||
|
if (event.getPlayer() instanceof Player) {
|
||||||
|
Inventory inv = event.getInventory();
|
||||||
|
player.setLevel(player.getLevel() - 1);
|
||||||
|
if (inv.equals(inv)) {
|
||||||
|
inv.clear();
|
||||||
|
player.playSound(player.getLocation(), closeSound, 1F, 1F);
|
||||||
|
Bukkit.getScheduler().scheduleSyncDelayedTask(SongodaUpdate.getHijackedPlugin(), () -> {
|
||||||
|
if (onClose != null) onClose.OnClose(player, inv);
|
||||||
|
destroy();
|
||||||
|
}, 1L);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
if (event.getPlayer().equals(getPlayer())) {
|
||||||
|
player.setLevel(player.getLevel() - 1);
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(listener, SongodaUpdate.getHijackedPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSlot(AnvilSlot slot, ItemStack item) {
|
||||||
|
items.put(slot, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open() {
|
||||||
|
player.setLevel(player.getLevel() + 1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object craftPlayer = NMSUtil.getCraftClass("entity.CraftPlayer").cast(player);
|
||||||
|
Method getHandleMethod = craftPlayer.getClass().getMethod("getHandle");
|
||||||
|
Object entityPlayer = getHandleMethod.invoke(craftPlayer);
|
||||||
|
Object playerInventory = NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "inventory", false));
|
||||||
|
Object world = NMSUtil.getFieldObject(entityPlayer, NMSUtil.getField(entityPlayer.getClass(), "world", false));
|
||||||
|
Object blockPosition = BlockPositionClass.getConstructor(int.class, int.class, int.class).newInstance(0, 0, 0);
|
||||||
|
|
||||||
|
Object container;
|
||||||
|
|
||||||
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
|
container = ContainerAnvilClass
|
||||||
|
.getConstructor(int.class, PlayerInventoryClass, ContainerAccessClass)
|
||||||
|
.newInstance(7, playerInventory, ContainerAccessClass.getMethod("at", WorldClass, BlockPositionClass).invoke(null, world, blockPosition));
|
||||||
|
} else {
|
||||||
|
container = ContainerAnvilClass
|
||||||
|
.getConstructor(PlayerInventoryClass, WorldClass, BlockPositionClass, EntityHumanClass)
|
||||||
|
.newInstance(playerInventory, world, blockPosition, entityPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
NMSUtil.getField(ContainerClass, "checkReachable", true).set(container, false);
|
||||||
|
|
||||||
|
Method getBukkitViewMethod = container.getClass().getMethod("getBukkitView");
|
||||||
|
Object bukkitView = getBukkitViewMethod.invoke(container);
|
||||||
|
Method getTopInventoryMethod = bukkitView.getClass().getMethod("getTopInventory");
|
||||||
|
inv = (Inventory) getTopInventoryMethod.invoke(bukkitView);
|
||||||
|
|
||||||
|
for (AnvilSlot slot : items.keySet()) {
|
||||||
|
inv.setItem(slot.getSlot(), items.get(slot));
|
||||||
|
}
|
||||||
|
|
||||||
|
Method nextContainerCounterMethod = entityPlayer.getClass().getMethod("nextContainerCounter");
|
||||||
|
int c = (int) nextContainerCounterMethod.invoke(entityPlayer);
|
||||||
|
|
||||||
|
Constructor<?> chatMessageConstructor = ChatMessageClass.getConstructor(String.class, Object[].class);
|
||||||
|
Object inventoryTitle = chatMessageConstructor.newInstance("Repairing", new Object[]{});
|
||||||
|
|
||||||
|
Object packet;
|
||||||
|
|
||||||
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
|
packet = PacketPlayOutOpenWindowClass
|
||||||
|
.getConstructor(int.class, ContainersClass, IChatBaseComponentClass)
|
||||||
|
.newInstance(c, ContainersClass.getField("ANVIL").get(null), inventoryTitle);
|
||||||
|
} else {
|
||||||
|
packet = PacketPlayOutOpenWindowClass
|
||||||
|
.getConstructor(int.class, String.class, IChatBaseComponentClass, int.class)
|
||||||
|
.newInstance(c, "minecraft:anvil", inventoryTitle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
NMSUtil.sendPacket(player, packet);
|
||||||
|
|
||||||
|
Field activeContainerField = NMSUtil.getField(EntityHumanClass, "activeContainer", true);
|
||||||
|
|
||||||
|
if (activeContainerField != null) {
|
||||||
|
activeContainerField.set(entityPlayer, container);
|
||||||
|
NMSUtil.getField(ContainerClass, "windowId", true).set(activeContainerField.get(entityPlayer), c);
|
||||||
|
Method addSlotListenerMethod = activeContainerField.get(entityPlayer).getClass().getMethod("addSlotListener", ICraftingClass);
|
||||||
|
addSlotListenerMethod.invoke(activeContainerField.get(entityPlayer), entityPlayer);
|
||||||
|
|
||||||
|
if (NMSUtil.getVersionNumber() > 13) {
|
||||||
|
ContainerClass.getMethod("setTitle", IChatBaseComponentClass).invoke(container, inventoryTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
player = null;
|
||||||
|
items = null;
|
||||||
|
|
||||||
|
HandlerList.unregisterAll(listener);
|
||||||
|
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnClose getOnClose() {
|
||||||
|
return onClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnClose(OnClose onClose) {
|
||||||
|
this.onClose = onClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCloseSound(Sound sound) {
|
||||||
|
closeSound = sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AnvilSlot {
|
||||||
|
INPUT_LEFT(0),
|
||||||
|
INPUT_RIGHT(1),
|
||||||
|
OUTPUT(2);
|
||||||
|
|
||||||
|
private int slot;
|
||||||
|
|
||||||
|
AnvilSlot(int slot) {
|
||||||
|
this.slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AnvilSlot bySlot(int slot) {
|
||||||
|
for (AnvilSlot anvilSlot : values()) {
|
||||||
|
if (anvilSlot.getSlot() == slot) {
|
||||||
|
return anvilSlot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface AnvilClickEventHandler {
|
||||||
|
void onAnvilClick(AnvilClickEvent event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AnvilClickEvent {
|
||||||
|
private AnvilSlot slot;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private boolean close = true;
|
||||||
|
private boolean destroy = true;
|
||||||
|
|
||||||
|
public AnvilClickEvent(AnvilSlot slot, String name) {
|
||||||
|
this.slot = slot;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnvilSlot getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getWillClose() {
|
||||||
|
return close;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWillClose(boolean close) {
|
||||||
|
this.close = close;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getWillDestroy() {
|
||||||
|
return destroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWillDestroy(boolean destroy) {
|
||||||
|
this.destroy = destroy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
254
src/main/java/com/songoda/update/utils/gui/AbstractGUI.java
Normal file
254
src/main/java/com/songoda/update/utils/gui/AbstractGUI.java
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
package com.songoda.update.utils.gui;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.utils.Methods;
|
||||||
|
import com.songoda.update.utils.gui.Clickable;
|
||||||
|
import com.songoda.update.utils.gui.OnClose;
|
||||||
|
import com.songoda.update.utils.gui.Range;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryType;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public abstract class AbstractGUI implements Listener {
|
||||||
|
|
||||||
|
private static boolean listenersInitialized = false;
|
||||||
|
protected final Player player;
|
||||||
|
protected Inventory inventory = null;
|
||||||
|
protected String setTitle = null;
|
||||||
|
protected boolean cancelBottom = false;
|
||||||
|
private Map<Range, Clickable> clickables = new HashMap<>();
|
||||||
|
private List<OnClose> onCloses = new ArrayList<>();
|
||||||
|
private Map<Range, Boolean> draggableRanges = new HashMap<>();
|
||||||
|
|
||||||
|
public AbstractGUI(Player player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initializeListeners(JavaPlugin plugin) {
|
||||||
|
if (listenersInitialized) return;
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(new Listener() {
|
||||||
|
@EventHandler
|
||||||
|
public void onClickGUI(InventoryClickEvent event) {
|
||||||
|
Inventory inventory = event.getClickedInventory();
|
||||||
|
if (inventory == null) return;
|
||||||
|
AbstractGUI gui = getGUIFromInventory(inventory);
|
||||||
|
Player player = (Player) event.getWhoClicked();
|
||||||
|
|
||||||
|
boolean bottom = false;
|
||||||
|
|
||||||
|
InventoryType type = event.getClickedInventory().getType();
|
||||||
|
if (type != InventoryType.CHEST && type != InventoryType.PLAYER) return;
|
||||||
|
|
||||||
|
if (gui == null && event.getWhoClicked().getOpenInventory().getTopInventory() != null) {
|
||||||
|
Inventory top = event.getWhoClicked().getOpenInventory().getTopInventory();
|
||||||
|
gui = getGUIFromInventory(top);
|
||||||
|
|
||||||
|
if (gui != null && gui.cancelBottom) event.setCancelled(true);
|
||||||
|
bottom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gui == null) return;
|
||||||
|
|
||||||
|
if (!bottom) event.setCancelled(true);
|
||||||
|
|
||||||
|
if (!gui.draggableRanges.isEmpty() && !bottom) {
|
||||||
|
for (Map.Entry<Range, Boolean> entry : gui.draggableRanges.entrySet()) {
|
||||||
|
Range range = entry.getKey();
|
||||||
|
if (range.getMax() == range.getMin() && event.getSlot() == range.getMin()
|
||||||
|
|| event.getSlot() >= range.getMin() && event.getSlot() <= range.getMax()) {
|
||||||
|
event.setCancelled(!entry.getValue());
|
||||||
|
if (!entry.getValue()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Range, Clickable> entries = new HashMap<>(gui.clickables);
|
||||||
|
|
||||||
|
for (Map.Entry<Range, Clickable> entry : entries.entrySet()) {
|
||||||
|
Range range = entry.getKey();
|
||||||
|
if (range.isBottom() && !bottom || !range.isBottom() && bottom || range.getClickType() != null && range.getClickType() != event.getClick())
|
||||||
|
continue;
|
||||||
|
if (event.getSlot() >= range.getMin() && event.getSlot() <= range.getMax()) {
|
||||||
|
entry.getValue().Clickable(player, inventory, event.getCursor(), event.getSlot(), event.getClick());
|
||||||
|
player.playSound(player.getLocation(), entry.getKey().getOnClickSound(), 1F, 1F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onCloseGUI(InventoryCloseEvent event) {
|
||||||
|
Inventory inventory = event.getInventory();
|
||||||
|
AbstractGUI gui = getGUIFromInventory(inventory);
|
||||||
|
|
||||||
|
if (gui == null || gui.inventory == null) return;
|
||||||
|
|
||||||
|
for (OnClose onClose : gui.onCloses) {
|
||||||
|
onClose.OnClose((Player) event.getPlayer(), inventory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractGUI getGUIFromInventory(Inventory inventory) {
|
||||||
|
if (inventory.getHolder() == null) return null;
|
||||||
|
InventoryHolder holder = inventory.getHolder();
|
||||||
|
if (!(holder instanceof GUIHolder)) return null;
|
||||||
|
|
||||||
|
return ((AbstractGUI.GUIHolder) holder).getGUI();
|
||||||
|
}
|
||||||
|
}, plugin);
|
||||||
|
listenersInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(String title, int slots) {
|
||||||
|
if (inventory == null
|
||||||
|
|| inventory.getSize() != slots
|
||||||
|
|| ChatColor.translateAlternateColorCodes('&', title) != player.getOpenInventory().getTitle()) {
|
||||||
|
this.inventory = Bukkit.getServer().createInventory(new GUIHolder(), slots, Methods.formatText(title));
|
||||||
|
this.setTitle = Methods.formatText(title);
|
||||||
|
if (this.clickables.size() == 0)
|
||||||
|
registerClickables();
|
||||||
|
if (this.onCloses.size() == 0)
|
||||||
|
registerOnCloses();
|
||||||
|
}
|
||||||
|
constructGUI();
|
||||||
|
initializeListeners(SongodaUpdate.getHijackedPlugin());
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void constructGUI();
|
||||||
|
|
||||||
|
protected void addDraggable(Range range, boolean option) {
|
||||||
|
this.draggableRanges.put(range, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeDraggable() {
|
||||||
|
this.draggableRanges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void registerClickables();
|
||||||
|
|
||||||
|
protected abstract void registerOnCloses();
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, Inventory inventory, ItemStack item, String name, String... lore) {
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
meta.setDisplayName(Methods.formatText(name));
|
||||||
|
if (lore != null && lore.length != 0) {
|
||||||
|
List<String> newLore = new ArrayList<>();
|
||||||
|
for (String line : lore) {
|
||||||
|
for (String string : line.split("\\s*\\r?\\n\\s*")) {
|
||||||
|
int lastIndex = 0;
|
||||||
|
for (int n = 0; n < string.length(); n++) {
|
||||||
|
if (n - lastIndex < 35)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (string.charAt(n) == ' ') {
|
||||||
|
newLore.add(Methods.formatText("&7" + string.substring(lastIndex, n).trim()));
|
||||||
|
lastIndex = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastIndex - string.length() < 35)
|
||||||
|
newLore.add(Methods.formatText("&7" + string.substring(lastIndex, string.length()).trim()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
meta.setLore(newLore);
|
||||||
|
}
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
inventory.setItem(slot, item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, ItemStack item, String name, ArrayList<String> lore) {
|
||||||
|
return createButton(slot, inventory, item, name, lore.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, ItemStack item, String name, String... lore) {
|
||||||
|
return createButton(slot, inventory, item, name, lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, Object item, String name, String... lore) {
|
||||||
|
if (item instanceof ItemStack)
|
||||||
|
return createButton(slot, inventory, (ItemStack) item, name, lore);
|
||||||
|
else
|
||||||
|
return createButton(slot, inventory, (Material) item, name, lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, Inventory inventory, Material material, String name, String... lore) {
|
||||||
|
return createButton(slot, inventory, new ItemStack(material), name, lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, Material material, String name, String... lore) {
|
||||||
|
return createButton(slot, inventory, new ItemStack(material), name, lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemStack createButton(int slot, Material material, String name, ArrayList<String> lore) {
|
||||||
|
return createButton(slot, material, name, lore.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerClickable(int min, int max, ClickType clickType, boolean bottom, Clickable clickable) {
|
||||||
|
clickables.put(new Range(min, max, clickType, bottom), clickable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerClickable(int min, int max, ClickType clickType, Clickable clickable) {
|
||||||
|
registerClickable(min, max, clickType, false, clickable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerClickable(int slot, ClickType clickType, Clickable clickable) {
|
||||||
|
registerClickable(slot, slot, clickType, false, clickable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerClickable(int min, int max, Clickable clickable) {
|
||||||
|
registerClickable(min, max, null, false, clickable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerClickable(int slot, boolean bottom, Clickable clickable) {
|
||||||
|
registerClickable(slot, slot, null, bottom, clickable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerClickable(int slot, Clickable clickable) {
|
||||||
|
registerClickable(slot, slot, null, false, clickable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void resetClickables() {
|
||||||
|
clickables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerOnClose(OnClose onClose) {
|
||||||
|
onCloses.add(onClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getInventory() {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GUIHolder implements InventoryHolder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Inventory getInventory() {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractGUI getGUI() {
|
||||||
|
return AbstractGUI.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSetTitle() {
|
||||||
|
return setTitle;
|
||||||
|
}
|
||||||
|
}
|
11
src/main/java/com/songoda/update/utils/gui/Clickable.java
Normal file
11
src/main/java/com/songoda/update/utils/gui/Clickable.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.songoda.update.utils.gui;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public interface Clickable {
|
||||||
|
|
||||||
|
void Clickable(Player player, Inventory inventory, ItemStack cursor, int slot, ClickType type);
|
||||||
|
}
|
10
src/main/java/com/songoda/update/utils/gui/OnClose.java
Normal file
10
src/main/java/com/songoda/update/utils/gui/OnClose.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package com.songoda.update.utils.gui;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
|
||||||
|
public interface OnClose {
|
||||||
|
|
||||||
|
void OnClose(Player player, Inventory inventory);
|
||||||
|
|
||||||
|
}
|
51
src/main/java/com/songoda/update/utils/gui/Range.java
Normal file
51
src/main/java/com/songoda/update/utils/gui/Range.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.songoda.update.utils.gui;
|
||||||
|
|
||||||
|
import com.songoda.update.SongodaUpdate;
|
||||||
|
import com.songoda.update.utils.ServerVersion;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
|
||||||
|
public class Range {
|
||||||
|
|
||||||
|
private int min;
|
||||||
|
private int max;
|
||||||
|
private ClickType clickType;
|
||||||
|
private boolean bottom;
|
||||||
|
private Sound onClickSound;
|
||||||
|
|
||||||
|
public Range(int min, int max, ClickType clickType, boolean bottom) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.clickType = clickType;
|
||||||
|
this.bottom = bottom;
|
||||||
|
if (SongodaUpdate.getInstance().isServerVersionAtLeast(ServerVersion.V1_9)) onClickSound = Sound.UI_BUTTON_CLICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range(int min, int max, Sound onClickSound, ClickType clickType, boolean bottom) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.onClickSound = onClickSound;
|
||||||
|
this.clickType = clickType;
|
||||||
|
this.bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClickType getClickType() {
|
||||||
|
return clickType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBottom() {
|
||||||
|
return bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sound getOnClickSound() {
|
||||||
|
return onClickSound;
|
||||||
|
}
|
||||||
|
}
|
100
src/main/java/com/songoda/update/utils/version/NMSUtil.java
Normal file
100
src/main/java/com/songoda/update/utils/version/NMSUtil.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package com.songoda.update.utils.version;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public class NMSUtil {
|
||||||
|
|
||||||
|
public static String getVersion() {
|
||||||
|
String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||||
|
return name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getVersionNumber() {
|
||||||
|
String name = getVersion().substring(3);
|
||||||
|
return Integer.valueOf(name.substring(0, name.length() - 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getVersionReleaseNumber() {
|
||||||
|
String NMSVersion = getVersion();
|
||||||
|
return Integer.valueOf(NMSVersion.substring(NMSVersion.length() - 2).replace(".", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<?> getNMSClass(String className) {
|
||||||
|
try {
|
||||||
|
String fullName = "net.minecraft.server." + getVersion() + className;
|
||||||
|
Class<?> clazz = Class.forName(fullName);
|
||||||
|
return clazz;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<?> getCraftClass(String className) throws ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
|
||||||
|
Class<?> clazz = Class.forName(fullName);
|
||||||
|
return clazz;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field getField(Class<?> clazz, String name, boolean declared) {
|
||||||
|
try {
|
||||||
|
Field field;
|
||||||
|
|
||||||
|
if (declared) {
|
||||||
|
field = clazz.getDeclaredField(name);
|
||||||
|
} else {
|
||||||
|
field = clazz.getField(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
return field;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getFieldObject(Object object, Field field) {
|
||||||
|
try {
|
||||||
|
return field.get(object);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setField(Object object, String fieldName, Object fieldValue, boolean declared) {
|
||||||
|
try {
|
||||||
|
Field field;
|
||||||
|
|
||||||
|
if (declared) {
|
||||||
|
field = object.getClass().getDeclaredField(fieldName);
|
||||||
|
} else {
|
||||||
|
field = object.getClass().getField(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(object, fieldValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendPacket(Player player, Object packet) {
|
||||||
|
try {
|
||||||
|
Object handle = player.getClass().getMethod("getHandle").invoke(player);
|
||||||
|
Object playerConnection = handle.getClass().getField("playerConnection").get(handle);
|
||||||
|
playerConnection.getClass().getMethod("sendPacket", getNMSClass("Packet")).invoke(playerConnection, packet);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user