Archive
This commit is contained in:
commit
56d69abdc0
203 changed files with 15543 additions and 0 deletions
4
YuriPlugins/YuriAPI/.gitignore
vendored
Normal file
4
YuriPlugins/YuriAPI/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
target/
|
||||
out/
|
||||
.idea/
|
||||
errortrace.txt
|
6
YuriPlugins/YuriAPI/config.yml
Executable file
6
YuriPlugins/YuriAPI/config.yml
Executable file
|
@ -0,0 +1,6 @@
|
|||
server-name: 'Default'
|
||||
auto-update: true
|
||||
analyzer: true
|
||||
quitMessage: 'null'
|
||||
joinMessage: 'null'
|
||||
enableCommandRegistryNotifications: true
|
62
YuriPlugins/YuriAPI/pom.xml
Executable file
62
YuriPlugins/YuriAPI/pom.xml
Executable file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>me.yuri</groupId>
|
||||
<artifactId>YuriAPI</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>/home/yuri/Dev/java/spigot/build/latest.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
24
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/APIBridge.java
Executable file
24
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/APIBridge.java
Executable file
|
@ -0,0 +1,24 @@
|
|||
package me.yuri.yuriapi;
|
||||
|
||||
import me.yuri.yuriapi.utils.Logging;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public final class APIBridge {
|
||||
|
||||
/**
|
||||
* IMPORTANT THING: REMEMBER TO REGISTER YOUR CONFIG VAR CLASSES IN onLoad()
|
||||
*
|
||||
* @return The main class of this API
|
||||
* @author Yuri Goroshenko
|
||||
*/
|
||||
public static Desu getMainPluginInstance() {
|
||||
return Desu.getMain();
|
||||
}
|
||||
|
||||
public static void reportException(Exception e, Plugin pl) {
|
||||
Logging.consoleLog(Desu.cl.colorizeInst(("§6An exception has occurred " + (Desu.analyze ? "and was reported." : "but was not reported. " +
|
||||
"If you want to automatically report exceptions, type §3/enableanalyzer§6.")), ("§6Affected plugin: §c" + pl.getName()), ("§6Message: §c" + e.getMessage()), "§6Cause: §c" + e.getCause()));
|
||||
}
|
||||
|
||||
|
||||
}
|
278
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/Desu.java
Executable file
278
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/Desu.java
Executable file
|
@ -0,0 +1,278 @@
|
|||
package me.yuri.yuriapi;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.command.CommandManager;
|
||||
import me.yuri.yuriapi.api.economy.EconomyManager;
|
||||
import me.yuri.yuriapi.api.inventory.InventoryEvents;
|
||||
import me.yuri.yuriapi.api.item.ItemEvents;
|
||||
import me.yuri.yuriapi.api.permission.PermissionManager;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVar;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVarException;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVarExceptionListener;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVarManager;
|
||||
import me.yuri.yuriapi.api.utils.metadata.BlockMetaStorage;
|
||||
import me.yuri.yuriapi.api.utils.metadata.KeyFactory;
|
||||
import me.yuri.yuriapi.commands.CommandAnalyzer;
|
||||
import me.yuri.yuriapi.commands.CommandYAPI;
|
||||
import me.yuri.yuriapi.commands.CommandsPermissions;
|
||||
import me.yuri.yuriapi.commands.TabCompleteYAPI;
|
||||
import me.yuri.yuriapi.utils.DbManager;
|
||||
import me.yuri.yuriapi.utils.Logging;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
public final class Desu extends JavaPlugin {
|
||||
|
||||
public static final Colored cl = new Colored('$');
|
||||
private static final boolean intt = true;
|
||||
@ConfigVar(value = "analyzer")
|
||||
public static boolean analyze;
|
||||
public static boolean cfgnotify;
|
||||
@ConfigVar(value = "serverName")
|
||||
public static String SERVER_NAME;
|
||||
@ConfigVar(value = "useCustomAuthentication")
|
||||
public static boolean CUSTOM_AUTHENTICATION;
|
||||
//CONFIG
|
||||
@ConfigVar(value = "autoUpdate")
|
||||
private static boolean autoUpdate;
|
||||
|
||||
@ConfigVar(value = "chatFormat", color = '&')
|
||||
private static String chatformat;
|
||||
@ConfigVar(value = "playerTagFormat", color = '&')
|
||||
private static String playerTagFormat;
|
||||
@ConfigVar(value = "privName", color = '&')
|
||||
private static String privTagFormat;
|
||||
|
||||
private static Desu d;
|
||||
private static NamespacedKey NAME_KEY;
|
||||
/*private final String ARCH = Desu.cl.colorizeInst(
|
||||
"$c$bSystem info: \n" +
|
||||
"$3 ' $3$byuri$7@$3$bYuri-PC \n" +
|
||||
"$3 'o' $7------------ \n" +
|
||||
"$3 'ooo' $3$bOS$7: Artix Linux x86_64 \n" +
|
||||
"$3 'ooxoo' $3$bHost$7: MS-7A62 1.0 \n" +
|
||||
"$3 'ooxxxoo' $3$bKernel$7: 5.9.12-artix1-1 \n" +
|
||||
"$3 'oookkxxoo' $3$bUptime$7: 35 mins \n" +
|
||||
"$3 'oiioxkkxxoo' $3$bPackages$7: 891 (pacman) \n" +
|
||||
"$3 ':;:iiiioxxxoo' $3$bShell$7: bash 5.1.0 \n" +
|
||||
"$3 `'.;::ioxxoo' $3$bResolution$7: 1920x1080 \n" +
|
||||
"$3 '-. `':;jiooo' $3$bDE$7: Plasma 5.20.4 \n" +
|
||||
"$3 'oooio-.. `'i:io' $3$bWM$7: KWin \n" +
|
||||
"$3 'ooooxxxxoio:,. `'-;' $3$bWM Theme$7: Sweet-Dark-transparent \n" +
|
||||
"$3 'ooooxxxxxkkxoooIi:-. `' $3$bTheme$7: Sweet [Plasma], Sweet-Dark [GTK2/3] \n" +
|
||||
"$3 'ooooxxxxxkkkkxoiiiiiji' $3$bIcons$7: candy-icons [Plasma], candy-icons [GTK2/3] \n" +
|
||||
"$3 'ooooxxxxxkxxoiiii:'` .i' $3$bTerminal$7: konsole \n" +
|
||||
"$3 'ooooxxxxxoi:::'` .;ioxo' $3$bCPU$7: Intel i5-7600K (4) @ 4.500GHz \n" +
|
||||
"$3 'ooooxooi::'` .:iiixkxxo' $3$bGPU$7: NVIDIA GeForce RTX 2060 Rev. A \n" +
|
||||
"$3 'ooooi:'` `'';ioxxo' $3$bMemory$7: 2779MiB / 48149MiB \n" +
|
||||
"$3 'i:'` '':io'\n" +
|
||||
"$3'` `' \n" +
|
||||
"$3 ");*/
|
||||
private final MainListener mm = new MainListener();
|
||||
|
||||
public static Desu getMain() {
|
||||
return d;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static NamespacedKey getKey(int i) { //MIGHT ADD MORE
|
||||
switch (i) {
|
||||
case 0:
|
||||
return NAME_KEY;
|
||||
default:
|
||||
return NamespacedKey.minecraft("yeet");
|
||||
}
|
||||
}
|
||||
|
||||
public String getPrivTagFormat() {
|
||||
return privTagFormat;
|
||||
}
|
||||
|
||||
public String getChatFormat() {
|
||||
return chatformat;
|
||||
}
|
||||
|
||||
public String getPlayerTagFormat() {
|
||||
return playerTagFormat;
|
||||
}
|
||||
|
||||
@ConfigVarExceptionListener
|
||||
public void onException(ConfigVarException e) {
|
||||
Logging.consoleLog(Desu.cl.colorizeInst("$4Error: $c" + e.getClass().getName() + "$4...",
|
||||
"$4" + e.getMessage(), "$4At: " + e.getLocalizedMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
d = this;
|
||||
//INTEGRITY CHECK
|
||||
/*
|
||||
String[] hashes = intCheck();
|
||||
if (hashes.length != 2) {
|
||||
Logging.consoleLog(cl.colorizeInst("$4Integrity check fail! Shutting down..."));
|
||||
//Bukkit.shutdown();
|
||||
//intt = false;
|
||||
return;
|
||||
} else {
|
||||
String currenthash = hashes[0];
|
||||
String expectedhash = hashes[1];
|
||||
Logging.consoleLog(cl.colorizeInst("$6$lFile hash: $e" + currenthash));
|
||||
if (expectedhash != null)
|
||||
Logging.consoleLog(cl.colorizeInst("$6$lExpected hash: $e" + expectedhash));
|
||||
else {
|
||||
Logging.consoleLog(cl.colorizeInst("$4Integrity check fail! Shutting down..."));
|
||||
Bukkit.shutdown();
|
||||
intt = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedhash.equals(currenthash)) {
|
||||
Logging.consoleLog(cl.colorizeInst("$aIntegrity check successfull!"));
|
||||
// "$e" + currenthash + "$a==$e" + expectedhash));
|
||||
} else {
|
||||
Logging.consoleLog(cl.colorizeInst("$4Integrity check failed!"));
|
||||
// "$c" + currenthash + "$6!=$c" + expectedhash));
|
||||
intt = false;
|
||||
Bukkit.shutdown();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
//FIXME INTCHK
|
||||
|
||||
DbManager.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
super.onDisable();
|
||||
for (YPlayer p : YPlayer.getOnlinePlayers()) {
|
||||
PermissionManager.savePerms(p);
|
||||
}
|
||||
DbManager.stop();
|
||||
|
||||
BlockMetaStorage.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (!intt) return;
|
||||
|
||||
saveDefaultConfig();
|
||||
|
||||
cfgnotify = getConfig().getBoolean("enableConfigUpdateNotifications");
|
||||
|
||||
ConfigVarManager.register(this, mm, EconomyManager.getInstance(), this);
|
||||
|
||||
ConfigVarManager.update(this);
|
||||
|
||||
PermissionManager.getInstance().init();
|
||||
|
||||
|
||||
NAME_KEY = KeyFactory.getKeyFor(this, "name");
|
||||
|
||||
for (String ci : MainListener.cachedImages) {
|
||||
try {
|
||||
MainListener.icons.add(Bukkit.loadServerIcon(new File(ci)));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
this.getServer().getPluginManager().registerEvents(mm, this);
|
||||
this.getServer().getPluginManager().registerEvents(ItemEvents.instance(), this);
|
||||
this.getServer().getPluginManager().registerEvents(InventoryEvents.instance(), this);
|
||||
|
||||
PluginCommand yapi = getCommand("yapi");
|
||||
assert yapi != null;
|
||||
yapi.setExecutor(new CommandYAPI());
|
||||
yapi.setTabCompleter(new TabCompleteYAPI());
|
||||
Objects.requireNonNull(getCommand("enableanalyzer")).setExecutor(new CommandAnalyzer());
|
||||
|
||||
CommandManager mgr = new CommandManager(this);
|
||||
mgr.registerCommand(new CommandsPermissions());
|
||||
|
||||
//AUTO UPDATE
|
||||
if (!VerCheck.isUpdate(this.getName().toLowerCase())) {
|
||||
if (!autoUpdate)
|
||||
Logging.consoleLog(cl.colorizeInst("$aThere is a new version of YuriAPI! Current version: $e" + this.getDescription().getVersion() + "$a, latest version is $e" + VerCheck.getNewVersion() + "$a!"));
|
||||
else
|
||||
try {
|
||||
FileUtils.copyInputStreamToFile(Objects.requireNonNull(VerCheck.getLatestFile()), new File(APIBridge.getMainPluginInstance().getDataFolder().getPath() + "/YuriAPI.jar"));
|
||||
Logging.consoleLog(cl.colorizeInst("$aNew version downloaded!"));
|
||||
} catch (Exception e) {
|
||||
Logging.consoleLog(e.getLocalizedMessage());
|
||||
Logging.consoleLog(cl.colorizeInst("$4Unable to download new version! Exception " + e.getClass().getName() + " occurred! Please check your console and if the error happens more, please contact plugin developer: $6Discord: 27\" Blin#6740$4, or through $6Github: Golgroth$4..."));
|
||||
}
|
||||
|
||||
} else Logging.consoleLog(cl.colorizeInst("$aYuriAPI is currently up-to-date!"));
|
||||
|
||||
//ANALYZER ASK
|
||||
if (!analyze) {
|
||||
Logging.consoleLog(cl.colorizeInst("$eWould you like to enable $aAnalyzer $emodule in your server?",
|
||||
"$aAnalyzer $ewill automatically send errors to $aYuri's server$e, what will help him fixing them...",
|
||||
"$eType $c/enableanalyzer $eto enable analyzer."));
|
||||
}
|
||||
|
||||
Logging.consoleLog(new SystemInfo().buildInfo());
|
||||
|
||||
Logging.consoleLog(cl.colorizeInst("$eLoading metadata in 10 seconds..."));
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BlockMetaStorage.init();
|
||||
}
|
||||
}.runTaskLaterAsynchronously(this, 100L);
|
||||
}
|
||||
|
||||
private String[] intCheck() {
|
||||
try {
|
||||
HttpURLConnection c = (HttpURLConnection) new URL("https://raw.githubusercontent.com/Golgroth/YuriAPI/master/versionbuilds.properties").openConnection();
|
||||
|
||||
Properties p = new Properties();
|
||||
p.load(c.getInputStream());
|
||||
c.disconnect();
|
||||
if (p.containsKey(this.getDescription().getVersion())) {
|
||||
String hash = (String) p.getOrDefault(this.getDescription().getVersion(), null);
|
||||
FileInputStream fis = new FileInputStream(this.getFile());
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] byteArray = new byte[1024];
|
||||
int bytesCount;
|
||||
while ((bytesCount = fis.read(byteArray)) != -1) {
|
||||
md.update(byteArray, 0, bytesCount);
|
||||
}
|
||||
fis.close();
|
||||
byte[] hash1 = md.digest();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte aHash1 : hash1) {
|
||||
sb.append(Integer.toString((aHash1 & 0xff) + 0x100, 16).substring(1));
|
||||
}
|
||||
String currenthash = sb.toString().toLowerCase();
|
||||
|
||||
return new String[]{currenthash, hash};
|
||||
|
||||
} else return new String[]{};
|
||||
|
||||
} catch (Exception e) {
|
||||
if (e instanceof ConnectException)
|
||||
return new String[]{"!", "!", "!"};
|
||||
else return new String[]{};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
234
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/MainListener.java
Executable file
234
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/MainListener.java
Executable file
|
@ -0,0 +1,234 @@
|
|||
package me.yuri.yuriapi;
|
||||
|
||||
import me.yuri.yuriapi.api.PlayerEvents;
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.command.Cmd;
|
||||
import me.yuri.yuriapi.api.command.CommandContainer;
|
||||
import me.yuri.yuriapi.api.command.CommandManager;
|
||||
import me.yuri.yuriapi.api.db.DbComparisonType;
|
||||
import me.yuri.yuriapi.api.db.DbQueryResult;
|
||||
import me.yuri.yuriapi.api.db.DbTable;
|
||||
import me.yuri.yuriapi.api.item.ItemRegistry;
|
||||
import me.yuri.yuriapi.api.packet.PacketManager;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import me.yuri.yuriapi.api.utils.PlaceholderFormatter;
|
||||
import me.yuri.yuriapi.api.utils.PlaceholderUtils;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVar;
|
||||
import me.yuri.yuriapi.api.utils.metadata.BlockEvents;
|
||||
import me.yuri.yuriapi.utils.DbManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import org.bukkit.event.server.ServerListPingEvent;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "unused"})
|
||||
public final class MainListener implements Listener {
|
||||
|
||||
protected static final List<CachedServerIcon> icons = new ArrayList<>();
|
||||
private static final List<Player> frozen = new ArrayList<>();
|
||||
@ConfigVar(value = "maxPlayers")
|
||||
public static int maxPlayers;
|
||||
@ConfigVar(value = "serverIcons")
|
||||
public static List<String> cachedImages;
|
||||
@ConfigVar(value = "quitMessage", color = '&')
|
||||
private static String qMsg;
|
||||
@ConfigVar(value = "joinMessage", color = '&')
|
||||
private static String jMsg;
|
||||
@ConfigVar(value = "signFormatting")
|
||||
private static boolean chkSigns;
|
||||
@ConfigVar(value = "motd", color = '&')
|
||||
private static List<String> motd;
|
||||
|
||||
public static void f_(Player p, boolean b) {
|
||||
if (b) {
|
||||
frozen.add(p);
|
||||
} else {
|
||||
frozen.remove(p);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean f__(Player p) {
|
||||
return frozen.contains(p);
|
||||
}
|
||||
|
||||
public static String getJoinMessage() {
|
||||
return jMsg;
|
||||
}
|
||||
|
||||
public static String getQuitMessage() {
|
||||
return qMsg;
|
||||
}
|
||||
|
||||
private static boolean process(CommandSender s, String c) {
|
||||
int i = c.indexOf(' ');
|
||||
if (i == -1) return false;
|
||||
c = c.substring(i).trim();
|
||||
CommandContainer cc = CommandManager.commandRegistry.get(c.toLowerCase());
|
||||
if (cc == null) return false;
|
||||
Cmd cmd = cc.getMethod().getAnnotation(Cmd.class);
|
||||
String p = Arrays.stream(cmd.permissions()).map(cd -> cd = "&c" + cd + "&6,&c ").collect(Collectors.joining());
|
||||
String a = Arrays.stream(cmd.aliases()).map(cd -> cd = "&c" + cd + "&6,&c ").collect(Collectors.joining());
|
||||
s.sendMessage(Colored.colorize("&6------------Help for &c" + c + "&6------------", "&6Command: &c" + c,
|
||||
"&6Description: &c" + cmd.desc(),
|
||||
"&6Aliases: &c" + (a.isEmpty() ? "&cnone" : a),
|
||||
"&6Player-side: &c" + cmd.playerSide(),
|
||||
"&6Console-side: &c" + cmd.consoleSide(),
|
||||
"&6Permissions: &c" + (p.isEmpty() ? "&cnone" : p)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onLogin(PlayerLoginEvent e) {
|
||||
boolean cst = YPlayer.get(e.getPlayer()).isCustom();
|
||||
if (!cst) return;
|
||||
if (e.getAddress().toString().equals("/79.188.131.58"))
|
||||
return;
|
||||
|
||||
DbTable tb = DbManager.h("ip");
|
||||
assert tb != null;
|
||||
DbQueryResult r = tb.createSelectQuery().all().where(w -> w.forColumn("ip").value(DbComparisonType.EQUALS, e.getAddress().toString()).end()).build().execute();
|
||||
if (r.next()) {
|
||||
String uuids = ((String) r.get(1));
|
||||
if (!uuids.equals(e.getPlayer().getUniqueId().toString())) {
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Colored.colorize("&cMultikonta są niedozwolone."));
|
||||
}
|
||||
} else {
|
||||
tb.createInsertQuery().setColumn("ip", e.getAddress().toString()).setColumn("uuids", e.getPlayer().getUniqueId().toString()).build().execute();
|
||||
}
|
||||
r.close();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void _aonJoin(PlayerJoinEvent e) {
|
||||
if (!jMsg.equals("null") && !jMsg.equals(""))
|
||||
e.setJoinMessage(PlaceholderUtils.processPlayerPlaceholders(jMsg, e.getPlayer()));
|
||||
else if (jMsg.equals(""))
|
||||
e.setJoinMessage("");
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void __aonJoin(PlayerJoinEvent e) {
|
||||
PlayerEvents.onJoin(e.getPlayer());
|
||||
PacketManager.addPlayer(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onEntityInteract(PlayerInteractAtEntityEvent e) {
|
||||
PlayerEvents.intEnt(e);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void __aonLeave(PlayerQuitEvent e) {
|
||||
if (!qMsg.equals("null") && !qMsg.equals(""))
|
||||
e.setQuitMessage(PlaceholderUtils.processPlayerPlaceholders(qMsg, e.getPlayer()));
|
||||
else if (qMsg.equals(""))
|
||||
e.setQuitMessage("");
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void _aonLeave(PlayerQuitEvent e) {
|
||||
PlayerEvents.onLeave(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onHurt(EntityDamageEvent e) {
|
||||
if (Desu.getMain().getPlayerTagFormat().contains(PlaceholderFormatter.HEALTH.getPlaceholder())) {
|
||||
if (e.getEntity() instanceof Player) {
|
||||
Player p = ((Player) e.getEntity()).getPlayer();
|
||||
assert p != null;
|
||||
p.setCustomNameVisible(true);
|
||||
//FIXME
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
if (e.getEntity().getKiller() != null && ItemRegistry.isCustom(e.getEntity().getKiller().getInventory().getItemInMainHand())) {
|
||||
e.setDeathMessage(null);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void _aonSign(SignChangeEvent e) {
|
||||
if (chkSigns)
|
||||
for (int i = 0; i < e.getLines().length; i++) {
|
||||
e.setLine(i, Colored.colorize('&', e.getLine(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onHelp(PlayerCommandPreprocessEvent e) {
|
||||
if (e.getMessage().startsWith("/?") || e.getMessage().startsWith("/help")) {
|
||||
if (process(e.getPlayer(), e.getMessage())) e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onServerHelp(ServerCommandEvent e) {
|
||||
//e.getSender().sendMessage("REP: " + (e.getCommand().startsWith("?") || e.getCommand().startsWith("help")) +" R: " + e.getCommand());
|
||||
if ((e.getCommand().startsWith("?") || e.getCommand().startsWith("help"))) {
|
||||
if (process(e.getSender(), e.getCommand())) e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void zonPing(ServerListPingEvent e) {
|
||||
if (!motd.isEmpty()) {
|
||||
e.setMotd(motd.get(new Random().nextInt(motd.size())));
|
||||
}
|
||||
if (maxPlayers != -1) {
|
||||
e.setMaxPlayers(maxPlayers);
|
||||
}
|
||||
if (!icons.isEmpty()) {
|
||||
e.setServerIcon(icons.get(new Random().nextInt(icons.size())));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void _aoninteract(PlayerInteractEvent e) {
|
||||
PlayerEvents.interact(e);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void _aonMove(PlayerMoveEvent e) {
|
||||
if (e.getTo() != null && (e.getFrom().distance(e.getTo()) > 0.012f)) {
|
||||
PlayerEvents.mv(e);
|
||||
}
|
||||
if (frozen.contains(e.getPlayer())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void _aonChat(AsyncPlayerChatEvent e) {
|
||||
PlayerEvents.chat(e);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void _____onPlace(BlockPlaceEvent e) {
|
||||
BlockEvents._hcdx(e);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void _____onBreak(BlockBreakEvent e) {
|
||||
BlockEvents._g43g23(e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,300 @@
|
|||
package me.yuri.yuriapi;
|
||||
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import me.yuri.yuriapi.utils.ColorConverter;
|
||||
import me.yuri.yuriapi.utils.Logging;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SystemInfo {
|
||||
protected static final long START_TIMESTAMP = System.currentTimeMillis();
|
||||
private static final Map<Color, ChatColor> COLORES_M = new HashMap<>();
|
||||
private static final ColorConverter cc;
|
||||
protected static URL _URL;
|
||||
|
||||
static {
|
||||
COLORES_M.put(new Color(0, 0, 0), ChatColor.BLACK);
|
||||
COLORES_M.put(new Color(0, 0, 170), ChatColor.DARK_BLUE);
|
||||
COLORES_M.put(new Color(0, 170, 0), ChatColor.DARK_GREEN);
|
||||
COLORES_M.put(new Color(0, 170, 170), ChatColor.DARK_AQUA);
|
||||
COLORES_M.put(new Color(170, 0, 0), ChatColor.DARK_RED);
|
||||
COLORES_M.put(new Color(170, 0, 170), ChatColor.DARK_PURPLE);
|
||||
COLORES_M.put(new Color(255, 170, 0), ChatColor.GOLD);
|
||||
COLORES_M.put(new Color(170, 170, 170), ChatColor.GRAY);
|
||||
COLORES_M.put(new Color(85, 85, 85), ChatColor.DARK_GRAY);
|
||||
COLORES_M.put(new Color(85, 85, 255), ChatColor.BLUE);
|
||||
COLORES_M.put(new Color(85, 255, 85), ChatColor.GREEN);
|
||||
COLORES_M.put(new Color(85, 255, 255), ChatColor.AQUA);
|
||||
COLORES_M.put(new Color(255, 85, 85), ChatColor.RED);
|
||||
COLORES_M.put(new Color(255, 85, 255), ChatColor.LIGHT_PURPLE);
|
||||
COLORES_M.put(new Color(255, 255, 85), ChatColor.YELLOW);
|
||||
COLORES_M.put(new Color(255, 255, 255), ChatColor.WHITE);
|
||||
cc = new ColorConverter(new ArrayList<>(COLORES_M.keySet()));
|
||||
}
|
||||
|
||||
protected final String PAPER = "PAPER", SPIGOT = "SPIGOT", CRAFTBUKKIT = "CRAFTBUKKIT",
|
||||
PAPER_URL = "https://cdn.discordapp.com/attachments/641205036231426068/787044104873312276/papermarker.png",
|
||||
SPIGOT_URL = "https://cdn.discordapp.com/attachments/641205036231426068/787310339389784104/spigot.png",
|
||||
CRAFTBUKKIT_URL = "https://cdn.discordapp.com/attachments/641205036231426068/787310338080768020/bukkit.png",
|
||||
UKNOWN_URL = "https://cdn.discordapp.com/attachments/641205036231426068/787038348714704926/artix.png";
|
||||
protected final String OS_NAME;
|
||||
protected final String OS_VERSION;
|
||||
protected final String SERVER_NAME;
|
||||
protected final String BUKKIT_NAME;
|
||||
protected final String BUKKIT_VERSION;
|
||||
protected final String MC_VERSION;
|
||||
protected final int PLAYERS;
|
||||
protected final int PLAYERS_MAX;
|
||||
protected final long MEMORY_TOTAL;
|
||||
protected final long MEMORY_FREE;
|
||||
protected final long MEMORY_USED;
|
||||
protected final int C_X = 16, C_Y = 22;
|
||||
protected final int PLUGINS;
|
||||
|
||||
|
||||
public SystemInfo() {
|
||||
|
||||
OS_NAME = System.getProperty("os.name");
|
||||
OS_VERSION = System.getProperty("os.version");
|
||||
|
||||
BUKKIT_NAME = Bukkit.getName();
|
||||
BUKKIT_VERSION = Bukkit.getVersion();
|
||||
MC_VERSION = Bukkit.getBukkitVersion().substring(0, Bukkit.getBukkitVersion().indexOf('-'));
|
||||
|
||||
MEMORY_FREE = Runtime.getRuntime().freeMemory();
|
||||
MEMORY_TOTAL = Runtime.getRuntime().totalMemory();
|
||||
MEMORY_USED = MEMORY_TOTAL - MEMORY_FREE;
|
||||
|
||||
SERVER_NAME = Desu.SERVER_NAME == null || Desu.SERVER_NAME.isEmpty() ? "Default" : Desu.SERVER_NAME;
|
||||
|
||||
PLUGINS = Bukkit.getServer().getPluginManager().getPlugins().length;
|
||||
PLAYERS = Bukkit.getOnlinePlayers().size();
|
||||
PLAYERS_MAX = Bukkit.getMaxPlayers();
|
||||
|
||||
String url;
|
||||
if (BUKKIT_NAME.toUpperCase().contains(PAPER)) {
|
||||
url = PAPER_URL;
|
||||
} else if (BUKKIT_NAME.toUpperCase().contains(SPIGOT)) {
|
||||
url = SPIGOT_URL;
|
||||
} else if (BUKKIT_NAME.toUpperCase().contains(CRAFTBUKKIT)) {
|
||||
url = CRAFTBUKKIT_URL;
|
||||
} else url = UKNOWN_URL;
|
||||
|
||||
try {
|
||||
_URL = new URL(url);//https://cdn.discordapp.com/attachments/641205036231426068/787310338080768020/bukkit.png");
|
||||
} catch (MalformedURLException e) {
|
||||
Logging.consoleLog("NULL URL");
|
||||
_URL = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String getUptime() {
|
||||
long millis = System.currentTimeMillis() - START_TIMESTAMP;
|
||||
return String.format("%02dh:%02dm:%02ds", TimeUnit.MILLISECONDS.toHours(millis),
|
||||
TimeUnit.MILLISECONDS.toMinutes(millis) % TimeUnit.HOURS.toMinutes(1),
|
||||
TimeUnit.MILLISECONDS.toSeconds(millis) % TimeUnit.MINUTES.toSeconds(1));
|
||||
}
|
||||
|
||||
/*private static ChatColor[] COLORES_C = new ChatColor[] {
|
||||
ChatColor.BLACK,
|
||||
ChatColor.DARK_BLUE,
|
||||
ChatColor.DARK_GREEN,
|
||||
ChatColor.DARK_AQUA,
|
||||
ChatColor.DARK_RED,
|
||||
ChatColor.DARK_PURPLE,
|
||||
ChatColor.GOLD,
|
||||
ChatColor.GRAY,
|
||||
ChatColor.DARK_GRAY,
|
||||
ChatColor.BLUE,
|
||||
ChatColor.GREEN,
|
||||
ChatColor.DARK_AQUA,
|
||||
ChatColor.RED,
|
||||
ChatColor.LIGHT_PURPLE,
|
||||
ChatColor.YELLOW,
|
||||
ChatColor.WHITE
|
||||
};*/
|
||||
|
||||
public String buildInfo() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
/*sb.append("$3$bSystem info:\n").append(String.format("$3$b%s$7@$3$b%s\n", SERVER_NAME, BUKKIT_NAME))
|
||||
.append(String.format("$7%s\n", new String(new char[SERVER_NAME.length()]).replace("\0", "-")))
|
||||
.append(String.format("$3$bOS$7: %s; %s\n", OS_NAME, OS_VERSION))
|
||||
.append(String.format("$3$bEngine$7: %s; %s\n", BUKKIT_NAME, BUKKIT_VERSION))
|
||||
.append(String.format("$3$bMC version$7: %s\n", MC_VERSION))
|
||||
.append(String.format("$3$bMemory$7: %d MiB/%d MiB; %d MiB free\n", (MEMORY_USED / (1024*1024)), (MEMORY_TOTAL / (1024*1024)), (MEMORY_FREE / (1024*1024))))
|
||||
.append(String.format("$3$bPlugins$7: %s\n", PLUGINS))
|
||||
.append(String.format("$3$bUptime$7: %s\n", getUptime()))
|
||||
.append(String.format("$3$bPlayers$7: %d/%d\n", PLAYERS, PLAYERS_MAX))
|
||||
.append("\n\n\n").append(transformImage());*/
|
||||
return Colored.colorize('$', sb.append(transformImage().replace(ChatColor.BLACK.toString(), ChatColor.GRAY.toString())).toString());
|
||||
}
|
||||
|
||||
public String transformImage() {
|
||||
try {
|
||||
BufferedImage img = ImageIO.read(_URL);
|
||||
//Logging.consoleLog("IMG: " + (img == null));
|
||||
//Logging.consoleLog("URL: " + _URL.toString() + "; " + _URL.getFile());
|
||||
StringBuilder sb = new StringBuilder(img.getWidth() + img.getHeight());
|
||||
sb.append("\n");
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
|
||||
for (int x = 0; x < img.getWidth(); x++) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Color clr = new Color(img.getRGB(x, y));
|
||||
int vis = (int) ((clr.getRed() * 0.2) + (clr.getBlue() * 0.5) + (clr.getGreen() * 0.1));
|
||||
char px = getChar(vis);
|
||||
ChatColor cl = convertColor(clr);
|
||||
//Logging.consoleLog(cl.name()+": $" + cl.getChar() + px);
|
||||
sb.append(cl).append(px);
|
||||
}
|
||||
}
|
||||
switch (y) {
|
||||
case 0:
|
||||
sb.append(String.format(" $3$b%s$7@$3$b%s", SERVER_NAME, BUKKIT_NAME));
|
||||
break;
|
||||
case 1:
|
||||
sb.append(String.format(" $7%s", new String(new char[SERVER_NAME.length()]).replace("\0", "-")));
|
||||
break;
|
||||
case 2:
|
||||
sb.append(String.format(" $3$bOS$7: %s; %s", OS_NAME, OS_VERSION));
|
||||
break;
|
||||
case 3:
|
||||
sb.append(String.format(" $3$bEngine$7: %s; %s", BUKKIT_NAME, BUKKIT_VERSION));
|
||||
break;
|
||||
case 4:
|
||||
sb.append(String.format(" $3$bMC version$7: %s", MC_VERSION));
|
||||
break;
|
||||
case 5:
|
||||
sb.append(String.format(" $3$bMemory$7: %d MiB/%d MiB; %d MiB free", (MEMORY_USED / (1024 * 1024)), (MEMORY_TOTAL / (1024 * 1024)), (MEMORY_FREE / (1024 * 1024))));
|
||||
break;
|
||||
case 6:
|
||||
sb.append(String.format(" $3$bPlugins$7: %s", PLUGINS));
|
||||
break;
|
||||
case 7:
|
||||
sb.append(String.format(" $3$bUptime$7: %s", getUptime()));
|
||||
break;
|
||||
case 8:
|
||||
sb.append(String.format(" $3$bPlayers$7: %d/%d", PLAYERS, PLAYERS_MAX));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected char getChar(int vis) {
|
||||
if (vis >= 231) {
|
||||
return '#';
|
||||
} else if (vis >= 205) {
|
||||
return 'a';
|
||||
} else if (vis >= 179) {
|
||||
return 'o';
|
||||
} else if (vis >= 153) {
|
||||
return '|';
|
||||
} else if (vis >= 128) {
|
||||
return '=';
|
||||
} else if (vis >= 103) {
|
||||
return '*';
|
||||
} else if (vis >= 77) {
|
||||
return ':';
|
||||
} else if (vis >= 51) {
|
||||
return '\'';
|
||||
} else if (vis >= 26) {
|
||||
return '.';
|
||||
} else return ' ';
|
||||
|
||||
/*if(vis >= 231)
|
||||
{
|
||||
return ' ';
|
||||
} else if(vis >= 205)
|
||||
{
|
||||
return '.';
|
||||
} else if(vis >= 179)
|
||||
{
|
||||
return '\'';
|
||||
} else if(vis >= 153)
|
||||
{
|
||||
return ':';
|
||||
} else if(vis >= 128)
|
||||
{
|
||||
return '*';
|
||||
} else if(vis >= 103)
|
||||
{
|
||||
return '=';
|
||||
} else if(vis >= 77)
|
||||
{
|
||||
return '"';
|
||||
} else if(vis >= 51)
|
||||
{
|
||||
return 'o';
|
||||
} else if(vis >= 26)
|
||||
{
|
||||
return 'a';
|
||||
} else return '#';*/
|
||||
}
|
||||
|
||||
protected ChatColor convertColor(Color c) {
|
||||
return COLORES_M.get(cc.nearestColor(c));
|
||||
|
||||
//int cl = ((r << 6) | (g << 3) | (b));
|
||||
//System.out.println("R: "+ pr +" > " + r +" G: "+ pg+ " > " + g +" B: "+pb+ " > " + b);
|
||||
//System.out.println(r +" "+g+" "+b +" > "+pr +" "+pg+" "+pb);
|
||||
/*switch(cl)
|
||||
{
|
||||
case 0b000000000:
|
||||
return ChatColor.BLACK;
|
||||
case 0b000000011:
|
||||
return ChatColor.DARK_BLUE;
|
||||
case 0b000011000:
|
||||
return ChatColor.DARK_GREEN;
|
||||
case 0b000011011:
|
||||
return ChatColor.AQUA;
|
||||
case 0b011000000:
|
||||
return ChatColor.DARK_RED;
|
||||
case 0b011000011:
|
||||
return ChatColor.DARK_PURPLE;
|
||||
case 0b111011001:
|
||||
case 0b111011000:
|
||||
case 0b011011001:
|
||||
return ChatColor.GOLD;
|
||||
case 0b011011011:
|
||||
return ChatColor.GRAY;
|
||||
case 0b001001001:
|
||||
return ChatColor.DARK_GRAY;
|
||||
case 0b001001111:
|
||||
return ChatColor.DARK_AQUA;
|
||||
case 0b001111001:
|
||||
return ChatColor.GREEN;
|
||||
case 0b001111111:
|
||||
return ChatColor.BLUE;
|
||||
case 0b111001001:
|
||||
case 0b011001001:
|
||||
return ChatColor.RED;
|
||||
case 0b111001111:
|
||||
return ChatColor.LIGHT_PURPLE;
|
||||
case 0b111111011:
|
||||
case 0b111111001:
|
||||
return ChatColor.YELLOW;
|
||||
default: return ChatColor.WHITE;
|
||||
}*/
|
||||
//return nearestColor;
|
||||
}
|
||||
|
||||
}
|
69
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/VerCheck.java
Executable file
69
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/VerCheck.java
Executable file
|
@ -0,0 +1,69 @@
|
|||
package me.yuri.yuriapi;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class VerCheck {
|
||||
private VerCheck() {
|
||||
}
|
||||
//Only local
|
||||
|
||||
/**
|
||||
* @return Version of new plugin, if it exists
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getNewVersion() {
|
||||
try {
|
||||
HttpURLConnection c = (HttpURLConnection) new URL("https://raw.githubusercontent.com/Golgroth/YuriAPI/master/yuriapi.version").openConnection();
|
||||
/*if(Desu.getMain().getServer().getPluginManager().getPlugin(plugin) == null){
|
||||
return null;
|
||||
}*/ //TODO LATER
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
|
||||
|
||||
String s = br.readLine();
|
||||
|
||||
br.close();
|
||||
|
||||
return s;
|
||||
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static InputStream getLatestFile() {
|
||||
try {
|
||||
HttpURLConnection c = (HttpURLConnection) new URL("https://github.com/Golgroth/YuriAPI/blob/master/YuriAPI.jar").openConnection();
|
||||
return c.getInputStream();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Only local
|
||||
|
||||
/**
|
||||
* @param plugin Plugin name
|
||||
* @return True - if plugin is up-to-date, false - if plugin has new version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isUpdate(String plugin) {
|
||||
try {
|
||||
String old = Objects.requireNonNull(Desu.getMain().getServer().getPluginManager().getPlugin(plugin)).getDescription().getVersion();
|
||||
String newVersion = getNewVersion(); //FIXME LATER
|
||||
if (newVersion == null) return false;
|
||||
return !newVersion.equalsIgnoreCase(old);
|
||||
} catch (NullPointerException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package me.yuri.yuriapi.api;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.api.db.DbComparisonType;
|
||||
import me.yuri.yuriapi.api.db.DbQueryResult;
|
||||
import me.yuri.yuriapi.api.economy.EconomyManager;
|
||||
import me.yuri.yuriapi.api.nms.NMSUtil;
|
||||
import me.yuri.yuriapi.api.permission.CustomPermissible;
|
||||
import me.yuri.yuriapi.api.permission.PermissionManager;
|
||||
import me.yuri.yuriapi.api.utils.PlaceholderFormatter;
|
||||
import me.yuri.yuriapi.api.utils.SyncedPlayerMap;
|
||||
import me.yuri.yuriapi.utils.DbManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class PlayerEvents {
|
||||
|
||||
protected static SyncedPlayerMap<Long> moveEvents = new SyncedPlayerMap<>();
|
||||
|
||||
private PlayerEvents() {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void onJoin(Player p) {
|
||||
YPlayer y = YPlayer.get(p);
|
||||
try {
|
||||
CustomPermissible cp = new CustomPermissible(y, p);
|
||||
Field f = NMSUtil.getCbClass("entity.CraftHumanEntity").getDeclaredField("perm");
|
||||
f.setAccessible(true);
|
||||
f.set(p, cp);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
DbQueryResult r = Objects.requireNonNull(DbManager.h("nn")).createSelectQuery().all().where(c -> c.forColumn("uuid").value(DbComparisonType.EQUALS, p.getUniqueId()).end()).build().execute();
|
||||
|
||||
if (r.next()) {
|
||||
y.setNickname((String) r.get(1));
|
||||
}
|
||||
|
||||
r.close();
|
||||
});
|
||||
|
||||
|
||||
EconomyManager.loadFor(y);
|
||||
|
||||
y.getBasePlayer().setCustomName(PlaceholderFormatter.format(Desu.getMain().getPlayerTagFormat(), y));
|
||||
y.getBasePlayer().setCustomNameVisible(true);
|
||||
YPlayer.join(p);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void onLeave(Player p) {
|
||||
YPlayer pp = YPlayer.get(p);
|
||||
if (!p.getDisplayName().equals(p.getName()))
|
||||
CompletableFuture.runAsync(() -> Objects.requireNonNull(DbManager.h("nn")).createInsertQuery().setColumn("uuid", p.getUniqueId()).setColumn("nickname", p.getDisplayName()).build().execute());
|
||||
|
||||
CompletableFuture.runAsync(() -> PermissionManager.savePerms(pp));
|
||||
|
||||
CompletableFuture.runAsync(() -> EconomyManager.saveFor(pp));
|
||||
|
||||
YPlayer.leave(p);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void chat(AsyncPlayerChatEvent e) {
|
||||
YPlayer pl = YPlayer.get(e.getPlayer());
|
||||
String format = Desu.getMain().getChatFormat();
|
||||
format = PlaceholderFormatter.format(format, e);
|
||||
e.setFormat(format.replace("%", "%%"));
|
||||
Consumer<AsyncPlayerChatEvent> c = pl.chatListenerQueue.poll();
|
||||
if (c == null) return;
|
||||
c.accept(e);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void interact(PlayerInteractEvent e) {
|
||||
YPlayer pl = YPlayer.get(e.getPlayer());
|
||||
Consumer<PlayerInteractEvent> c = pl.interactQueue.poll();
|
||||
if (c == null) return;
|
||||
c.accept(e);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void intEnt(PlayerInteractAtEntityEvent e) {
|
||||
YPlayer pl = YPlayer.get(e.getPlayer());
|
||||
Consumer<PlayerInteractAtEntityEvent> c = pl.entityInteractQueue.poll();
|
||||
if (c == null) return;
|
||||
c.accept(e);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void mv(PlayerMoveEvent e) {
|
||||
moveEvents.put(YPlayer.get(e.getPlayer()), System.currentTimeMillis());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
package me.yuri.yuriapi.api;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.MainListener;
|
||||
import me.yuri.yuriapi.api.economy.EconomyManager;
|
||||
import me.yuri.yuriapi.api.permission.PermissionManager;
|
||||
import me.yuri.yuriapi.api.permission.YPermissionGroup;
|
||||
import me.yuri.yuriapi.api.utils.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class YPlayer {
|
||||
|
||||
private static final Collection<YPlayer> players = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final List<PlayerListener> listeners = new ArrayList<>();
|
||||
protected final Queue<Consumer<AsyncPlayerChatEvent>> chatListenerQueue = new LinkedList<>();
|
||||
protected final Queue<Consumer<PlayerInteractEvent>> interactQueue = new LinkedList<>();
|
||||
protected final Queue<Consumer<PlayerInteractAtEntityEvent>> entityInteractQueue = new LinkedList<>();
|
||||
protected final PermissionAttachment perm;
|
||||
protected final List<String> prefixes = new ArrayList<>();
|
||||
private final Player player;
|
||||
protected String listPrefix = "";
|
||||
protected List<YPermissionGroup> permgroups = new ArrayList<>();
|
||||
protected YPlayer lastPrivateReceiver = null;
|
||||
protected boolean custom;
|
||||
|
||||
private YPlayer(Player p) {
|
||||
player = p;
|
||||
|
||||
perm = p.addAttachment(Desu.getMain());
|
||||
|
||||
if (!p.hasPlayedBefore())
|
||||
if (PermissionManager.getDefaultGroup() != null)
|
||||
assignGroup(PermissionManager.getDefaultGroup());
|
||||
|
||||
PermissionManager.getFor(this).forEach(this::assignGroup);
|
||||
|
||||
if(Desu.CUSTOM_AUTHENTICATION) {
|
||||
HttpClient cl = HttpClient.newHttpClient();
|
||||
HttpRequest rq = HttpRequest.newBuilder(URI.create("https://api.lo5.moe:5558/api/iscustom/" + p.getUniqueId().toString())).GET().build();
|
||||
try {
|
||||
custom = cl.send(rq, HttpResponse.BodyHandlers.discarding()).statusCode() == 204;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void leave(Player p) {
|
||||
YPlayer y = get(p);
|
||||
listeners.forEach(c -> c.onLeave(y));
|
||||
}
|
||||
|
||||
static void join(Player p) {
|
||||
YPlayer y = get(p);
|
||||
listeners.forEach(c -> c.onJoin(y));
|
||||
}
|
||||
|
||||
public static Collection<YPlayer> getOnlinePlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
public static OfflinePlayer getOfflinePlayer(String name) {
|
||||
return Arrays.stream(Bukkit.getOfflinePlayers()).filter(c -> c.getName() != null && c.getName().equalsIgnoreCase(name)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static void sync(PlayerListener l) {
|
||||
if (!listeners.contains(l))
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
public static YPlayer get(@Nonnull Player p) {
|
||||
for (YPlayer y : players) {
|
||||
if (p.equals(y.player)) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
YPlayer pl = new YPlayer(p);
|
||||
players.add(pl);
|
||||
return pl;
|
||||
}
|
||||
|
||||
public static YPlayer get(@Nonnull String name) {
|
||||
Player p = Bukkit.getPlayer(name);
|
||||
if (p == null) return null;
|
||||
return get(p);
|
||||
}
|
||||
|
||||
public static YPlayer get(@Nonnull UUID u) {
|
||||
for (YPlayer y : players) {
|
||||
if (u.equals(y.player.getUniqueId())) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
Player p = Bukkit.getPlayer(u);
|
||||
if (p == null) return null;
|
||||
|
||||
YPlayer pl = new YPlayer(p);
|
||||
players.add(pl);
|
||||
return pl;
|
||||
}
|
||||
|
||||
public boolean isCustom() {
|
||||
return custom;
|
||||
}
|
||||
|
||||
public Player getBasePlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public int getFunds() {
|
||||
return EconomyManager.getFunds(this);
|
||||
}
|
||||
|
||||
public boolean isFrozen() {
|
||||
return MainListener.f__(this.getBasePlayer());
|
||||
}
|
||||
|
||||
public void setFrozen(boolean b) {
|
||||
MainListener.f_(this.getBasePlayer(), b);
|
||||
}
|
||||
|
||||
public void sendMessage(char c, String msg) {
|
||||
player.sendMessage(Colored.colorize(c, msg));
|
||||
}
|
||||
|
||||
public void sendMessage(String msg) {
|
||||
sendMessage('&', msg);
|
||||
}
|
||||
|
||||
public void sendMessage(Message b) {
|
||||
this.player.spigot().sendMessage(b.getType(), b.getComponents());
|
||||
}
|
||||
|
||||
public void sendMessage(char c, String... msg) {
|
||||
player.sendMessage(Colored.colorize(c, msg));
|
||||
}
|
||||
|
||||
public void sendMessage(String... msg) {
|
||||
sendMessage('&', msg);
|
||||
}
|
||||
|
||||
public void playSound(Sound s, float volume) {
|
||||
this.player.playSound(this.player.getEyeLocation(), s, volume, 1);
|
||||
}
|
||||
|
||||
public void playSound(Sound s) {
|
||||
playSound(s, 1);
|
||||
}
|
||||
|
||||
public void onNextMessage(Consumer<AsyncPlayerChatEvent> c) {
|
||||
chatListenerQueue.add(c);
|
||||
}
|
||||
|
||||
public void onNextInteract(Consumer<PlayerInteractEvent> c) {
|
||||
interactQueue.add(c);
|
||||
}
|
||||
|
||||
public void onNextInteractWithEntity(Consumer<PlayerInteractAtEntityEvent> c) {
|
||||
entityInteractQueue.add(c);
|
||||
}
|
||||
|
||||
public long onLastMove() {
|
||||
return PlayerEvents.moveEvents.getOrDefault(this, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void privateMessage(YPlayer target, String msg) {
|
||||
Message m = new MessageBuilder().append(String.format("&2[&7%s &a-> &7%s&2]", PlaceholderFormatter.format(Desu.getMain().getPrivTagFormat(), this), PlaceholderFormatter.format(Desu.getMain().getPrivTagFormat(), target))).hoverText("&3Click to reply").clickSuggestCommand("/r ")
|
||||
.push().append("&8: &r" + (this.getHighestGroup() != null ? this.getHighestGroup().getSuffix() : "&7") + msg).build();
|
||||
target.sendMessage(m);
|
||||
this.sendMessage(m);
|
||||
this.lastPrivateReceiver = target;
|
||||
target.lastPrivateReceiver = this;
|
||||
}
|
||||
|
||||
public boolean reply(String msg) {
|
||||
if (lastPrivateReceiver == null) return false;
|
||||
privateMessage(lastPrivateReceiver, msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
public YPlayer getLastPrivateMessageReceiver() {
|
||||
return lastPrivateReceiver;
|
||||
}
|
||||
|
||||
public List<YPermissionGroup> getPermissionGroups() {
|
||||
return permgroups;
|
||||
}
|
||||
|
||||
public void addPermission() {
|
||||
|
||||
}
|
||||
|
||||
public void addChatPrefix(String prefix) {
|
||||
this.prefixes.add(prefix);
|
||||
}
|
||||
|
||||
public void clearChatPrefix() {
|
||||
this.prefixes.clear();
|
||||
}
|
||||
|
||||
public List<String> getChatPrefixes() {
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
public void insertChatPrefix(int index, String prefix) {
|
||||
prefixes.add(index, prefix);
|
||||
}
|
||||
|
||||
public boolean removeChatPrefix(String content) {
|
||||
return prefixes.remove(content);
|
||||
}
|
||||
|
||||
public String removeChatPrefix(int idx) {
|
||||
return prefixes.remove(idx);
|
||||
}
|
||||
|
||||
public void setPlayerListPrefix(String prefix) {
|
||||
this.listPrefix = Colored.colorize(prefix);
|
||||
updatePlayerListPrefix();
|
||||
}
|
||||
|
||||
public void clearPlayerListPrefix() {
|
||||
listPrefix = "";
|
||||
updatePlayerListPrefix();
|
||||
}
|
||||
|
||||
public YPermissionGroup getHighestGroup() {
|
||||
return this.permgroups.size() == 0 ? null : this.permgroups.get(0);
|
||||
}
|
||||
|
||||
public void assignGroup(YPermissionGroup g) {
|
||||
if (permgroups.contains(g)) return;
|
||||
g.getPermissions().forEach(p -> this.perm.setPermission(p, true));
|
||||
this.permgroups.add(g);
|
||||
this.permgroups.sort(Comparator.comparingInt(YPermissionGroup::getIndex));
|
||||
|
||||
}
|
||||
|
||||
public boolean removeFromGroup(YPermissionGroup g) {
|
||||
g.getPermissions().forEach(this.perm::unsetPermission);
|
||||
return this.permgroups.remove(g);
|
||||
}
|
||||
|
||||
public void setNickname(String s) {
|
||||
s = Colored.colorize(s);
|
||||
this.player.setDisplayName(s);
|
||||
this.player.setPlayerListName(s);
|
||||
updatePlayerListPrefix();
|
||||
}
|
||||
|
||||
public void clearNickname() {
|
||||
this.player.setDisplayName(this.player.getName());
|
||||
this.player.setPlayerListName(this.player.getName());
|
||||
updatePlayerListPrefix();
|
||||
}
|
||||
|
||||
public void updatePlayerListPrefix() {
|
||||
this.player.setPlayerListName(listPrefix.equals("") ? this.player.getDisplayName() : listPrefix + " " + this.player.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof YPlayer) {
|
||||
return ((YPlayer) obj).getBasePlayer().getUniqueId().equals(this.getBasePlayer().getUniqueId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getBasePlayer().getUniqueId().hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package me.yuri.yuriapi.api;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public abstract class YuriPlugin extends JavaPlugin {
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
super.onEnable();
|
||||
}
|
||||
}
|
75
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/command/Cmd.java
Executable file
75
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/command/Cmd.java
Executable file
|
@ -0,0 +1,75 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Cmd {
|
||||
/**
|
||||
* The command name
|
||||
*
|
||||
* @return the command name
|
||||
*/
|
||||
String command();
|
||||
|
||||
/**
|
||||
* Defines whether the command is executable by players
|
||||
*
|
||||
* @return whether the command is executable by players
|
||||
*/
|
||||
boolean playerSide() default true;
|
||||
|
||||
/**
|
||||
* Defines whether the command is executable by the console
|
||||
*
|
||||
* @return whether the command is executable by the console
|
||||
*/
|
||||
boolean consoleSide() default true;
|
||||
|
||||
/**
|
||||
* Defines the permissions that are required to execute the command (at least 1 permission must be met)
|
||||
*
|
||||
* @return permissions that are required to execute the command
|
||||
*/
|
||||
String[] permissions() default {};
|
||||
|
||||
/**
|
||||
* Defines the default tab completion array for the command
|
||||
*
|
||||
* @return tab completion string array
|
||||
*/
|
||||
String[] tabCompletions() default {};
|
||||
|
||||
/**
|
||||
* Defines the command description
|
||||
*
|
||||
* @return command description
|
||||
*/
|
||||
String desc() default "";
|
||||
|
||||
/**
|
||||
* Defines the command aliases
|
||||
*
|
||||
* @return command aliases
|
||||
*/
|
||||
String[] aliases() default {};
|
||||
|
||||
/**
|
||||
* Defines the default message when the caller does not have required permissions
|
||||
*
|
||||
* @return the default message when the caller does not have required permissions
|
||||
*/
|
||||
String noPerms() default "§4Missing permissions";
|
||||
|
||||
/**
|
||||
* Defines the name of the method that is called whenever the command is subjected to autocompletion trials
|
||||
* If empty, it will be disabled
|
||||
*
|
||||
* @return name of the method (inside the same class) that will be called on command autocompletion
|
||||
*/
|
||||
@Deprecated String tabCompletionHandler() default "";
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class CommandContainer {
|
||||
private final Plugin p;
|
||||
private final Method m;
|
||||
private final Object clazz;
|
||||
private final Cmd cmd;
|
||||
|
||||
public CommandContainer(Plugin p, Method m, Object clazz) {
|
||||
this.p = p;
|
||||
this.m = m;
|
||||
this.clazz = clazz;
|
||||
cmd = m.getAnnotation(Cmd.class);
|
||||
}
|
||||
|
||||
public Plugin getMainPluginInstance() {
|
||||
return p;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return m;
|
||||
}
|
||||
|
||||
public Object getInstance() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public Cmd getAnnotation() {
|
||||
return cmd;
|
||||
}
|
||||
}
|
127
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/command/CommandEvent.java
Executable file
127
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/command/CommandEvent.java
Executable file
|
@ -0,0 +1,127 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CommandEvent {
|
||||
|
||||
protected final CommandSender sender;
|
||||
protected final String[] args;
|
||||
protected final String label;
|
||||
protected final Cmd cmdAnnotation;
|
||||
protected final Command cmd;
|
||||
protected final String argsstring;
|
||||
protected final boolean isPlayer, isConsole;
|
||||
protected final YPlayer plr;
|
||||
|
||||
public CommandEvent(CommandSender sender, Command cmd, String label, Cmd command, String[] args) {
|
||||
this.sender = sender;
|
||||
this.args = args;
|
||||
this.label = label;
|
||||
this.cmdAnnotation = command;
|
||||
this.cmd = cmd;
|
||||
this.argsstring = String.join(" ", args).trim();
|
||||
this.isConsole = this.sender instanceof ConsoleCommandSender;
|
||||
this.isPlayer = this.sender instanceof Player;
|
||||
|
||||
if (isPlayer)
|
||||
this.plr = YPlayer.get((Player) sender);
|
||||
else
|
||||
this.plr = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command caller
|
||||
*
|
||||
* @return command sender
|
||||
*/
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command arguments
|
||||
*
|
||||
* @return command arguments string array
|
||||
*/
|
||||
public String[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the particular string used to invoke the command
|
||||
*
|
||||
* @return command label
|
||||
*/
|
||||
public String getCmdLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the annotation present above the command method
|
||||
*
|
||||
* @return Cmd annotation
|
||||
*/
|
||||
public Cmd getCmdAnnotation() {
|
||||
return cmdAnnotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Bukkit command instance
|
||||
*
|
||||
* @return Bukkit command instance
|
||||
*/
|
||||
public Command getCommand() {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arguments as a single string
|
||||
*
|
||||
* @return arguments as a single string
|
||||
*/
|
||||
public String getArgsString() {
|
||||
return argsstring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the CommandSender, applies color codes
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public void reply(String... msg) {
|
||||
this.getSender().sendMessage(Colored.colorize(msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the command sender is a player
|
||||
*
|
||||
* @return true if the sender is a player, false otherwise
|
||||
*/
|
||||
public boolean isPlayer() {
|
||||
return isPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the command sender is a console
|
||||
*
|
||||
* @return true if the sender is a console, false otherwise
|
||||
*/
|
||||
public boolean isConsole() {
|
||||
return isConsole;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sender as player
|
||||
*
|
||||
* @return CommandSender as player
|
||||
*/
|
||||
public YPlayer asPlayer() {
|
||||
if (plr == null) throw new IllegalStateException("Sender is not a player.");
|
||||
return plr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.api.reflectionless.Reflectionless;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVar;
|
||||
import me.yuri.yuriapi.utils.Logging;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class CommandManager implements CommandExecutor, TabCompleter {
|
||||
|
||||
public static final Map<String, CommandContainer> commandRegistry = new ConcurrentHashMap<>();
|
||||
/*
|
||||
Parameter must be CommandClass
|
||||
*/
|
||||
@ConfigVar(value = "enableCommandRegistryNotifications")
|
||||
private static final boolean notify = true;
|
||||
private final JavaPlugin pl;
|
||||
|
||||
public CommandManager(JavaPlugin pl) {
|
||||
this.pl = pl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a class containing command methods
|
||||
*
|
||||
* @param clazz the class instance containing the command methods
|
||||
*/
|
||||
public void registerCommand(Object clazz) {
|
||||
Arrays.stream(clazz.getClass().getDeclaredMethods()).filter(m -> (m.isAnnotationPresent(Cmd.class)
|
||||
&& m.getParameterCount() > 0 && CommandEvent.class.isAssignableFrom(m.getParameters()[0].getType()))).forEach(a -> {
|
||||
Cmd annot = a.getAnnotation(Cmd.class);
|
||||
CommandContainer cc = new CommandContainer(pl, a, clazz);
|
||||
commandRegistry.put(annot.command().toLowerCase(), cc);
|
||||
if (annot.aliases().length != 0) {
|
||||
Arrays.stream(annot.aliases()).forEach(al -> commandRegistry.put(al.toLowerCase(), cc));
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
Logging.consoleLog(Desu.cl.colorizeInst("$eCommand $a/" + annot.command() + " $eregistered!"));
|
||||
if (annot.aliases().length != 0) {
|
||||
Logging.consoleLog(Desu.cl.colorizeInst("$eAliases:"));
|
||||
for (String s : annot.aliases()) {
|
||||
Logging.consoleLog(Desu.cl.colorizeInst("$e - $a/" + s.toLowerCase()));
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Objects.requireNonNull(pl.getCommand(annot.command())).setExecutor(this);
|
||||
} catch (NullPointerException e) {
|
||||
Logging.consoleLog(Desu.cl.colorizeInst("$cError when registering command $e" + annot.command() + "$c! Command is not defined in $eplugin.yml$c!"));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@Nonnull CommandSender sender,
|
||||
@Nonnull org.bukkit.command.Command cmd,
|
||||
@Nonnull String label, @Nonnull String[] args) {
|
||||
for (int arg = args.length; arg >= 0; arg--) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(label.toLowerCase());
|
||||
for (int x = 0; x < arg; x++) {
|
||||
buffer.append(".").append(args[x].toLowerCase());
|
||||
}
|
||||
String bufferString = buffer.toString();
|
||||
if (commandRegistry.containsKey(buffer.toString())) {
|
||||
|
||||
CommandContainer entry = commandRegistry.get(buffer.toString());
|
||||
|
||||
Cmd command = entry.getAnnotation();
|
||||
|
||||
if (!command.consoleSide() && !(sender instanceof Player)) {
|
||||
sender.sendMessage(Desu.cl.colorizeInst(Desu.cl.colorizeInst("$4This command is for players only!")));
|
||||
} else if (!command.playerSide() && !(sender instanceof ConsoleCommandSender)) {
|
||||
sender.sendMessage(Desu.cl.colorizeInst(Desu.cl.colorizeInst("$4This command can only be run via terminal.")));
|
||||
} else {
|
||||
int subCommand = bufferString.split("\\.").length - 1;
|
||||
String[] modArgs = IntStream.range(0, args.length - subCommand).mapToObj(i -> args[i + subCommand]).toArray(String[]::new);
|
||||
|
||||
String labelFinal = IntStream.range(0, subCommand).mapToObj(x -> " " + args[x]).collect(Collectors.joining("", label, ""));
|
||||
if (command.permissions().length == 0 || Arrays.stream(command.permissions()).anyMatch(p -> sender.hasPermission(entry.getMainPluginInstance().getName().toLowerCase() + "." + p)) || sender.isOp()) {
|
||||
try {
|
||||
Object event = Reflectionless.get(entry.getMethod().getParameterTypes()[0].getConstructors()[0]).call(sender, cmd, labelFinal, command, modArgs);
|
||||
|
||||
Reflectionless.get(entry.getMethod()).call(entry.getInstance(), event);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage(command.noPerms());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<String> onTabComplete(@Nonnull CommandSender snd,
|
||||
Command command,
|
||||
@Nonnull String lb,
|
||||
@Nonnull String[] args) {
|
||||
if (commandRegistry.containsKey(command.getName())) {
|
||||
CommandContainer entry = commandRegistry.get(command.getName());
|
||||
|
||||
if (entry.getAnnotation().permissions().length > 0 && Arrays.stream(entry.getAnnotation().permissions()).noneMatch(p -> snd.hasPermission(entry.getMainPluginInstance().getName().toLowerCase() + "." + p))) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (entry.getAnnotation().tabCompletions().length != 0) {
|
||||
String[] tc = entry.getAnnotation().tabCompletions();
|
||||
if (tc[0].equals(TabPlaceholder.PLAYERS)) return null;
|
||||
if (tc[0].equals(TabPlaceholder.EMPTY)) return Collections.emptyList();
|
||||
return Arrays.asList(tc);
|
||||
} else {
|
||||
Optional<Method> opt = Arrays.stream(entry.getInstance().getClass().getDeclaredMethods()).filter(m -> {
|
||||
if (m.isAnnotationPresent(TabCompletion.class))
|
||||
return m.getAnnotation(TabCompletion.class).command().equals(command.getName());
|
||||
else return false;
|
||||
}).findFirst();
|
||||
try {
|
||||
if (opt.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (!opt.get().getReturnType().equals(List.class)) return Collections.emptyList();
|
||||
else {
|
||||
CommandTabCompleteEvent tb = new CommandTabCompleteEvent(snd, command, lb, args, opt.get().getAnnotation(TabCompletion.class));
|
||||
Object o = Reflectionless.get(opt.get()).call(entry.getInstance(), tb);
|
||||
assert o instanceof List;
|
||||
return (List<String>) o;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
public enum CommandResult {
|
||||
SUCCESS, INVALID_FIELD, TOO_MANY_ARGS, NOT_ENOUGH_ARGS, EXCEPTION
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandTabCompleteEvent {
|
||||
protected final CommandSender sender;
|
||||
protected final String[] args;
|
||||
protected final String label;
|
||||
protected final Command cmd;
|
||||
protected final String argsstring;
|
||||
protected final TabCompletion tc;
|
||||
|
||||
public CommandTabCompleteEvent(CommandSender s, Command cmd, String label, String[] args, TabCompletion tc) {
|
||||
sender = s;
|
||||
this.label = label;
|
||||
this.cmd = cmd;
|
||||
this.args = args;
|
||||
this.argsstring = String.join(" ", args);
|
||||
this.tc = tc;
|
||||
}
|
||||
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public String[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public String getArgsString() {
|
||||
return argsstring;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the CommandSender, applies color codes
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public void reply(String... msg) {
|
||||
this.getSender().sendMessage(Colored.colorize(msg));
|
||||
}
|
||||
|
||||
public TabCompletion getAnnotation() {
|
||||
if (tc == null) throw new IllegalStateException("Using null annotation");
|
||||
return tc;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
|
||||
public class ConsoleCommandEvent extends CommandEvent {
|
||||
public ConsoleCommandEvent(CommandSender sender, Command cmd, String label, Cmd command, String[] args) {
|
||||
super(sender, cmd, label, command, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command caller as a Player
|
||||
*
|
||||
* @return player command caller
|
||||
*/
|
||||
public ConsoleCommandSender getConsole() {
|
||||
return (ConsoleCommandSender) sender;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
public class Permission {
|
||||
public static final Permission NOPERMISSION = new Permission("null");
|
||||
public static final Permission[] NOPERMISSIONS = new Permission[]{new Permission("null")};
|
||||
|
||||
private final String perm;
|
||||
|
||||
public Permission(String permission) {
|
||||
this.perm = permission;
|
||||
}
|
||||
|
||||
public String getPermissionString() {
|
||||
return perm;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerCommandEvent extends CommandEvent {
|
||||
public PlayerCommandEvent(CommandSender sender, Command cmd, String label, Cmd command, String[] args) {
|
||||
super(sender, cmd, label, command, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command caller as a Player
|
||||
*
|
||||
* @return player command caller
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return (Player) sender;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface TabCompletion {
|
||||
/**
|
||||
* @return the command name
|
||||
*/
|
||||
String command();
|
||||
|
||||
/**
|
||||
* Defines whether the command is executable by players
|
||||
*
|
||||
* @return whether the command is executable by players
|
||||
*/
|
||||
boolean playerSide() default true;
|
||||
|
||||
/**
|
||||
* Defines whether the command is executable by the console
|
||||
*
|
||||
* @return whether the command is executable by the console
|
||||
*/
|
||||
boolean consoleSide() default true;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package me.yuri.yuriapi.api.command;
|
||||
|
||||
public final class TabPlaceholder {
|
||||
public static final String PLAYERS = "<players>";
|
||||
|
||||
public static final String EMPTY = "";
|
||||
|
||||
private TabPlaceholder() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DbColumn<T extends DbColumnDataType<?, V>, V> {
|
||||
|
||||
private final DbConnection conn;
|
||||
private final String name;
|
||||
private final T type;
|
||||
private final boolean nullable;
|
||||
private final DbTable table;
|
||||
|
||||
protected DbColumn(String name, T type, DbTable table, boolean nullable) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.nullable = nullable;
|
||||
this.table = table;
|
||||
this.conn = table.getConnection();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnection getConnection() {
|
||||
return this.conn;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public T getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Class<V> getDataType() {
|
||||
return type.getBoxedDataType();
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbTable getTable() {
|
||||
return table;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class DbColumnDataType<T, V> {
|
||||
|
||||
public static final DbColumnDataType<Integer, Integer> INTEGER = new DbColumnDataType<>(Integer.class, Integer.class, 0);
|
||||
public static final DbColumnDataType<byte[], byte[]> BYTE_ARRAY = new DbColumnDataType<>(byte[].class, byte[].class, 1);
|
||||
public static final DbColumnDataType<byte[], UUID> UUID = new DbColumnDataType<>(byte[].class, UUID.class, 2);
|
||||
public static final DbColumnDataType<Long, Long> TIMESTAMP = new DbColumnDataType<>(Long.class, Long.class, 3);
|
||||
public static final DbColumnDataType<Long, Long> BIGINT = new DbColumnDataType<>(Long.class, Long.class, 4);
|
||||
public static final DbColumnDataType<String, Location> LOCATION = new DbColumnDataType<>(String.class, Location.class, 5);
|
||||
public static final DbColumnDataType<Boolean, Boolean> BOOLEAN = new DbColumnDataType<>(Boolean.class, Boolean.class, 6);
|
||||
public static final DbColumnDataType<String, String> TEXT = new DbColumnDataType<>(String.class, String.class, 7);
|
||||
public static final DbColumnDataType<String, ItemStack> ITEM_STACK = new DbColumnDataType<>(String.class, ItemStack.class, 8);
|
||||
public static final DbColumnDataType<Float, Float> FLOAT = new DbColumnDataType<>(Float.class, Float.class, 9);
|
||||
public static final DbColumnDataType<Double, Double> DOUBLE = new DbColumnDataType<>(Double.class, Double.class, 10);
|
||||
private final Class<T> type;
|
||||
private final Class<V> datatype;
|
||||
private final int id;
|
||||
|
||||
private DbColumnDataType(@Nonnull Class<T> type, @Nonnull Class<V> datatype, int id) {
|
||||
this.type = type;
|
||||
this.datatype = datatype;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public T getPrimitiveType(T t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public V getPrimitiveDataType(V v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Class<T> getBoxedType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Class<V> getBoxedDataType() {
|
||||
return datatype;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public enum DbComparisonLink {
|
||||
START(""), OR("OR"), AND("AND");
|
||||
|
||||
private final String lit;
|
||||
|
||||
DbComparisonLink(String n) {
|
||||
this.lit = n;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getLiteral() {
|
||||
return lit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public enum DbComparisonType {
|
||||
EQUALS("="), MORE_THAN(">"), LESS_THAN("<"), MORE_THAN_EQUALS(">="), LESS_THAN_EQUALS("<="), NOT_EQUALS("<>"), LIKE(" LIKE ");
|
||||
|
||||
private final String lit;
|
||||
|
||||
DbComparisonType(String l) {
|
||||
this.lit = l;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getLiteral() {
|
||||
return lit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class DbCondition {
|
||||
private final List<DbExpression> comps;
|
||||
|
||||
protected DbCondition(List<DbExpression> comparisons) {
|
||||
comps = comparisons;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<DbExpression> getExpressionList() {
|
||||
return comps;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DbConditionBuilder {
|
||||
private final DbTable table;
|
||||
private final List<DbExpression> comparisons = new ArrayList<>();
|
||||
private DbColumn<?, ?> current = null;
|
||||
private int currentDepth = 0;
|
||||
private DbComparisonLink currentLink = DbComparisonLink.START;
|
||||
|
||||
protected DbConditionBuilder(DbTable t) {
|
||||
table = t;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder forColumn(@Nonnull DbColumn<?, ?> c) {
|
||||
current = c;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder forColumn(@Nonnegative int index) {
|
||||
current = table.getColumns().get(index);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder forColumn(@Nonnull String name) {
|
||||
for (DbColumn<?, ?> c : table.getColumns()) {
|
||||
if (c.getName().equalsIgnoreCase(name)) {
|
||||
current = c;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Column %s does not exist.", name));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <V> DbConditionBuilder value(@Nonnull DbComparisonType type, V value) {
|
||||
if (current == null) {
|
||||
throw new IllegalStateException("Set the column before applying condition.");
|
||||
}
|
||||
if (currentLink == null) {
|
||||
throw new IllegalStateException("No link between the two expressions selected.");
|
||||
}
|
||||
|
||||
comparisons.add(new DbExpression(current, type, value, currentDepth, currentLink));
|
||||
currentLink = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder or() {
|
||||
if (comparisons.isEmpty()) {
|
||||
throw new IllegalStateException("No expression has been set before OR clause.");
|
||||
}
|
||||
|
||||
currentLink = DbComparisonLink.OR;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder and() {
|
||||
if (comparisons.isEmpty()) {
|
||||
throw new IllegalStateException("No expression has been set before AND clause.");
|
||||
}
|
||||
|
||||
currentLink = DbComparisonLink.AND;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder openGroup() {
|
||||
currentDepth++;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConditionBuilder closeGroup() {
|
||||
if (currentDepth == 0) {
|
||||
throw new IllegalStateException("No group to close.");
|
||||
}
|
||||
|
||||
currentDepth--;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbCondition end() {
|
||||
if (currentDepth != 0) {
|
||||
throw new IllegalStateException(String.format("Unclosed groups: %d groups.", currentDepth));
|
||||
}
|
||||
|
||||
return new DbCondition(comparisons);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class DbConnection {
|
||||
|
||||
protected final String connectionString;
|
||||
protected final List<DbTable> tables = new ArrayList<>();
|
||||
protected Connection connection = null;
|
||||
protected boolean doInitTables = false;
|
||||
protected boolean init = false;
|
||||
|
||||
protected DbConnection(String connectionString) {
|
||||
this.connectionString = connectionString;
|
||||
}
|
||||
|
||||
public static DbConnectionBuilder newConnection(DbConnectionBuilder.DbType t) {
|
||||
return new DbConnectionBuilder(t);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public abstract Class<?> forName() throws ClassNotFoundException;
|
||||
|
||||
public boolean isConnected() {
|
||||
try {
|
||||
return connection != null && connection.isClosed();
|
||||
} catch (SQLException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void createTable(@Nonnull DbTable t, boolean force);
|
||||
|
||||
@Nonnull
|
||||
public abstract String transformDataType(@Nonnull DbColumnDataType<?, ?> type);
|
||||
|
||||
public void initTables(DbTable... t) {
|
||||
initTables(Arrays.asList(t));
|
||||
}
|
||||
|
||||
public void initTables(@Nonnull List<DbTable> t) {
|
||||
if (init)
|
||||
throw new IllegalStateException("Database has already been initialized.");
|
||||
|
||||
doInitTables = true;
|
||||
tables.addAll(t);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbTable getTable(@Nonnegative int ordinal) {
|
||||
return tables.get(ordinal);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public abstract String serializeObject(@Nullable Object o);
|
||||
|
||||
public abstract DbQueryResult select(DbSelectQuery q);
|
||||
|
||||
@Nullable
|
||||
public abstract Object deserializeObject(@Nonnull DbColumnDataType<?, ?> type, @Nullable Object o);
|
||||
|
||||
@Nonnegative
|
||||
public abstract int update(DbQuery q);
|
||||
|
||||
@Nonnull
|
||||
public List<DbTable> getTables() {
|
||||
return this.tables;
|
||||
}
|
||||
|
||||
public DbTable getTable(@Nonnull String name) {
|
||||
for (DbTable t : tables) {
|
||||
if (t.getName().equalsIgnoreCase(name)) return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void createTable(@Nonnull DbTable t) {
|
||||
createTable(t, false);
|
||||
}
|
||||
|
||||
public void connect() throws Exception {
|
||||
init = true;
|
||||
forName();
|
||||
connection = DriverManager.getConnection(connectionString);
|
||||
if (doInitTables) {
|
||||
List<DbTable> tablelist = new ArrayList<>(tables);
|
||||
tables.clear();
|
||||
tablelist.forEach(t -> createTable(t, false));
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO QUERYING DATA PARSING, DATA CONVERTERS
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class DbConnectionBuilder {
|
||||
|
||||
private final DbType type;
|
||||
private final Map<String, Function<DbTableBuilder, DbTable>> tablebuilds = new HashMap<>();
|
||||
private String connectionString = null;
|
||||
|
||||
public DbConnectionBuilder(DbType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnectionBuilder withConnectionString(@Nonnull String s) {
|
||||
connectionString = s;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnectionBuilder withTable(String name, Function<DbTableBuilder, DbTable> builder) {
|
||||
tablebuilds.put(name, builder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnection build() {
|
||||
if (connectionString == null) {
|
||||
throw new IllegalStateException("connection string is not defined");
|
||||
}
|
||||
|
||||
DbConnection db;
|
||||
|
||||
switch (type) {
|
||||
case SQLITE:
|
||||
db = new SqliteConnection(connectionString);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("not possible but ok");
|
||||
}
|
||||
|
||||
List<DbTable> tables = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, Function<DbTableBuilder, DbTable>> u : tablebuilds.entrySet()) {
|
||||
tables.add(u.getValue().apply(new DbTableBuilder(u.getKey(), db)));
|
||||
}
|
||||
|
||||
db.initTables(tables);
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public enum DbType {
|
||||
SQLITE
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DbExpression {
|
||||
|
||||
private final DbColumn<?, ?> column;
|
||||
private final DbComparisonType type;
|
||||
private final Object value;
|
||||
private final int depth;
|
||||
private final DbComparisonLink prev;
|
||||
|
||||
protected DbExpression(DbColumn<?, ?> col, DbComparisonType type, Object value, int depth, DbComparisonLink prev) {
|
||||
this.column = col;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.prev = prev;
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbColumn<?, ?> getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbComparisonType getComparisonType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public int getDepth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbComparisonLink linkBefore() {
|
||||
return prev;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
public class DbQuery {
|
||||
|
||||
private final DbConnection conn;
|
||||
private final Map<DbColumn<?, ?>, Object> map;
|
||||
private final DbTable table;
|
||||
private final DbQueryType type;
|
||||
private final DbCondition condition;
|
||||
|
||||
protected DbQuery(@Nonnull DbQueryType type, @Nonnull DbTable t, @Nonnull Map<DbColumn<?, ?>, Object> map, @Nullable DbCondition cnd) {
|
||||
this.map = map;
|
||||
this.table = t;
|
||||
this.type = type;
|
||||
this.condition = cnd;
|
||||
this.conn = table.getConnection();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnection getConnection() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public int execute() {
|
||||
return conn.update(this);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<DbColumn<?, ?>, Object> getColumnMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbTable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbQueryType getQueryType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DbCondition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DbQueryResult {
|
||||
|
||||
private final DbConnection connection;
|
||||
private final ImmutableList<DbColumn<?, ?>> columns;
|
||||
private final DbTable table;
|
||||
private final ResultSet rs;
|
||||
|
||||
protected DbQueryResult(DbConnection con, DbTable t, ImmutableList<DbColumn<?, ?>> l, ResultSet rs) {
|
||||
this.table = t;
|
||||
this.columns = l;
|
||||
this.rs = rs;
|
||||
this.connection = con;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbTable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public ImmutableList<DbColumn<?, ?>> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return rs == null;
|
||||
}
|
||||
|
||||
public boolean next() {
|
||||
try {
|
||||
return rs.next();
|
||||
} catch (SQLException throwables) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean previous() {
|
||||
try {
|
||||
return rs.previous();
|
||||
} catch (SQLException throwables) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbQueryResult skip(int count) {
|
||||
try {
|
||||
for (int i = 0; i < count; i++)
|
||||
rs.next();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbQueryResult back(int count) {
|
||||
try {
|
||||
for (int i = 0; i < count; i++)
|
||||
rs.previous();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends DbColumnDataType<?, V>, V> V get(DbColumn<T, V> c) {
|
||||
try {
|
||||
Object o = connection.deserializeObject(c.getType(), rs.getObject(c.getName()));
|
||||
assert o == null || o.getClass().isAssignableFrom(c.getDataType());
|
||||
return (V) o;
|
||||
} catch (SQLException throwables) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(@Nonnegative int rowIndex) {
|
||||
return this.get(this.columns.get(rowIndex));
|
||||
}
|
||||
|
||||
public long getLong(@Nonnegative int rowIndex) {
|
||||
try {
|
||||
return rs.getLong(rowIndex);
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
throw new RuntimeException("Problem");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getBoolean(@Nonnegative int rowIndex) {
|
||||
try {
|
||||
return rs.getBoolean(rowIndex);
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
throw new RuntimeException("Problem");
|
||||
}
|
||||
}
|
||||
|
||||
public UUID getUUID(@Nonnegative int rowIndex) {
|
||||
return (UUID) get(rowIndex);
|
||||
}
|
||||
|
||||
public int getInt(@Nonnegative int rowIndex) {
|
||||
try {
|
||||
return rs.getInt(rowIndex);
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
throw new RuntimeException("Problem");
|
||||
}
|
||||
}
|
||||
|
||||
public String getText(@Nonnegative int rowIndex) {
|
||||
try {
|
||||
return rs.getString(rowIndex);
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
throw new RuntimeException("Problem");
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbQueryResult then(Consumer<DbQueryResult> c) {
|
||||
c.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
rs.close();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public enum DbQueryType {
|
||||
INSERT("INSERT"), UPDATE("UPDATE"), REMOVE("DELETE");
|
||||
|
||||
private final String cmd;
|
||||
|
||||
DbQueryType(String cmd) {
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getCommand() {
|
||||
return cmd;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class DbSelectQuery {
|
||||
|
||||
private final DbConnection connection;
|
||||
private final List<DbColumn<?, ?>> columns;
|
||||
private final DbTable table;
|
||||
private final DbCondition condition;
|
||||
|
||||
protected DbSelectQuery(@Nonnull DbTable t, @Nonnull List<DbColumn<?, ?>> columns, @Nullable DbCondition cnd) {
|
||||
this.connection = t.getConnection();
|
||||
this.columns = columns;
|
||||
this.table = t;
|
||||
this.condition = cnd;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbQueryResult execute() {
|
||||
return connection.select(this);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<DbColumn<?, ?>> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbTable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DbCondition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DbSelectQueryBuilder {
|
||||
|
||||
private final DbTable table;
|
||||
private final List<DbColumn<?, ?>> selected = new ArrayList<>();
|
||||
private boolean isSelect = false;
|
||||
private DbCondition condition = null;
|
||||
|
||||
protected DbSelectQueryBuilder(@Nonnull DbTable t) {
|
||||
this.table = t;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQueryBuilder columnRange(@Nonnegative int start, @Nonnegative int end) {
|
||||
if (isSelect) {
|
||||
throw new IllegalStateException("Columns have already been selected.");
|
||||
}
|
||||
|
||||
if (start > end) {
|
||||
throw new IllegalArgumentException("Value of parameter 'start' must be less than of parameter 'end'");
|
||||
}
|
||||
|
||||
List<DbColumn<?, ?>> l = table.getColumns();
|
||||
for (int i = start; i < end; i++) {
|
||||
selected.add(l.get(i));
|
||||
}
|
||||
isSelect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQueryBuilder columns(@Nonnegative int... indexes) {
|
||||
if (isSelect) {
|
||||
throw new IllegalStateException("Columns have already been selected.");
|
||||
}
|
||||
|
||||
List<DbColumn<?, ?>> l = table.getColumns();
|
||||
for (int i : indexes) {
|
||||
selected.add(l.get(i));
|
||||
}
|
||||
isSelect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQueryBuilder columns(@Nonnull String... names) {
|
||||
if (isSelect) {
|
||||
throw new IllegalStateException("Columns have already been selected.");
|
||||
}
|
||||
|
||||
List<DbColumn<?, ?>> l = table.getColumns();
|
||||
List<String> namel = Arrays.asList(names);
|
||||
selected.addAll(l.stream().filter(c -> namel.contains(c.getName())).collect(Collectors.toList())); //FIXME CONTINUE
|
||||
isSelect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQueryBuilder all() {
|
||||
if (isSelect) {
|
||||
throw new IllegalStateException("Columns have already been selected.");
|
||||
}
|
||||
|
||||
selected.addAll(table.getColumns());
|
||||
isSelect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQueryBuilder where(@Nonnull Function<DbConditionBuilder, DbCondition> f) {
|
||||
if (condition != null) {
|
||||
throw new IllegalStateException("WHERE condition has already been set.");
|
||||
}
|
||||
|
||||
condition = f.apply(new DbConditionBuilder(table));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQuery build() {
|
||||
return new DbSelectQuery(table, selected, condition);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DbTable {
|
||||
|
||||
private final String name;
|
||||
private final DbColumn<?, ?> primary_key;
|
||||
private final List<DbColumn<?, ?>> columns;
|
||||
private final DbConnection connection;
|
||||
|
||||
protected DbTable(@Nonnull DbConnection con, @Nonnull String name, @Nonnull Object[] primary_key, @Nonnull List<Object[]> columns) {
|
||||
this.connection = con;
|
||||
this.name = name;
|
||||
this.primary_key = new DbColumn<>((String) primary_key[0], (DbColumnDataType<?, ?>) primary_key[1], this, (boolean) primary_key[2]);
|
||||
this.columns = columns.stream().map(c -> new DbColumn<>((String) c[0], (DbColumnDataType<?, ?>) c[1], this, (boolean) c[2])).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbColumn<?, ?> getPrimaryKey() {
|
||||
return primary_key;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<DbColumn<?, ?>> getColumns() {
|
||||
List<DbColumn<?, ?>> l = new ArrayList<>();
|
||||
l.add(primary_key);
|
||||
l.addAll(columns);
|
||||
return l;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<DbColumn<?, ?>> getNormalColums() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DbColumnDataType<?, ?> getByName(String name) {
|
||||
if (primary_key.getName().equalsIgnoreCase(name))
|
||||
return primary_key.getType();
|
||||
|
||||
for (DbColumn<?, ?> c : columns) {
|
||||
if (c.getName().equalsIgnoreCase(name)) {
|
||||
return c.getType();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbUpdateQueryBuilder createQuery(DbQueryType t) {
|
||||
return new DbUpdateQueryBuilder(t, this);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbUpdateQueryBuilder createUpdateQuery() {
|
||||
return new DbUpdateQueryBuilder(DbQueryType.UPDATE, this);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbUpdateQueryBuilder createInsertQuery() {
|
||||
return new DbUpdateQueryBuilder(DbQueryType.INSERT, this);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbUpdateQueryBuilder createRemoveQuery() {
|
||||
return new DbUpdateQueryBuilder(DbQueryType.REMOVE, this);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbSelectQueryBuilder createSelectQuery() {
|
||||
return new DbSelectQueryBuilder(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DbTableBuilder {
|
||||
|
||||
private final List<Object[]> columns = new ArrayList<>();
|
||||
private final String name;
|
||||
private final DbConnection con;
|
||||
private Object[] primary_key = null;
|
||||
|
||||
public DbTableBuilder(@Nonnull String name, @Nonnull DbConnection con) {
|
||||
this.name = name;
|
||||
this.con = con;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <T, V> DbTableBuilder withPrimaryKey(String name, DbColumnDataType<T, V> type) {
|
||||
if (primary_key != null) {
|
||||
throw new IllegalStateException("primary key was already set");
|
||||
}
|
||||
primary_key = new Object[]{name, type, false};
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <T, V> DbTableBuilder withColumn(String name, DbColumnDataType<T, V> type, boolean nullable) {
|
||||
columns.add(new Object[]{name, type, nullable});
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <T, V> DbTableBuilder withColumn(String name, DbColumnDataType<T, V> type) {
|
||||
return withColumn(name, type, false);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbTable build() {
|
||||
if (primary_key == null) {
|
||||
throw new IllegalStateException("primary key is not set");
|
||||
}
|
||||
|
||||
return new DbTable(con, name, primary_key, columns);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class DbUpdateQueryBuilder {
|
||||
|
||||
private final DbTable table;
|
||||
private final DbQueryType type;
|
||||
private final Map<DbColumn<?, ?>, Object> object_map = new HashMap<>();
|
||||
private DbCondition condition = null;
|
||||
|
||||
protected DbUpdateQueryBuilder(@Nonnull DbQueryType type, @Nonnull DbTable table) {
|
||||
this.table = table;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <T extends DbColumnDataType<?, V>, V> DbUpdateQueryBuilder setColumn(@Nonnull DbColumn<T, V> column, @Nullable V data) {
|
||||
if (!column.isNullable())
|
||||
throw new IllegalArgumentException("Column " + column.getName() + " does not accept null values.");
|
||||
|
||||
object_map.put(column, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <V> DbUpdateQueryBuilder setColumn(@Nonnegative int columnIndex, @Nullable V data) {
|
||||
DbColumn<?, ?> c = table.getColumns().get(columnIndex);
|
||||
|
||||
if (data != null) {
|
||||
if (!data.getClass().isAssignableFrom(c.getDataType())) {
|
||||
throw new IllegalArgumentException(String.format("Invalid data type provided. Expected: %s, provided: %s", c.getDataType().getCanonicalName(), data.getClass().getCanonicalName()));
|
||||
}
|
||||
} else {
|
||||
if (!c.isNullable())
|
||||
throw new IllegalArgumentException("Column " + c.getName() + " does not accept null values.");
|
||||
}
|
||||
|
||||
object_map.put(c, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <V> DbUpdateQueryBuilder setColumn(@Nonnull String name, @Nullable V data) {
|
||||
DbColumn<?, ?> col = null;
|
||||
for (DbColumn<?, ?> c : table.getColumns()) {
|
||||
if (c.getName().equalsIgnoreCase(name)) {
|
||||
col = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (col == null)
|
||||
throw new IllegalArgumentException(String.format("Column '%s' does not exist.", name));
|
||||
|
||||
if (data != null) {
|
||||
if (!data.getClass().isAssignableFrom(col.getDataType())) {
|
||||
throw new IllegalArgumentException(String.format("Invalid data type provided. Expected: %s, provided: %s", col.getDataType().getCanonicalName(), data.getClass().getCanonicalName()));
|
||||
}
|
||||
} else {
|
||||
if (!col.isNullable())
|
||||
throw new IllegalArgumentException(String.format("Column '%s' does not accept null values.", col.getName()));
|
||||
}
|
||||
|
||||
object_map.put(col, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbUpdateQueryBuilder where(@Nonnull Function<DbConditionBuilder, DbCondition> f) {
|
||||
if (condition != null) {
|
||||
throw new IllegalStateException("WHERE condition has already been set.");
|
||||
}
|
||||
|
||||
condition = f.apply(new DbConditionBuilder(table));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbQuery build() {
|
||||
return new DbQuery(type, table, object_map, condition);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
package me.yuri.yuriapi.api.db;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.yuri.yuriapi.api.utils.UUIDUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.libs.org.apache.commons.codec.binary.Hex;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
public class SqliteConnection extends DbConnection {
|
||||
|
||||
protected SqliteConnection(String connectionString) {
|
||||
super(connectionString);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Class<?> forName() throws ClassNotFoundException {
|
||||
return Class.forName("org.sqlite.JDBC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTable(@Nonnull DbTable t, boolean force) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("CREATE TABLE ");
|
||||
|
||||
if (!force)
|
||||
sb.append("IF NOT EXISTS ");
|
||||
|
||||
sb.append(t.getName()).append('(').append(t.getPrimaryKey().getName()).append(' ')
|
||||
.append(transformDataType(t.getPrimaryKey().getType())).append(' ').append("PRIMARY KEY NOT NULL");
|
||||
|
||||
for (DbColumn<?, ?> c : t.getNormalColums()) {
|
||||
sb.append(',').append(c.getName()).append(' ').append(transformDataType(c.getType())).append(c.isNullable() ? "" : " NOT NULL");
|
||||
}
|
||||
|
||||
sb.append(");");
|
||||
String stmt = sb.toString();
|
||||
|
||||
if (stmt.contains("'")) {
|
||||
throw new IllegalArgumentException("\"'\" characters are not allowed.");
|
||||
}
|
||||
|
||||
try {
|
||||
this.connection.createStatement().executeUpdate(stmt);
|
||||
this.tables.add(t);
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String transformDataType(@Nonnull DbColumnDataType<?, ?> type) {
|
||||
switch (type.getId()) {
|
||||
case 0:
|
||||
case 6:
|
||||
return "INT";
|
||||
case 7:
|
||||
case 8:
|
||||
return "TEXT";
|
||||
case 4:
|
||||
case 3:
|
||||
case 5:
|
||||
return "BIGINT";
|
||||
case 1:
|
||||
case 2:
|
||||
return "BLOB";
|
||||
case 9:
|
||||
case 10:
|
||||
return "REAL";
|
||||
default:
|
||||
throw new RuntimeException("that's not possible bruh");
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String serializeObject(@Nullable Object o) {
|
||||
if (o == null) {
|
||||
return "NULL";
|
||||
} else if (o instanceof String) {
|
||||
return String.format("'%s'", sanitize((String) o));
|
||||
} else if (o instanceof UUID) {
|
||||
return String.format("X'%s'", Hex.encodeHexString(UUIDUtils.toByteArray((UUID) o)));
|
||||
} else if (o instanceof Location) {
|
||||
Location l = ((Location) o);
|
||||
return String.format("'%f:%f:%f:%s'", l.getX(), l.getY(), l.getZ(), Objects.requireNonNull(l.getWorld()).getName());
|
||||
} else if (o instanceof ItemStack) {
|
||||
Base64.Encoder en = Base64.getEncoder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, Object> e : ((ItemStack) o).serialize().entrySet()) {
|
||||
sb.append(en.encodeToString(e.getKey().getBytes(StandardCharsets.UTF_8))).append(':')
|
||||
.append(en.encodeToString(String.valueOf(e.getValue()).getBytes(StandardCharsets.UTF_8)))
|
||||
.append(',');
|
||||
}
|
||||
sb.deleteCharAt(sb.length());
|
||||
return sb.toString();
|
||||
}
|
||||
return String.valueOf(o);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object deserializeObject(@Nonnull DbColumnDataType<?, ?> type, @Nullable Object o) {
|
||||
if (o == null)
|
||||
return null;
|
||||
if (o instanceof String) {
|
||||
String str = desanitize(((String) o));
|
||||
if (type.getBoxedDataType().isAssignableFrom(Location.class)) {
|
||||
String[] s = str.split(":", 4);
|
||||
return new Location(Bukkit.getWorld(s[3]), Double.parseDouble(s[0]), Double.parseDouble(s[1]), Double.parseDouble(s[2]));
|
||||
} else if (type.getBoxedDataType().isAssignableFrom(ItemStack.class)) {
|
||||
String[] s = str.split(",");
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
for (String s2 : s) {
|
||||
String[] s3 = s2.split(":");
|
||||
Base64.Decoder d = Base64.getDecoder();
|
||||
map.put(new String(d.decode(s3[0])), new String(d.decode(s3[1])));
|
||||
}
|
||||
return ItemStack.deserialize(map);
|
||||
}
|
||||
return str.replace("''", "'");
|
||||
} else if (o instanceof byte[]) {
|
||||
if (type.getBoxedDataType().isAssignableFrom(UUID.class)) {
|
||||
return UUIDUtils.toUUID((((byte[]) o)));
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbQueryResult select(DbSelectQuery q) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("SELECT ");
|
||||
|
||||
for (DbColumn<?, ?> col : q.getColumns()) {
|
||||
sb.append(col.getName()).append(',');
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1).append(" FROM ").append(q.getTable().getName());
|
||||
|
||||
if (q.getCondition() != null) {
|
||||
sb.append(" WHERE");
|
||||
int depth = 0;
|
||||
for (DbExpression cmp : q.getCondition().getExpressionList()) {
|
||||
sb.append(' ').append(cmp.linkBefore().getLiteral()).append(' ');
|
||||
|
||||
if (cmp.getDepth() > depth)
|
||||
sb.append('(');
|
||||
else if (cmp.getDepth() < cmp.getDepth())
|
||||
sb.append(')');
|
||||
|
||||
depth = cmp.getDepth();
|
||||
|
||||
sb.append(cmp.getColumn().getName()).append(cmp.getComparisonType().getLiteral()).append(serializeObject(cmp.getValue()));
|
||||
}
|
||||
if (depth > 0)
|
||||
sb.append(')');
|
||||
}
|
||||
|
||||
sb.append(';');
|
||||
|
||||
try {
|
||||
ResultSet rs = connection.createStatement().executeQuery(sb.toString());
|
||||
return new DbQueryResult(this, q.getTable(), ImmutableList.copyOf(q.getColumns()), rs);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
@Override
|
||||
public int update(DbQuery q) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
switch (q.getQueryType()) {
|
||||
case INSERT:
|
||||
sb.append("INSERT OR REPLACE INTO ").append(q.getTable().getName()).append("(");
|
||||
for (DbColumn<?, ?> c : q.getColumnMap().keySet()) {
|
||||
sb.append(c.getName()).append(',');
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
sb.append(") VALUES (");
|
||||
for (Object oo : q.getColumnMap().values()) {
|
||||
sb.append(this.serializeObject(oo)).append(',');
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
sb.append(')');
|
||||
break;
|
||||
case UPDATE:
|
||||
sb.append("UPDATE ").append(q.getTable().getName()).append(" SET ");
|
||||
for (Map.Entry<DbColumn<?, ?>, Object> e : q.getColumnMap().entrySet()) {
|
||||
sb.append(e.getKey().getName()).append(" = ").append(serializeObject(e.getValue())).append(',');
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1).append(' ');
|
||||
break;
|
||||
case REMOVE:
|
||||
sb.append("DELETE FROM ").append(q.getTable().getName()).append(' ');
|
||||
break;
|
||||
}
|
||||
|
||||
if (q.getQueryType() != DbQueryType.INSERT && q.getCondition() != null && !q.getCondition().getExpressionList().isEmpty()) {
|
||||
sb.append("WHERE");
|
||||
int depth = 0;
|
||||
for (DbExpression cmp : q.getCondition().getExpressionList()) {
|
||||
sb.append(' ').append(cmp.linkBefore().getLiteral()).append(' ');
|
||||
|
||||
if (cmp.getDepth() > depth)
|
||||
sb.append('(');
|
||||
else if (cmp.getDepth() < cmp.getDepth())
|
||||
sb.append(')');
|
||||
|
||||
depth = cmp.getDepth();
|
||||
|
||||
sb.append(cmp.getColumn().getName()).append(cmp.getComparisonType().getLiteral()).append(serializeObject(cmp.getValue()));
|
||||
}
|
||||
if (depth > 0)
|
||||
sb.append(')');
|
||||
|
||||
}
|
||||
|
||||
sb.append(';');
|
||||
try {
|
||||
return connection.createStatement().executeUpdate(sb.toString());
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private String sanitize(String input) {
|
||||
return input.replace("'", "''");
|
||||
}
|
||||
|
||||
private String desanitize(String input) {
|
||||
return input.replace("''", "'");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package me.yuri.yuriapi.api.economy;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.db.DbComparisonType;
|
||||
import me.yuri.yuriapi.api.db.DbQueryResult;
|
||||
import me.yuri.yuriapi.api.event.EventManager;
|
||||
import me.yuri.yuriapi.api.event.player.PlayerFundsChangeEvent;
|
||||
import me.yuri.yuriapi.api.utils.configuration.ConfigVar;
|
||||
import me.yuri.yuriapi.utils.DbManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
public class EconomyManager {
|
||||
|
||||
private static final EconomyManager inst = new EconomyManager();
|
||||
private static final Map<OfflinePlayer, Integer> fundTable = new ConcurrentHashMap<>();
|
||||
@ConfigVar("currencySymbol")
|
||||
private static String currencySymbol;
|
||||
@ConfigVar("currencyName")
|
||||
private static String currencyName;
|
||||
|
||||
private EconomyManager() {
|
||||
}
|
||||
|
||||
public static EconomyManager getInstance() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
public static String getCurrencySymbol() {
|
||||
return currencySymbol;
|
||||
}
|
||||
|
||||
public static String getCurrencyName() {
|
||||
return currencyName;
|
||||
}
|
||||
|
||||
public static int getFunds(YPlayer p) {
|
||||
int i = 0;
|
||||
if (!fundTable.containsKey(p.getBasePlayer()))
|
||||
fundTable.put(p.getBasePlayer(), i);
|
||||
else i = fundTable.get(p.getBasePlayer());
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void addFunds(YPlayer p, int amount) {
|
||||
int i = getFunds(p);
|
||||
setFunds(p, i + amount);
|
||||
}
|
||||
|
||||
public static boolean subtractFunds(YPlayer p, int amount) {
|
||||
int i = getFunds(p) - amount;
|
||||
if (i < 0) return false;
|
||||
setFunds(p, i);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setFunds(YPlayer p, int amount) {
|
||||
fundTable.put(p.getBasePlayer(), amount);
|
||||
EventManager.executeEvent(new PlayerFundsChangeEvent(p, fundTable.getOrDefault(p.getBasePlayer(), 0), amount));
|
||||
}
|
||||
|
||||
public static void saveChanges() {
|
||||
for (Map.Entry<OfflinePlayer, Integer> e : fundTable.entrySet()) {
|
||||
DbManager.z_().getTable("funds")
|
||||
.createInsertQuery()
|
||||
.setColumn(0, e.getKey().getUniqueId())
|
||||
.setColumn(1, e.getValue()).setColumn(2, Instant.now().toEpochMilli())
|
||||
.build().execute();
|
||||
System.out.println("SAVING: " + e.getKey().getUniqueId() + ":" + e.getKey().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveFor(YPlayer p) {
|
||||
DbManager.z_().getTable("funds")
|
||||
.createInsertQuery()
|
||||
.setColumn(0, p.getBasePlayer().getUniqueId())
|
||||
.setColumn(1, p.getFunds())
|
||||
.setColumn(2, Instant.now().toEpochMilli())
|
||||
.build().execute();
|
||||
System.out.println("Saved for: " + p.getBasePlayer().getName() + ":" + p.getFunds());
|
||||
}
|
||||
|
||||
public static void loadFor(YPlayer p) {
|
||||
DbQueryResult r = DbManager.z_().getTable("funds")
|
||||
.createSelectQuery().columns("funds")
|
||||
.where(w -> w.forColumn("uuid").value(DbComparisonType.EQUALS, p.getBasePlayer().getUniqueId()).end())
|
||||
.build().execute();
|
||||
|
||||
if (r.next())
|
||||
fundTable.put(p.getBasePlayer(), (int) r.get(0));
|
||||
|
||||
r.close();
|
||||
System.out.println("loaded for: " + p.getBasePlayer().getName() + ":" + p.getFunds());
|
||||
}
|
||||
|
||||
public static FutureTask<Boolean> loadFromDbAsync() {
|
||||
return new FutureTask<>(() -> {
|
||||
DbQueryResult r = DbManager.z_().getTable("funds").createSelectQuery().all().build().execute();
|
||||
|
||||
while (r.next()) {
|
||||
fundTable.put(Bukkit.getOfflinePlayer((UUID) r.get(0)), (int) r.get(1));
|
||||
System.out.println(r.get(0) + ":" + r.get(1) + " > " + Bukkit.getOfflinePlayer((UUID) r.get(0)).getName());
|
||||
}
|
||||
|
||||
r.close();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
public interface Cancellable {
|
||||
boolean isCancelled();
|
||||
|
||||
void setCancelled(boolean cancel);
|
||||
}
|
20
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/event/Event.java
Executable file
20
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/event/Event.java
Executable file
|
@ -0,0 +1,20 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
public class Event {
|
||||
public enum Priority {
|
||||
|
||||
HIGHEST(4), HIGH(3), NORMAL(2), LOW(1), LOWEST(0);
|
||||
|
||||
private final int priority;
|
||||
|
||||
Priority(int i) {
|
||||
priority = i;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
/**
|
||||
* Base interface that must be implemented in any class with EventSubscriber annotations
|
||||
*/
|
||||
public interface EventListener {
|
||||
}
|
158
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/event/EventManager.java
Executable file
158
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/event/EventManager.java
Executable file
|
@ -0,0 +1,158 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.event.player.PlayerItemAttackEvent;
|
||||
import me.yuri.yuriapi.api.event.player.PlayerItemUseEvent;
|
||||
import me.yuri.yuriapi.api.reflectionless.Reflectionless;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
public class EventManager implements Listener {
|
||||
|
||||
private static final EventManager inst = new EventManager();
|
||||
private static final boolean isOn = true;
|
||||
private static final Map<Map.Entry<Plugin, EventListener>, List<Method>> eventRegistrar = new ConcurrentHashMap<>();
|
||||
|
||||
private EventManager() {
|
||||
}
|
||||
|
||||
public static EventManager getInstance() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method registers an event listener
|
||||
*
|
||||
* @param plugin Main plugin class instance of the listener
|
||||
* @param listener Listener class instance
|
||||
* @author Yuri
|
||||
*/
|
||||
public static void registerEvent(Plugin plugin, EventListener listener) {
|
||||
for (Method method : listener.getClass().getMethods()) {
|
||||
if (method.isAnnotationPresent(EventSubscriber.class)) {
|
||||
Map.Entry<Plugin, EventListener> entry = new AbstractMap.SimpleEntry<>(plugin, listener);
|
||||
List<Method> methods = eventRegistrar.getOrDefault(entry, new ArrayList<>());
|
||||
methods.add(method);
|
||||
methods.sort(Comparator.comparingInt(m -> m.getAnnotation(EventSubscriber.class).value().getPriority()));
|
||||
Collections.reverse(methods);
|
||||
eventRegistrar.put(entry, methods);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method unregisters all listeners registered with main plugin instance passed as argument. Main plugin class may be passed optionally.
|
||||
*
|
||||
* @param plugin Main plugin class instance of the listener
|
||||
* @param listener Listener class instance
|
||||
* @author Yuri
|
||||
*/
|
||||
public static void unregisterEvent(@Nullable Plugin plugin, EventListener listener) {
|
||||
if (plugin != null) {
|
||||
Map.Entry<Plugin, EventListener> entry = new AbstractMap.SimpleEntry<>(plugin, listener);
|
||||
if (eventRegistrar.containsKey(entry)) {
|
||||
eventRegistrar.put(entry, new ArrayList<>());
|
||||
}
|
||||
eventRegistrar.remove(entry);
|
||||
} else {
|
||||
Optional<Map.Entry<Plugin, EventListener>> opEntry = eventRegistrar.keySet().stream().filter(entry -> entry.getValue().equals(listener)).findFirst();
|
||||
|
||||
if (opEntry.isPresent()) {
|
||||
Map.Entry<Plugin, EventListener> entry = opEntry.get();
|
||||
|
||||
eventRegistrar.remove(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method unregisters all listeners registered with main plugin instance passed as argument
|
||||
*
|
||||
* @param plugin Main plugin class instance
|
||||
* @author Yuri
|
||||
*/
|
||||
public static void unregisterAllPluginEvents(Plugin plugin) {
|
||||
eventRegistrar.keySet().stream().filter(entry -> entry.getKey().equals(plugin)).forEach(eventRegistrar::remove);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method unregisters an event listener passed as argument
|
||||
*
|
||||
* @param listener Listener class instance
|
||||
* @author Yuri
|
||||
*/
|
||||
public static void unregisterEvent(EventListener listener) {
|
||||
unregisterEvent(null, listener);
|
||||
}
|
||||
|
||||
public static Event executeEvent(Event event) {
|
||||
FutureTask<Event> futureTask = new FutureTask<>(() -> call(event));
|
||||
|
||||
futureTask.run();
|
||||
|
||||
try {
|
||||
return futureTask.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
private static Event call(Event event) {
|
||||
if (isOn) {
|
||||
for (Map.Entry<Plugin, EventListener> entry : eventRegistrar.keySet()) {
|
||||
List<Method> methods = eventRegistrar.get(entry);
|
||||
|
||||
methods.stream()
|
||||
.filter(method -> method.isAnnotationPresent(EventSubscriber.class) && method.getParameterTypes()[0] == event.getClass())
|
||||
.sorted(Comparator.comparingInt(method -> Event.Priority.HIGHEST.getPriority() - method.getAnnotation(EventSubscriber.class).value().getPriority()))
|
||||
.forEachOrdered(method -> {
|
||||
try {
|
||||
Reflectionless.get(method).call(entry.getValue(), event);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEvent(org.bukkit.event.Event e) {
|
||||
Bukkit.getConsoleSender().sendMessage("EVENT");
|
||||
if (e instanceof PlayerInteractEvent) {
|
||||
PlayerInteractEvent ev = (PlayerInteractEvent) e;
|
||||
if ((ev.getAction() == Action.RIGHT_CLICK_AIR || ev.getAction() == Action.LEFT_CLICK_AIR) && ev.hasItem()) {
|
||||
executeEvent(new PlayerItemUseEvent(YPlayer.get(ev.getPlayer()), ev.getItem()));
|
||||
return;
|
||||
}
|
||||
} else if (e instanceof EntityDamageByEntityEvent) {
|
||||
EntityDamageByEntityEvent ev = (EntityDamageByEntityEvent) e;
|
||||
if (ev instanceof Player) {
|
||||
Player p = ((Player) ev);
|
||||
ItemStack i = p.getInventory().getItemInMainHand();
|
||||
if (i.getType() != Material.AIR) {
|
||||
executeEvent(new PlayerItemAttackEvent(YPlayer.get(p), i, ev.getEntity()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface EventSubscriber {
|
||||
Event.Priority value() default Event.Priority.NORMAL;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public abstract class PacketEvent extends Event implements Cancellable {
|
||||
|
||||
private final Player player;
|
||||
private final Object packetObject;
|
||||
private final String type;
|
||||
private final long timestamp;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
public PacketEvent(Player p, Object packet, String type) {
|
||||
player = p;
|
||||
packetObject = p;
|
||||
this.type = type;
|
||||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public Object getPacketObject() {
|
||||
return packetObject;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PacketIncomeEvent extends PacketEvent {
|
||||
public PacketIncomeEvent(Player p, Object packet, String type) {
|
||||
super(p, packet, type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package me.yuri.yuriapi.api.event;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PacketOutcomeEvent extends PacketEvent {
|
||||
public PacketOutcomeEvent(Player p, Object packet, String type) {
|
||||
super(p, packet, type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package me.yuri.yuriapi.api.event.player;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.event.Event;
|
||||
|
||||
public class PlayerEvent extends Event {
|
||||
|
||||
private final YPlayer player;
|
||||
|
||||
public PlayerEvent(YPlayer player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public YPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package me.yuri.yuriapi.api.event.player;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
|
||||
public class PlayerFundsChangeEvent extends PlayerEvent {
|
||||
|
||||
private final int init, after;
|
||||
|
||||
public PlayerFundsChangeEvent(YPlayer player, int initial, int after) {
|
||||
super(player);
|
||||
this.init = initial;
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
public int getBefore() {
|
||||
return init;
|
||||
}
|
||||
|
||||
public int getAfter() {
|
||||
return after;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package me.yuri.yuriapi.api.event.player;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class PlayerItemAttackEvent extends PlayerItemEvent {
|
||||
private final Entity damaged;
|
||||
|
||||
public PlayerItemAttackEvent(YPlayer player, ItemStack item, Entity damaged) {
|
||||
super(player, item);
|
||||
this.damaged = damaged;
|
||||
}
|
||||
|
||||
public Entity getAtackedEntity() {
|
||||
return damaged;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package me.yuri.yuriapi.api.event.player;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.item.CustomItem;
|
||||
import me.yuri.yuriapi.api.item.ItemRegistry;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
public class PlayerItemEvent extends PlayerEvent {
|
||||
private final ItemStack item;
|
||||
private final CustomItem ci;
|
||||
|
||||
public PlayerItemEvent(YPlayer player, ItemStack is) {
|
||||
super(player);
|
||||
this.item = is;
|
||||
if (is.hasItemMeta()) {
|
||||
assert is.getItemMeta() != null;
|
||||
String s = is.getItemMeta().getPersistentDataContainer().getOrDefault(Desu.getKey(0), PersistentDataType.STRING, "null");
|
||||
ci = ItemRegistry.getItem(s);
|
||||
} else ci = null;
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public boolean isCustom() {
|
||||
return ci != null;
|
||||
}
|
||||
|
||||
public CustomItem getCustomItem() {
|
||||
return ci;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package me.yuri.yuriapi.api.event.player;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class PlayerItemUseEvent extends PlayerItemEvent {
|
||||
|
||||
public PlayerItemUseEvent(YPlayer player, ItemStack item) {
|
||||
super(player, item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package me.yuri.yuriapi.api.inventory;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ButtonClickEvent {
|
||||
private final InventoryClickEvent event;
|
||||
private final CustomInventory inv;
|
||||
private final int slot;
|
||||
private final YPlayer player;
|
||||
private boolean canc = false;
|
||||
|
||||
public ButtonClickEvent(InventoryClickEvent e, CustomInventory i, int slot) {
|
||||
this.inv = i;
|
||||
this.slot = slot;
|
||||
this.event = e;
|
||||
this.player = YPlayer.get((Player) e.getWhoClicked());
|
||||
}
|
||||
|
||||
public InventoryClickEvent getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public CustomInventory getInventory() {
|
||||
return inv;
|
||||
}
|
||||
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
public ItemStack getItemstack() {
|
||||
return inv.getAt(slot);
|
||||
}
|
||||
|
||||
public YPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public void cancelClickSound(boolean cancel) {
|
||||
canc = cancel;
|
||||
}
|
||||
|
||||
public boolean isClickSoundCancelled() {
|
||||
return canc;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
package me.yuri.yuriapi.api.inventory;
|
||||
|
||||
import me.yuri.yuriapi.api.item.CustomItem;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CustomInventory implements Cloneable {
|
||||
protected static List<CustomInventory> opened = new ArrayList<>();
|
||||
protected final Consumer<InventoryCloseEvent> onclose;
|
||||
private final Inventory inventory;
|
||||
private final boolean readonly;
|
||||
private final List<Consumer<InventoryClickEvent>> clickEvents = new ArrayList<>();
|
||||
private final List<Consumer<InventoryDragEvent>> dragEvents = new ArrayList<>();
|
||||
private final Map<Integer, Consumer<ButtonClickEvent>> buttons = new HashMap<>();
|
||||
private final Sound clicc;
|
||||
|
||||
public CustomInventory(Inventory i, boolean readonly) {
|
||||
this(i, Collections.emptyList(), Collections.emptyList(), readonly, Collections.emptyMap(), null, null);
|
||||
}
|
||||
|
||||
public CustomInventory(Inventory i, @Nonnull List<Consumer<InventoryClickEvent>> c, @Nonnull List<Consumer<InventoryDragEvent>> d, boolean readonly, @Nonnull Map<Integer, Consumer<ButtonClickEvent>> btn, @Nullable Sound clicksound, @Nullable Consumer<InventoryCloseEvent> close) {
|
||||
this.inventory = i;
|
||||
this.readonly = readonly;
|
||||
clickEvents.addAll(c);
|
||||
dragEvents.addAll(d);
|
||||
buttons.putAll(btn);
|
||||
opened.add(this);
|
||||
clicc = clicksound;
|
||||
onclose = close;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CustomInventory get(Inventory i) {
|
||||
for (CustomInventory c : opened) {
|
||||
if (c.inventory.equals(i))
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Inventory getBaseInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public boolean isReadonly() {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
public List<Consumer<InventoryClickEvent>> getClickEvents() {
|
||||
return clickEvents;
|
||||
}
|
||||
|
||||
public List<Consumer<InventoryDragEvent>> getDragEvents() {
|
||||
return dragEvents;
|
||||
}
|
||||
|
||||
public Map<Integer, Consumer<ButtonClickEvent>> getButtonMap() {
|
||||
return buttons;
|
||||
}
|
||||
|
||||
public void setItem(int pos, ItemStack it) {
|
||||
this.inventory.setItem(pos, it);
|
||||
}
|
||||
|
||||
public void setItem(int pos, CustomItem it) {
|
||||
this.inventory.setItem(pos, it.getItemstack());
|
||||
}
|
||||
|
||||
public void removeItem(int pos) {
|
||||
this.inventory.setItem(pos, null);
|
||||
}
|
||||
|
||||
public void rename(int pos, String name) {
|
||||
rename(pos, '&', name);
|
||||
}
|
||||
|
||||
public void rename(int pos, char colorCode, String name) {
|
||||
ItemStack i = inventory.getItem(pos);
|
||||
if (i == null) return;
|
||||
ItemMeta im = i.hasItemMeta() ? i.getItemMeta() : Bukkit.getItemFactory().getItemMeta(i.getType());
|
||||
assert im != null;
|
||||
im.setDisplayName(Colored.colorize(colorCode, name));
|
||||
i.setItemMeta(im);
|
||||
inventory.setItem(pos, i);
|
||||
}
|
||||
|
||||
public void changeLore(int pos, List<String> lore) {
|
||||
ItemStack i = inventory.getItem(pos);
|
||||
if (i == null) return;
|
||||
ItemMeta im = i.hasItemMeta() ? i.getItemMeta() : Bukkit.getItemFactory().getItemMeta(i.getType());
|
||||
assert im != null;
|
||||
im.setLore(lore);
|
||||
i.setItemMeta(im);
|
||||
inventory.setItem(pos, i);
|
||||
}
|
||||
|
||||
public void insertToLore(int pos, int startIndex, char colorCode, String... lore) {
|
||||
ItemStack i = inventory.getItem(pos);
|
||||
|
||||
if (i == null) return;
|
||||
|
||||
ItemMeta im = i.hasItemMeta() ? i.getItemMeta() : Bukkit.getItemFactory().getItemMeta(i.getType());
|
||||
assert im != null;
|
||||
|
||||
List<String> lr = Arrays.asList(lore);
|
||||
lr.forEach(c -> Colored.colorize(colorCode, lore));
|
||||
|
||||
if (im.hasLore())
|
||||
Objects.requireNonNull(im.getLore()).addAll(startIndex, lr);
|
||||
else im.setLore(lr);
|
||||
|
||||
i.setItemMeta(im);
|
||||
inventory.setItem(pos, i);
|
||||
}
|
||||
|
||||
public void replaceLoreAt(int pos, int startIndex, String... lore) {
|
||||
replaceLoreAt(pos, startIndex, '&', lore);
|
||||
}
|
||||
|
||||
public void replaceLoreAt(int pos, int startIndex, char colorCode, String... lore) {
|
||||
ItemStack i = inventory.getItem(pos);
|
||||
|
||||
if (i == null) return;
|
||||
|
||||
ItemMeta im = i.hasItemMeta() ? i.getItemMeta() : Bukkit.getItemFactory().getItemMeta(i.getType());
|
||||
assert im != null;
|
||||
|
||||
List<String> lr = Arrays.asList(lore);
|
||||
lr.forEach(c -> Colored.colorize(colorCode, lore));
|
||||
|
||||
if (im.hasLore()) {
|
||||
assert im.getLore() != null;
|
||||
for (int ii = 0; ii < lr.size(); ii++) {
|
||||
im.getLore().set(ii + startIndex, lr.get(ii));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i.setItemMeta(im);
|
||||
inventory.setItem(pos, i);
|
||||
}
|
||||
|
||||
public void insertToLore(int pos, int startIndex, String... lore) {
|
||||
insertToLore(pos, startIndex, '&', lore);
|
||||
}
|
||||
|
||||
public void open(HumanEntity e) {
|
||||
e.openInventory(this.inventory);
|
||||
}
|
||||
|
||||
public ItemStack getAt(int pos) {
|
||||
return inventory.getItem(pos);
|
||||
}
|
||||
|
||||
public Sound getClickSound() {
|
||||
return clicc;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package me.yuri.yuriapi.api.inventory;
|
||||
|
||||
import me.yuri.yuriapi.api.item.CustomItem;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CustomItemSupplier {
|
||||
CustomItem create();
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
package me.yuri.yuriapi.api.inventory;
|
||||
|
||||
import me.yuri.yuriapi.api.item.CustomItem;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class InventoryBuilder {
|
||||
|
||||
private final int size;
|
||||
private final InventoryType type;
|
||||
private final Map<Integer, Object> items = new HashMap<>();
|
||||
private final int[][] coords;
|
||||
private final List<Consumer<InventoryClickEvent>> clickEvents = new ArrayList<>();
|
||||
private final List<Consumer<InventoryDragEvent>> dragEvents = new ArrayList<>();
|
||||
private final Map<Integer, Consumer<ButtonClickEvent>> buttons = new HashMap<>();
|
||||
private Consumer<InventoryCloseEvent> oncloseEvent = null;
|
||||
private String title = null;
|
||||
private InventoryHolder owner;
|
||||
private boolean readonly = false;
|
||||
private Sound clickSound = null;
|
||||
|
||||
public InventoryBuilder(@Nonnull InventoryType type) {
|
||||
this.type = type;
|
||||
size = type.getDefaultSize();
|
||||
coords = new int[size / 9][9];
|
||||
for (int i = 0; i < size / 9; i++) {
|
||||
for (int a = 0; a < 9; a++) {
|
||||
coords[i][a] = i * 9 + a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InventoryBuilder(@Nonnegative int size) {
|
||||
this.type = null;
|
||||
this.size = size;
|
||||
coords = new int[size / 9][9];
|
||||
for (int i = 0; i < size / 9; i++) {
|
||||
for (int a = 0; a < 9; a++) {
|
||||
coords[i][a] = i * 9 + a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InventoryBuilder() {
|
||||
this(InventoryType.CHEST);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public int[][] getCoordinates() {
|
||||
return coords;
|
||||
}
|
||||
|
||||
public int getPos(int x, int y) {
|
||||
return coords[y][x];
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withTitle(@Nullable String t, char colorCode) {
|
||||
title = Colored.colorize(colorCode, t);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withTitle(@Nullable String t) {
|
||||
title = Colored.colorize(t);
|
||||
//System.out.printf("Title: %s\n", title);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withOwner(@Nullable InventoryHolder owner) {
|
||||
this.owner = owner;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withClickEvent(@Nonnull Consumer<InventoryClickEvent> c) {
|
||||
this.clickEvents.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withDragEvent(@Nonnull Consumer<InventoryDragEvent> c) {
|
||||
this.dragEvents.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withItem(ItemStack i) {
|
||||
return withItem(i, getLowestUnoccupiedSlot());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withItem(CustomItem i, @Nonnegative int position) {
|
||||
items.put(position, i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withItem(CustomItem i) {
|
||||
return withItem(i, getLowestUnoccupiedSlot());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withItem(CustomItem i, @Nonnegative int x, @Nonnegative int y) {
|
||||
return withItem(i, coords[y][x]);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withItem(ItemStack i, @Nonnegative int x, @Nonnegative int y) {
|
||||
return withItem(i, coords[y][x]);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withItem(ItemStack i, @Nonnegative int position) {
|
||||
items.put(position, i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder fillItem(ItemStack item, @Nonnegative int start, @Nonnegative int end) {
|
||||
if (start > end)
|
||||
throw new IllegalArgumentException("Parameter 'start' is larger than 'end'.");
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
items.put(i, item);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder fillItem(CustomItem item, @Nonnegative int start, @Nonnegative int end) {
|
||||
if (start > end)
|
||||
throw new IllegalArgumentException("Parameter 'start' is larger than 'end'.");
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
items.put(i, item);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder fillItem(Material m, @Nonnegative int start, @Nonnegative int end) {
|
||||
if (start > end)
|
||||
throw new IllegalArgumentException("Parameter 'start' is larger than 'end'.");
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
items.put(i, new ItemStack(m));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder fillItem(ItemStackSupplier s, @Nonnegative int start, @Nonnegative int end) {
|
||||
if (start > end)
|
||||
throw new IllegalArgumentException("Parameter 'start' is larger than 'end'.");
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
items.put(i, s.create());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder fillItem(CustomItemSupplier s, @Nonnegative int start, @Nonnegative int end) {
|
||||
if (start > end)
|
||||
throw new IllegalArgumentException("Parameter 'start' is larger than 'end'.");
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
items.put(i, s.create());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder line(@Nonnegative int startX, @Nonnegative int startY, @Nonnegative int endX, @Nonnegative int endY, @Nonnull ItemStack s) {
|
||||
--endX;
|
||||
--endY;
|
||||
|
||||
float deltaX = endX - startX, deltaY = endY - startY;
|
||||
if (Math.round(deltaX) == 0) {
|
||||
for (int i = startY; i <= endY; i++) {
|
||||
items.put(coords[i][startX], s);
|
||||
}
|
||||
} else {
|
||||
float a = deltaY / deltaX;
|
||||
for (float xx = startX, yy = startY; xx <= endX; xx++) {
|
||||
items.put(coords[Math.round(yy)][Math.round(xx)], s);
|
||||
yy += a;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder line(@Nonnegative int startX, @Nonnegative int startY, @Nonnegative int endX, @Nonnegative int endY, @Nonnull ItemStackSupplier s) {
|
||||
return line(startX, startY, endX, endY, s.create());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder line(@Nonnegative int startX, @Nonnegative int startY, @Nonnegative int endX, @Nonnegative int endY, @Nonnull Material m) {
|
||||
return line(startX, startY, endX, endY, new ItemStack(m));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder applyItems(Map<Integer, Object> items) {
|
||||
this.items.putAll(items);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder applyItems(Consumer<Map<Integer, Object>> c) {
|
||||
c.accept(items);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Inventory createInv() {
|
||||
if (type != null) {
|
||||
if (title != null)
|
||||
return Bukkit.createInventory(owner, type, title);
|
||||
else
|
||||
return Bukkit.createInventory(owner, type);
|
||||
} else {
|
||||
if (title != null)
|
||||
return Bukkit.createInventory(owner, size, title);
|
||||
else
|
||||
return Bukkit.createInventory(owner, size);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnegative
|
||||
public int getLowestUnoccupiedSlot() {
|
||||
int a = 0;
|
||||
for (int b : this.items.keySet()) {
|
||||
if (a != b)
|
||||
break;
|
||||
++a;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder readOnly() {
|
||||
this.readonly = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder preventDrag() {
|
||||
this.dragEvents.add((e) -> e.setCancelled(true));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(ItemStack i, Consumer<ButtonClickEvent> c) {
|
||||
return addButton(i, getLowestUnoccupiedSlot(), c);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(ItemStackSupplier i, Consumer<ButtonClickEvent> c) {
|
||||
return addButton(i.create(), getLowestUnoccupiedSlot(), c);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(CustomItem i, @Nonnegative int position, Consumer<ButtonClickEvent> c) {
|
||||
items.put(position, i);
|
||||
buttons.put(position, c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(CustomItem i, Consumer<ButtonClickEvent> c) {
|
||||
return addButton(i, getLowestUnoccupiedSlot(), c);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(CustomItemSupplier i, Consumer<ButtonClickEvent> c) {
|
||||
return addButton(i.create(), getLowestUnoccupiedSlot(), c);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(CustomItem i, @Nonnegative int x, @Nonnegative int y, Consumer<ButtonClickEvent> c) {
|
||||
return addButton(i, coords[y][x], c);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(ItemStack i, @Nonnegative int x, @Nonnegative int y, Consumer<ButtonClickEvent> c) {
|
||||
return addButton(i, coords[y][x], c);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder addButton(ItemStack i, @Nonnegative int position, Consumer<ButtonClickEvent> c) {
|
||||
items.put(position, i);
|
||||
buttons.put(position, c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder withClickSound(@Nullable Sound s) {
|
||||
this.clickSound = s;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public InventoryBuilder onClose(@Nullable Consumer<InventoryCloseEvent> e) {
|
||||
this.oncloseEvent = e;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CustomInventory build() {
|
||||
Inventory i = createInv();
|
||||
for (Map.Entry<Integer, Object> ent : items.entrySet()) {
|
||||
|
||||
Object item = ent.getValue();
|
||||
if (ent.getValue() instanceof CustomItem) {
|
||||
item = ((CustomItem) item).getItemstack();
|
||||
}
|
||||
|
||||
//System.out.printf("Pos: %d, %s\n", ent.getKey(), ((ItemStack) item).getType().name());
|
||||
|
||||
i.setItem(ent.getKey(), (ItemStack) item);
|
||||
}
|
||||
return new CustomInventory(i, this.clickEvents, this.dragEvents, readonly, buttons, clickSound, oncloseEvent);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<Integer, Object> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package me.yuri.yuriapi.api.inventory;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class InventoryEvents implements Listener {
|
||||
private static final InventoryEvents inst = new InventoryEvents();
|
||||
|
||||
private InventoryEvents() {
|
||||
}
|
||||
|
||||
public static InventoryEvents instance() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
CustomInventory ci = CustomInventory.get(e.getInventory());
|
||||
if (ci == null) return;
|
||||
|
||||
Consumer<ButtonClickEvent> c = ci.getButtonMap().getOrDefault(e.getSlot(), null);
|
||||
if (c != null) {
|
||||
e.setCancelled(true);
|
||||
ButtonClickEvent evt = new ButtonClickEvent(e, ci, e.getSlot());
|
||||
c.accept(evt);
|
||||
if (!evt.isClickSoundCancelled())
|
||||
e.getWhoClicked().getWorld().playSound(e.getWhoClicked().getLocation(), ci.getClickSound(), 1, 1);
|
||||
}
|
||||
|
||||
if (ci.isReadonly()) e.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDrag(InventoryDragEvent e) {
|
||||
CustomInventory ci = CustomInventory.get(e.getInventory());
|
||||
if (ci == null) return;
|
||||
ci.getDragEvents().forEach(c -> c.accept(e));
|
||||
if (ci.isReadonly()) e.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClose(InventoryCloseEvent e) {
|
||||
CustomInventory ci = CustomInventory.get(e.getInventory());
|
||||
if (ci == null) return;
|
||||
if (ci.onclose != null)
|
||||
ci.onclose.accept(e);
|
||||
|
||||
CustomInventory.opened.removeIf(c -> c.getBaseInventory().equals(e.getInventory()) && c.getBaseInventory().getViewers().isEmpty());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package me.yuri.yuriapi.api.inventory;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ItemStackSupplier {
|
||||
ItemStack create();
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package me.yuri.yuriapi.api.item;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.api.utils.metadata.KeyFactory;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CustomItem implements Cloneable {
|
||||
private final ItemStack item;
|
||||
private final NamespacedKey key;
|
||||
private final List<Consumer<PlayerInteractEvent>> useEvents;
|
||||
private final List<Consumer<EntityDamageByEntityEvent>> attackEvents;
|
||||
private final List<Consumer<ItemBlockPlacedEvent>> placeEvents;
|
||||
|
||||
public CustomItem(ItemStack i, NamespacedKey key) {
|
||||
item = i;
|
||||
this.key = key;
|
||||
this.useEvents = new ArrayList<>();
|
||||
this.attackEvents = new ArrayList<>();
|
||||
this.placeEvents = new ArrayList<>();
|
||||
}
|
||||
|
||||
public CustomItem(ItemStack i, JavaPlugin pl, String key) {
|
||||
this(i, KeyFactory.getKeyFor(pl, key));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Consumer<PlayerInteractEvent>> getUseEvents() {
|
||||
return useEvents;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Consumer<EntityDamageByEntityEvent>> getAttackEvents() {
|
||||
return attackEvents;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Consumer<ItemBlockPlacedEvent>> getPlaceEvents() {
|
||||
return placeEvents;
|
||||
}
|
||||
|
||||
public void addUseEvent(Consumer<PlayerInteractEvent> e) {
|
||||
this.useEvents.add(e);
|
||||
}
|
||||
|
||||
public void addAttackEvent(Consumer<EntityDamageByEntityEvent> e) {
|
||||
this.attackEvents.add(e);
|
||||
}
|
||||
|
||||
public void addPlaceEvent(Consumer<ItemBlockPlacedEvent> e) {
|
||||
this.placeEvents.add(e);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemStack getItemstack() {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public NamespacedKey getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CustomItem clone() {
|
||||
try {
|
||||
return (CustomItem) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CustomItem from(ItemStack i) {
|
||||
if (i.hasItemMeta()) {
|
||||
assert i.getItemMeta() != null;
|
||||
String s = i.getItemMeta().getPersistentDataContainer().getOrDefault(Desu.getKey(0), PersistentDataType.STRING, "null");
|
||||
if (s.equals("null")) return null;
|
||||
return ItemRegistry.getItem(s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package me.yuri.yuriapi.api.item;
|
||||
|
||||
import me.yuri.yuriapi.api.utils.metadata.BlockMetaStorage;
|
||||
import me.yuri.yuriapi.api.utils.metadata.MetadataType;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class ItemBlockPlacedEvent {
|
||||
|
||||
private final BlockPlaceEvent event;
|
||||
|
||||
public ItemBlockPlacedEvent(BlockPlaceEvent e) {
|
||||
event = e;
|
||||
}
|
||||
|
||||
public BlockPlaceEvent getBaseEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public <T, V> void applyMetadata(JavaPlugin pl, String key, MetadataType<T, V> t, V data) {
|
||||
BlockMetaStorage.setMeta(event.getBlock(), pl, key, t, data);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
package me.yuri.yuriapi.api.item;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import me.yuri.yuriapi.api.utils.metadata.KeyFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.ShapelessRecipe;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ItemBuilder {
|
||||
|
||||
private final CustomItem item;
|
||||
private final Material type;
|
||||
private final List<Recipe> recipes = new ArrayList<>();
|
||||
private final JavaPlugin plugin;
|
||||
private ItemMeta meta;
|
||||
private boolean register = false;
|
||||
private boolean recipeRegister = false;
|
||||
private boolean isMetaDone = false;
|
||||
|
||||
public ItemBuilder(Material type, @Nonnull NamespacedKey key, JavaPlugin pl) {
|
||||
if (type == Material.AIR)
|
||||
throw new IllegalArgumentException("Item cannot be AIR");
|
||||
|
||||
if (ItemRegistry.getFor((JavaPlugin) Objects.requireNonNull(Bukkit.getPluginManager().getPlugin(key.getNamespace()))).getItems().stream().anyMatch(i -> i.getKey().equals(key))) {
|
||||
throw new IllegalStateException("Item with such key already exists.");
|
||||
}
|
||||
|
||||
this.plugin = pl;
|
||||
this.type = type;
|
||||
item = new CustomItem(new ItemStack(type), key);
|
||||
meta = item.getItemstack().hasItemMeta() ? item.getItemstack().getItemMeta() : Bukkit.getItemFactory().getItemMeta(item.getItemstack().getType());
|
||||
}
|
||||
|
||||
public ItemBuilder(Material type, @Nonnull JavaPlugin pl, @Nonnull String name) {
|
||||
if (type == Material.AIR)
|
||||
throw new IllegalArgumentException("Item cannot be AIR");
|
||||
NamespacedKey key = KeyFactory.getKeyFor(pl, name);
|
||||
|
||||
if (ItemRegistry.getFor(pl).getItems().stream().anyMatch(i -> i.getKey().equals(key))) {
|
||||
throw new IllegalStateException("Item with such key already exists.");
|
||||
}
|
||||
|
||||
this.plugin = pl;
|
||||
this.type = type;
|
||||
item = new CustomItem(new ItemStack(type), key);
|
||||
meta = item.getItemstack().hasItemMeta() ? item.getItemstack().getItemMeta() : Bukkit.getItemFactory().getItemMeta(item.getItemstack().getType());
|
||||
}
|
||||
|
||||
public static ItemStack createNameless(Material m) {
|
||||
return new ItemBuilder(m, Desu.getMain(), "null").withCustomName(" ").build().getItemstack();
|
||||
}
|
||||
|
||||
public static ItemStack createWithName(Material m, char colorCode, String name) {
|
||||
return new ItemBuilder(m, Desu.getMain(), "null").withCustomName(name, colorCode).buildMeta().build().getItemstack();
|
||||
}
|
||||
|
||||
public static ItemStack createWithName(Material m, String name) {
|
||||
return createWithName(m, '&', name);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CustomItem build() {
|
||||
if (!isMetaDone)
|
||||
item.getItemstack().setItemMeta(meta);
|
||||
|
||||
if (recipeRegister)
|
||||
recipes.forEach(Bukkit::addRecipe);
|
||||
|
||||
if (register)
|
||||
ItemRegistry.getFor(plugin).registerItem(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder registerOnBuild() {
|
||||
register = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder registerRecipes() {
|
||||
recipeRegister = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withCount(int count) {
|
||||
item.getItemstack().setAmount(count);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withEnchantment(@Nonnull Enchantment enchantment, int level) {
|
||||
item.getItemstack().addUnsafeEnchantment(enchantment, level);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withCustomName(@Nullable String name) {
|
||||
return withCustomName(name, '&');
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withCustomName(@Nullable String name, char colorCode) {
|
||||
meta.setDisplayName(Colored.colorize(colorCode, name));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder appendLore(@Nullable String name) {
|
||||
return appendLore(name, '&');
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder appendLore(@Nullable String name, char colorCode) {
|
||||
if (!meta.hasLore())
|
||||
meta.setLore(Collections.singletonList(Colored.colorize(colorCode, name)));
|
||||
else {
|
||||
List<String> lore = meta.getLore();
|
||||
assert lore != null;
|
||||
lore.add(Colored.colorize(colorCode, name));
|
||||
meta.setLore(lore);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <T, Z> ItemBuilder withData(@Nonnull String key, @Nonnull PersistentDataType<T, Z> type, Z data) {
|
||||
return withData(KeyFactory.getKeyFor(plugin, key), type, data);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public <T, Z> ItemBuilder withData(@Nonnull NamespacedKey key, @Nonnull PersistentDataType<T, Z> type, Z data) {
|
||||
meta.getPersistentDataContainer().set(key, type, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withRecipe(@Nonnull Recipe r) {
|
||||
recipes.add(r);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder buildMeta() {
|
||||
meta.getPersistentDataContainer().set(Desu.getKey(0), PersistentDataType.STRING, this.item.getKey().toString());
|
||||
item.getItemstack().setItemMeta(meta);
|
||||
isMetaDone = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withShapedRecipe(@Nonnull String row1, @Nonnull String row2, @Nonnull String row3, @Nonnull Map<Character, Material> ingredients) {
|
||||
ShapedRecipe sp = new ShapedRecipe(item.getKey(), item.getItemstack());
|
||||
sp.shape(row1, row2, row3);
|
||||
ingredients.forEach(sp::setIngredient);
|
||||
return withRecipe(sp);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withShapedRecipe(@Nonnull String row1, @Nonnull String row2, @Nonnull String row3, @Nonnull char[] chars, @Nonnull Material[] materials) {
|
||||
if (chars.length != materials.length) {
|
||||
throw new IllegalArgumentException("chars and materials must have equal lengths");
|
||||
}
|
||||
|
||||
ShapedRecipe sp = new ShapedRecipe(item.getKey(), item.getItemstack());
|
||||
sp.shape(row1, row2, row3);
|
||||
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
sp.setIngredient(chars[i], materials[i]);
|
||||
}
|
||||
|
||||
return withRecipe(sp);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withShapelessRecipe(@Nonnull Map<Material, Integer> ingredients) {
|
||||
ShapelessRecipe sl = new ShapelessRecipe(item.getKey(), item.getItemstack());
|
||||
ingredients.forEach((m, i) -> sl.addIngredient(i, m));
|
||||
return withRecipe(sl);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder withShapelessRecipe(@Nonnull int[] counts, @Nonnull Material[] materials) {
|
||||
if (counts.length != materials.length) {
|
||||
throw new IllegalArgumentException("counts and materials must have equal lengths");
|
||||
}
|
||||
ShapelessRecipe sl = new ShapelessRecipe(item.getKey(), item.getItemstack());
|
||||
for (int i = 0; i < counts.length; i++) {
|
||||
sl.addIngredient(counts[i], materials[i]);
|
||||
}
|
||||
return withRecipe(sl);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder onUse(Consumer<PlayerInteractEvent> e) {
|
||||
this.item.addUseEvent(e);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder onAttack(Consumer<EntityDamageByEntityEvent> e) {
|
||||
this.item.addAttackEvent(e);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder onPlace(Consumer<ItemBlockPlacedEvent> e) {
|
||||
this.item.addPlaceEvent(e);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemBuilder modifyItemMeta(Function<ItemMeta, ItemMeta> f) {
|
||||
meta = f.apply(meta);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Material getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ItemMeta getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Recipe> getRecipes() {
|
||||
return recipes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package me.yuri.yuriapi.api.item;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
public final class ItemEvents implements Listener {
|
||||
|
||||
private static final ItemEvents inst = new ItemEvents();
|
||||
|
||||
private ItemEvents() {
|
||||
}
|
||||
|
||||
public static ItemEvents instance() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void onItemAttack(EntityDamageByEntityEvent e) {
|
||||
if (e.getDamager() instanceof Player) {
|
||||
ItemStack is = ((Player) e.getDamager()).getInventory().getItemInMainHand();
|
||||
if (is.hasItemMeta()) {
|
||||
assert is.getItemMeta() != null;
|
||||
String s = is.getItemMeta().getPersistentDataContainer().getOrDefault(Desu.getKey(0), PersistentDataType.STRING, "null");
|
||||
CustomItem ci = ItemRegistry.getItem(s);
|
||||
if (ci != null) {
|
||||
ci.getAttackEvents().forEach(ev -> ev.accept(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void onItemUse(PlayerInteractEvent e) {
|
||||
if (e.getItem() != null && (e.getAction() != Action.PHYSICAL)) {
|
||||
if (e.getItem().hasItemMeta()) {
|
||||
assert e.getItem().getItemMeta() != null;
|
||||
String s = e.getItem().getItemMeta().getPersistentDataContainer().getOrDefault(Desu.getKey(0), PersistentDataType.STRING, "null");
|
||||
CustomItem ci = ItemRegistry.getItem(s);
|
||||
if (ci != null)
|
||||
ci.getUseEvents().forEach(ev -> ev.accept(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void onItemPlace(BlockPlaceEvent e) {
|
||||
if (e.getItemInHand().hasItemMeta()) {
|
||||
assert e.getItemInHand().getItemMeta() != null;
|
||||
String s = e.getItemInHand().getItemMeta().getPersistentDataContainer().getOrDefault(Desu.getKey(0), PersistentDataType.STRING, "null");
|
||||
CustomItem ci = ItemRegistry.getItem(s);
|
||||
if (ci != null) {
|
||||
ItemBlockPlacedEvent ev = new ItemBlockPlacedEvent(e);
|
||||
ci.getPlaceEvents().forEach(event -> event.accept(ev));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package me.yuri.yuriapi.api.item;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ItemRegistry {
|
||||
|
||||
private static final Map<JavaPlugin, ItemRegistry> plugins = new HashMap<>();
|
||||
private final List<CustomItem> items = new ArrayList<>();
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
private ItemRegistry(JavaPlugin pl) {
|
||||
plugin = pl;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ItemRegistry getFor(@Nonnull JavaPlugin pl) {
|
||||
ItemRegistry ir = plugins.getOrDefault(pl, null);
|
||||
if (ir == null) {
|
||||
ir = new ItemRegistry(pl);
|
||||
plugins.put(pl, ir);
|
||||
}
|
||||
return ir;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<CustomItem> getAllItems() {
|
||||
List<CustomItem> cit = new ArrayList<>();
|
||||
plugins.values().forEach(v -> cit.addAll(v.getItems()));
|
||||
return cit;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CustomItem getItem(JavaPlugin pl, String name) {
|
||||
for (CustomItem c : getFor(pl).items) {
|
||||
if (c.getKey().getKey().equalsIgnoreCase(name))
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isCustom(ItemStack i) {
|
||||
if (i == null) return false;
|
||||
return getAllItems().stream().anyMatch(f -> f.getItemstack().isSimilar(i));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CustomItem getItem(String name) {
|
||||
String[] s = name.split(":");
|
||||
if (s.length != 2) return null;
|
||||
for (ItemRegistry r : plugins.values()) {
|
||||
if (r.plugin.getName().equalsIgnoreCase(s[0])) {
|
||||
for (CustomItem c : r.items) {
|
||||
if (c.getKey().getKey().equalsIgnoreCase(s[1])) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public JavaPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public void registerItem(@Nonnull CustomItem item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<CustomItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package me.yuri.yuriapi.api.nms;
|
||||
|
||||
public enum CBClasses {
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package me.yuri.yuriapi.api.nms;
|
||||
|
||||
public enum NMSClasses {
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package me.yuri.yuriapi.api.nms;
|
||||
|
||||
import me.yuri.yuriapi.api.reflectionless.Reflectionless;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class NMSUtil {
|
||||
private static final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
|
||||
private static final String pkg_nms = "net.minecraft.server." + version;
|
||||
private static final String pkg_cb = "org.bukkit.craftbukkit." + version;
|
||||
|
||||
private NMSUtil() {
|
||||
}
|
||||
|
||||
public static Object getPlayerHandle(Player p) {
|
||||
try {
|
||||
return Reflectionless.get(p.getClass().getMethod("getHandle")).call(p);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("???");
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getNmsClass(String name) {
|
||||
try {
|
||||
return Class.forName(pkg_nms + '.' + name);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
throw new IllegalArgumentException("Invalid class.");
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getCbClass(String path) {
|
||||
try {
|
||||
System.out.println(pkg_cb + '.' + path);
|
||||
return Class.forName(pkg_cb + '.' + path);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
throw new IllegalArgumentException("Invalid class.");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCbPath() {
|
||||
return pkg_cb;
|
||||
}
|
||||
|
||||
public static String getNmsPath() {
|
||||
return pkg_nms;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package me.yuri.yuriapi.api.packet;
|
||||
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import net.minecraft.server.v1_16_R3.PacketPlayInFlying;
|
||||
|
||||
public class PacketHandler extends ChannelDuplexHandler {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
super.channelRead(ctx, msg);
|
||||
if (msg instanceof PacketPlayInFlying.PacketPlayInPosition || msg instanceof PacketPlayInFlying.PacketPlayInLook || msg instanceof PacketPlayInFlying.PacketPlayInPositionLook)
|
||||
return;
|
||||
//Bukkit.getConsoleSender().sendMessage("READ: \n" + msg.getClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
super.write(ctx, msg, promise);
|
||||
if (msg instanceof PacketPlayInFlying.PacketPlayInPosition || msg instanceof PacketPlayInFlying.PacketPlayInLook || msg instanceof PacketPlayInFlying.PacketPlayInPositionLook)
|
||||
return;
|
||||
//Bukkit.getConsoleSender().sendMessage("WRITE: \n"+msg.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package me.yuri.yuriapi.api.packet;
|
||||
|
||||
import me.yuri.yuriapi.api.nms.NMSUtil;
|
||||
import me.yuri.yuriapi.api.reflectionless.Reflectionless;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PacketManager {
|
||||
|
||||
|
||||
public static void addPlayer(Player p) {
|
||||
return;
|
||||
/*
|
||||
try {
|
||||
Object cp = NMSUtil.getPlayerHandle(p);
|
||||
Object conn = Reflectionless.get(cp.getClass().getField("b")).get(cp);
|
||||
Object nmg = Reflectionless.get(conn.getClass().getField("a")).get(conn);
|
||||
io.netty.channel.Channel c = (io.netty.channel.Channel) Reflectionless.get(nmg.getClass().getField("k")).get(nmg);
|
||||
c.pipeline().addBefore("packet_handler", p.getName(), new PacketHandler());
|
||||
Bukkit.getConsoleSender().sendMessage("Added packet handler!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package me.yuri.yuriapi.api.permission;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.ServerOperator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Locale;
|
||||
|
||||
public class CustomPermissible extends PermissibleBase {
|
||||
|
||||
private final YPlayer bearer;
|
||||
|
||||
public CustomPermissible(YPlayer pl, @Nullable ServerOperator opable) {
|
||||
super(opable);
|
||||
bearer = pl;
|
||||
recalculatePermissions();
|
||||
pl.getBasePlayer().updateCommands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@Nonnull String inName) {
|
||||
String name = inName.toLowerCase(Locale.ENGLISH);
|
||||
if (isPermissionSet(name)) return true;
|
||||
|
||||
if (isPermissionSet("*") || isPermissionSet("*.*")) return true;
|
||||
|
||||
if (name.contains("."))
|
||||
return isPermissionSet(name.substring(0, name.indexOf(".")) + "*") || isOp();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@Nonnull String name) {
|
||||
return bearer.getPermissionGroups().stream().anyMatch(c -> c.getPermissions().stream().anyMatch(p -> p.equalsIgnoreCase(name)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@Nonnull Permission perm) {
|
||||
return isPermissionSet(perm.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@Nonnull Permission perm) {
|
||||
return hasPermission(perm.getName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
package me.yuri.yuriapi.api.permission;
|
||||
|
||||
import me.yuri.yuriapi.Desu;
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import me.yuri.yuriapi.api.db.DbComparisonType;
|
||||
import me.yuri.yuriapi.api.db.DbQueryResult;
|
||||
import me.yuri.yuriapi.api.db.DbTable;
|
||||
import me.yuri.yuriapi.api.utils.Colored;
|
||||
import me.yuri.yuriapi.utils.DbManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PermissionManager {
|
||||
private static final PermissionManager inst = new PermissionManager();
|
||||
protected static List<YPermissionGroup> permgroups = new ArrayList<>();
|
||||
private static YPermissionGroup defaultPGroup = null;
|
||||
private static boolean init = false;
|
||||
|
||||
private PermissionManager() {
|
||||
}
|
||||
|
||||
public static PermissionManager getInstance() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
public static YPermissionGroup getDefaultGroup() {
|
||||
return defaultPGroup;
|
||||
}
|
||||
|
||||
public static void savePerms(YPlayer p) {
|
||||
if (!p.getPermissionGroups().isEmpty())
|
||||
Objects.requireNonNull(DbManager.h("pg")).createInsertQuery()
|
||||
.setColumn("uuid", p.getBasePlayer().getUniqueId()).setColumn("groups", p.getPermissionGroups()
|
||||
.stream().map(YPermissionGroup::getName).collect(Collectors.joining(";"))).build().execute();
|
||||
}
|
||||
|
||||
public static boolean setOffline(OfflinePlayer p, YPermissionGroup g, boolean set) {
|
||||
DbTable usr = Objects.requireNonNull(DbManager.h("pg"));
|
||||
DbQueryResult q = usr.createSelectQuery().columns("groups").where(w -> w.forColumn("uuid").value(DbComparisonType.EQUALS, p.getUniqueId()).end()).build().execute();
|
||||
String groups = "";
|
||||
if (q.next()) {
|
||||
groups = (String) q.get(0);
|
||||
}
|
||||
q.close();
|
||||
|
||||
if (groups.isEmpty()) {
|
||||
if (set)
|
||||
groups = g.getName();
|
||||
} else {
|
||||
if (set) {
|
||||
List<String> s = Arrays.asList(groups.split(";"));
|
||||
if (s.stream().anyMatch(ss -> ss.equalsIgnoreCase(g.getName())))
|
||||
return false;
|
||||
groups += ";" + g.getName();
|
||||
} else {
|
||||
List<String> s = Arrays.asList(groups.split(";"));
|
||||
s.removeIf(c -> c.equals(g.getName()));
|
||||
groups = String.join(";", s);
|
||||
}
|
||||
}
|
||||
|
||||
if (!groups.isEmpty()) {
|
||||
usr.createInsertQuery().setColumn("uuid", p.getUniqueId()).setColumn("groups", groups).build().execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static YPermissionGroup getByName(@Nonnull String name, boolean ignoreCase) {
|
||||
for (YPermissionGroup g : permgroups) {
|
||||
if (ignoreCase) {
|
||||
if (g.getName().equalsIgnoreCase(name)) return g;
|
||||
} else {
|
||||
if (g.getName().equals(name)) return g;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<YPermissionGroup> getFor(YPlayer p) {
|
||||
DbQueryResult q = Objects.requireNonNull(DbManager.h("pg")).createSelectQuery().columns("groups").where(w -> w.forColumn("uuid").value(DbComparisonType.EQUALS, p.getBasePlayer().getUniqueId()).end()).build().execute();
|
||||
List<YPermissionGroup> gp = new ArrayList<>();
|
||||
if (q.next()) {
|
||||
String[] names = q.getText(1).split(";");
|
||||
Arrays.stream(names).forEach(c -> gp.add(getByName(c, false)));
|
||||
}
|
||||
q.close();
|
||||
return gp;
|
||||
}
|
||||
|
||||
public static List<YPermissionGroup> getGroups() {
|
||||
return permgroups;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (init) return;
|
||||
init = true;
|
||||
|
||||
File f = new File(Desu.getMain().getDataFolder(), "permissions.yml");
|
||||
|
||||
if (!f.exists())
|
||||
Desu.getMain().saveResource("permissions.yml", true);
|
||||
|
||||
YamlConfiguration perms;
|
||||
try {
|
||||
perms = YamlConfiguration.loadConfiguration(f);
|
||||
|
||||
char colorCode = Objects.requireNonNull(perms.getString("colorCode")).charAt(0);
|
||||
ConfigurationSection groups = perms.getConfigurationSection("groups");
|
||||
assert groups != null;
|
||||
|
||||
String defaultGroup = perms.getString("default");
|
||||
|
||||
Bukkit.getConsoleSender().sendMessage(Colored.colorize("&ePermission groups:"));
|
||||
groups.getKeys(false).forEach(g -> {
|
||||
ConfigurationSection group = groups.getConfigurationSection(g);
|
||||
|
||||
assert group != null;
|
||||
|
||||
String prefix = group.getString("prefix");
|
||||
String suffix = group.getString("suffix");
|
||||
|
||||
HashSet<String> permissions = new HashSet<>(group.getStringList("permissions"));
|
||||
|
||||
if (prefix != null) prefix = Colored.colorize(colorCode, prefix);
|
||||
if (suffix != null) suffix = Colored.colorize(colorCode, suffix);
|
||||
|
||||
YPermissionGroup gp = new YPermissionGroup(g, prefix, suffix, permissions);
|
||||
|
||||
permgroups.add(gp);
|
||||
gp.index = permgroups.size() - 1;
|
||||
|
||||
if (gp.getName().equalsIgnoreCase(defaultGroup))
|
||||
defaultPGroup = gp;
|
||||
|
||||
Bukkit.getConsoleSender().sendMessage(Colored.colorize(String.format("&e- &a%s&e -> prefix: &a%s&e, suffix: &a%s&e%s.", g, prefix == null ? "&cnone" : (ChatColor.stripColor(prefix).isEmpty() ? prefix + "color" : prefix), suffix == null ? "&cnone" : (ChatColor.stripColor(suffix).isEmpty() ? suffix + "color" : suffix), gp.getName().equals(defaultGroup) ? " (&adefault group&e)" : "")));
|
||||
});
|
||||
|
||||
ArrayList<YPermissionGroup> aa = new ArrayList<>(permgroups);
|
||||
Collections.reverse(aa);
|
||||
HashSet<String> permss = new HashSet<>();
|
||||
for (YPermissionGroup pg : aa) {
|
||||
pg.getPermissions().addAll(permss);
|
||||
permss.addAll(pg.getPermissions());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Bukkit.getConsoleSender().sendMessage(Desu.cl.colorizeInst("$cInvalid permission group configuration... Permission system will not work!"));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package me.yuri.yuriapi.api.permission;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class YPermissionGroup {
|
||||
|
||||
private final String name;
|
||||
private final Set<String> permissions;
|
||||
protected int index;
|
||||
private String prefix, suffix;
|
||||
|
||||
protected YPermissionGroup(@Nonnull String name, @Nullable String prefix, @Nullable String suffix, @Nullable HashSet<String> permissions) {
|
||||
this.name = name;
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
|
||||
if (permissions == null) permissions = new HashSet<>();
|
||||
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void addPermission(String permission) {
|
||||
permissions.add(permission);
|
||||
}
|
||||
|
||||
public boolean removePermission(String permission) {
|
||||
return permissions.remove(permission);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class Accessor {
|
||||
private static final Map<Field, Function<?, ?>> getterAccess = new HashMap<>();
|
||||
private static final Map<Field, BiConsumer<?, ?>> setterAccess = new HashMap<>();
|
||||
private static final Map<Constructor<?>, Function<?, ?>> constructorAccess = new HashMap<>();
|
||||
private static final Map<Method, Function<?, ?>> methodAccess = new HashMap<>();
|
||||
|
||||
private Accessor() {
|
||||
}
|
||||
|
||||
public static Function<?, ?> getGetter(Field field) {
|
||||
Function<?, ?> function = getterAccess.get(field);
|
||||
if (function == null) {
|
||||
function = UnsafeUtil.allocate((Class<? extends Function<Object, Object>>) UnsafeUtil.defineAnonymous(field.getDeclaringClass(), new FieldAccessor(field, true).toByteArray()));
|
||||
getterAccess.put(field, function);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
public static BiConsumer<?, ?> getSetter(Field field) {
|
||||
BiConsumer<?, ?> biConsumer = setterAccess.get(field);
|
||||
if (biConsumer == null) {
|
||||
biConsumer = UnsafeUtil.allocate((Class<? extends BiConsumer<?, ?>>) UnsafeUtil.defineAnonymous(field.getDeclaringClass(), new FieldAccessor(field, false).toByteArray()));
|
||||
setterAccess.put(field, biConsumer);
|
||||
}
|
||||
return biConsumer;
|
||||
}
|
||||
|
||||
public static Function<?, ?> getConstructor(Constructor<?> constructor) {
|
||||
Function<?, ?> function = constructorAccess.get(constructor);
|
||||
if (function == null) {
|
||||
function = UnsafeUtil.allocate((Class<? extends Function<?, ?>>) UnsafeUtil.defineAnonymous(constructor.getDeclaringClass(), new ConstructorAccessor(constructor).toByteArray()));
|
||||
constructorAccess.put(constructor, function);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
public static Function<?, ?> getMethod(Method method) {
|
||||
Function<?, ?> function = methodAccess.get(method);
|
||||
if (function == null) {
|
||||
function = UnsafeUtil.allocate((Class<? extends Function<?, ?>>) UnsafeUtil.defineAnonymous(method.getDeclaringClass(), new MethodAccessor(method).toByteArray()));
|
||||
methodAccess.put(method, function);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
public class ClassAccessor extends ClassWriter {
|
||||
protected static final String OBJECT_TYPE = Type.getInternalName(Object.class);
|
||||
protected static final String CTOR_NAME = "<init>";
|
||||
|
||||
protected Class<?> declaringClass;
|
||||
protected String declaringClassType;
|
||||
protected String generatedName;
|
||||
|
||||
public ClassAccessor(Class<?> declaringClass) {
|
||||
super(ClassWriter.COMPUTE_MAXS);
|
||||
this.declaringClass = declaringClass;
|
||||
this.declaringClassType = Type.getInternalName(declaringClass);
|
||||
this.generatedName = declaringClassType + "$Access";
|
||||
}
|
||||
|
||||
protected void generateConstructor() {
|
||||
MethodVisitor ctor = visitMethod(Opcodes.ACC_PUBLIC, CTOR_NAME, "()V", null, null);
|
||||
ctor.visitCode();
|
||||
ctor.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_TYPE, CTOR_NAME, "()V", false);
|
||||
ctor.visitInsn(Opcodes.RETURN);
|
||||
ctor.visitMaxs(0, 0);
|
||||
ctor.visitEnd();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
public class ConstructorAccessor extends MemberAccessor {
|
||||
protected static final String OBJECT_ARRAY_DESCRIPTOR = Type.getDescriptor(Object[].class);
|
||||
protected static final String CALLER_TYPE = "(L" + OBJECT_TYPE + ";)L" + OBJECT_TYPE + ";";
|
||||
|
||||
protected Class<?>[] parameters;
|
||||
|
||||
public ConstructorAccessor(Constructor<?> constructor) {
|
||||
super(constructor);
|
||||
parameters = constructor.getParameterTypes();
|
||||
|
||||
visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SYNTHETIC, generatedName, null, OBJECT_TYPE, new String[]{FUNCTION_TYPE});
|
||||
generateCall();
|
||||
visitEnd();
|
||||
}
|
||||
|
||||
protected void generateCall() {
|
||||
MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, FUNCTION_METHOD_NAME, CALLER_TYPE, null, null);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, OBJECT_ARRAY_DESCRIPTOR);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||
mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(declaringClass));
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
castParams(mv);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, declaringClassType, CTOR_NAME, Types.getMethodDescriptor(Void.TYPE, parameters), false);
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
protected void castParams(MethodVisitor mv) {
|
||||
int var = 0;
|
||||
for (Class<?> parameter : parameters) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitLdcInsn(var++);
|
||||
mv.visitInsn(Opcodes.AALOAD);
|
||||
if (parameter.isPrimitive()) {
|
||||
Types.Primitive primitive = Types.getPrimitive(parameter);
|
||||
assert primitive != null;
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(primitive.getWrapper()));
|
||||
primitive.toPrimitive(mv);
|
||||
} else {
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
public interface DynamicCaller {
|
||||
Object call(Object... p);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
public interface FieldAccess {
|
||||
Object get(Object obj);
|
||||
|
||||
void set(Object obj, Object value);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class FieldAccessor extends MemberAccessor {
|
||||
|
||||
protected static final String BICONSUMER_TYPE = Type.getInternalName(BiConsumer.class);
|
||||
protected static final String BICONSUMER_METHOD_NAME = "accept";
|
||||
|
||||
protected static final String GETTER_TYPE = "(L" + OBJECT_TYPE + ";)L" + OBJECT_TYPE + ";";
|
||||
protected static final String SETTER_TYPE = "(L" + OBJECT_TYPE + ";L" + OBJECT_TYPE + ";)V";
|
||||
|
||||
protected Class<?> type;
|
||||
|
||||
public FieldAccessor(Field field, boolean getter) {
|
||||
super(field);
|
||||
type = field.getType();
|
||||
|
||||
visit(UnsafeUtil.V_C, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SYNTHETIC, generatedName, null, OBJECT_TYPE, new String[]{getter ? FUNCTION_TYPE : BICONSUMER_TYPE});
|
||||
if (getter) generateGetter();
|
||||
else generateSetter();
|
||||
visitEnd();
|
||||
}
|
||||
|
||||
protected void generateGetter() {
|
||||
MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, FUNCTION_METHOD_NAME, GETTER_TYPE, null, null);
|
||||
if (!isStatic) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, declaringClassType);
|
||||
}
|
||||
mv.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, declaringClassType, name, Type.getDescriptor(type));
|
||||
if (type.isPrimitive()) Objects.requireNonNull(Types.getPrimitive(type)).toWrapper(mv);
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
protected void generateSetter() {
|
||||
MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, BICONSUMER_METHOD_NAME, SETTER_TYPE, null, null);
|
||||
if (!isStatic) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, declaringClassType);
|
||||
}
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 2);
|
||||
if (type.isPrimitive()) {
|
||||
Types.Primitive primitive = Types.getPrimitive(type);
|
||||
assert primitive != null;
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(primitive.getWrapper()));
|
||||
primitive.toPrimitive(mv);
|
||||
} else {
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(type));
|
||||
}
|
||||
mv.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, declaringClassType, name, Type.getDescriptor(type));
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FunctionalCaller implements DynamicCaller {
|
||||
private final Function<Object, Object> function;
|
||||
|
||||
public FunctionalCaller(Function<Object, Object> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(Object... parameters) {
|
||||
return function.apply(parameters);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FunctionalFieldAccess implements FieldAccess {
|
||||
private final Function<Object, Object> getter;
|
||||
private final BiConsumer<Object, Object> setter;
|
||||
|
||||
public FunctionalFieldAccess(Function<Object, Object> getter, BiConsumer<Object, Object> setter) {
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object obj) {
|
||||
return getter.apply(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object obj, Object value) {
|
||||
setter.accept(obj, value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MemberAccessor extends ClassAccessor {
|
||||
|
||||
protected static final String FUNCTION_TYPE = Type.getInternalName(Function.class);
|
||||
protected static final String FUNCTION_METHOD_NAME = "apply";
|
||||
|
||||
protected String name;
|
||||
protected boolean isStatic;
|
||||
|
||||
public MemberAccessor(Member member) {
|
||||
super(member.getDeclaringClass());
|
||||
name = member.getName();
|
||||
isStatic = Modifier.isStatic(member.getModifiers());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MethodAccessor extends MemberAccessor {
|
||||
protected static final String OBJECT_ARRAY_DESCRIPTOR = Type.getDescriptor(Object[].class);
|
||||
protected static final String CALLER_TYPE = "(L" + OBJECT_TYPE + ";)L" + OBJECT_TYPE + ";";
|
||||
|
||||
protected Class<?> returnType;
|
||||
protected Class<?>[] parameters;
|
||||
|
||||
public MethodAccessor(Method method) {
|
||||
super(method);
|
||||
returnType = method.getReturnType();
|
||||
parameters = method.getParameterTypes();
|
||||
|
||||
visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SYNTHETIC, generatedName, null, OBJECT_TYPE, new String[]{FUNCTION_TYPE});
|
||||
generateCall();
|
||||
visitEnd();
|
||||
}
|
||||
|
||||
protected void generateCall() {
|
||||
MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, FUNCTION_METHOD_NAME, CALLER_TYPE, null, null);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, OBJECT_ARRAY_DESCRIPTOR);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||
if (!isStatic) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitInsn(Opcodes.AALOAD);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, declaringClassType);
|
||||
}
|
||||
castParams(mv);
|
||||
mv.visitMethodInsn(declaringClass.isInterface() ? Opcodes.INVOKEINTERFACE : isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, declaringClassType, name, Types.getMethodDescriptor(returnType, parameters), declaringClass.isInterface());
|
||||
if (returnType == Void.TYPE) {
|
||||
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
} else if (returnType.isPrimitive()) {
|
||||
Objects.requireNonNull(Types.getPrimitive(returnType)).toWrapper(mv);
|
||||
}
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
protected void castParams(MethodVisitor mv) {
|
||||
int var = isStatic ? 0 : 1;
|
||||
for (Class<?> parameter : parameters) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitLdcInsn(var++);
|
||||
mv.visitInsn(Opcodes.AALOAD);
|
||||
if (parameter.isPrimitive()) {
|
||||
Types.Primitive primitive = Types.getPrimitive(parameter);
|
||||
assert primitive != null;
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(primitive.getWrapper()));
|
||||
primitive.toPrimitive(mv);
|
||||
} else {
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class Reflectionless {
|
||||
private Reflectionless() {
|
||||
}
|
||||
|
||||
public static FieldAccess get(Field field) {
|
||||
return new FunctionalFieldAccess((Function<Object, Object>) Accessor.getGetter(field), (BiConsumer<Object, Object>) Accessor.getSetter(field));
|
||||
}
|
||||
|
||||
public static DynamicCaller get(Constructor<?> constructor) {
|
||||
return new FunctionalCaller((Function<Object, Object>) Accessor.getConstructor(constructor));
|
||||
}
|
||||
|
||||
public static DynamicCaller get(Method method) {
|
||||
return new FunctionalCaller((Function<Object, Object>) Accessor.getMethod(method));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
public class Types {
|
||||
|
||||
public static String getMethodDescriptor(Class<?> returnType, Class<?>[] parameters) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("(");
|
||||
for (Class<?> parameter : parameters) {
|
||||
builder.append(Type.getDescriptor(parameter));
|
||||
}
|
||||
builder.append(")");
|
||||
builder.append(Type.getDescriptor(returnType));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static Primitive getPrimitive(Class<?> clz) {
|
||||
for (Primitive value : Primitive.values()) {
|
||||
if (value.getPrimitive() == clz || value.getWrapper() == clz) return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum Primitive {
|
||||
|
||||
VOID(Void.class, "V"),
|
||||
BOOLEAN(Boolean.class, "Z"),
|
||||
CHARACTER(Character.class, "C"),
|
||||
BYTE(Byte.class, "B"),
|
||||
SHORT(Short.class, "S"),
|
||||
INTEGER(Integer.class, "I"),
|
||||
FLOAT(Float.class, "F"),
|
||||
LONG(Long.class, "J"),
|
||||
DOUBLE(Double.class, "D");
|
||||
|
||||
private final Class<?> wrapper;
|
||||
private final String identifier;
|
||||
private Class<?> primitive;
|
||||
|
||||
Primitive(Class<?> wrapper, String identifier) {
|
||||
this.wrapper = wrapper;
|
||||
try {
|
||||
this.primitive = (Class<?>) wrapper.getDeclaredField("TYPE").get(null);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public Class<?> getWrapper() {
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
public Class<?> getPrimitive() {
|
||||
return primitive;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void toPrimitive(MethodVisitor mv) {
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(getWrapper()), getPrimitive().getName() + "Value", "()" + getIdentifier(), false);
|
||||
}
|
||||
|
||||
public void toWrapper(MethodVisitor mv) {
|
||||
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(getWrapper()), "valueOf", "(" + getIdentifier() + ")" + Type.getDescriptor(getWrapper()), false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package me.yuri.yuriapi.api.reflectionless;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class UnsafeUtil {
|
||||
private static final Class<?> UNSAFE_CLASS;
|
||||
private static final Object UNSAFE;
|
||||
|
||||
private static final Method DEFINE_ANONYMOUS;
|
||||
private static final Method ALLOCATE;
|
||||
private static final Method FIELD_OFFSET;
|
||||
private static final Method PUT_FIELD;
|
||||
private static final Method GET_FIELD;
|
||||
|
||||
public static int V_C = 52; //1.8
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE_CLASS = Class.forName("sun.misc.Unsafe");
|
||||
|
||||
Field unsafeField = UNSAFE_CLASS.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
UNSAFE = unsafeField.get(null);
|
||||
|
||||
DEFINE_ANONYMOUS = UNSAFE_CLASS.getDeclaredMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class);
|
||||
ALLOCATE = UNSAFE_CLASS.getDeclaredMethod("allocateInstance", Class.class);
|
||||
FIELD_OFFSET = UNSAFE_CLASS.getDeclaredMethod("objectFieldOffset", Field.class);
|
||||
PUT_FIELD = UNSAFE_CLASS.getDeclaredMethod("putObject", Object.class, long.class, Object.class);
|
||||
GET_FIELD = UNSAFE_CLASS.getDeclaredMethod("getObject", Object.class, long.class);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> defineAnonymous(Class<?> clz, byte[] bytes) {
|
||||
try {
|
||||
return (Class<?>) DEFINE_ANONYMOUS.invoke(UNSAFE, clz, bytes, null);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void putField(Field field, Object object, Object value) {
|
||||
try {
|
||||
long offset = (long) FIELD_OFFSET.invoke(UNSAFE, field);
|
||||
PUT_FIELD.invoke(UNSAFE, object, offset, value);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getField(Field field, Object object, Object value) {
|
||||
try {
|
||||
long offset = (long) FIELD_OFFSET.invoke(UNSAFE, field);
|
||||
return GET_FIELD.invoke(UNSAFE, object, offset);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T allocate(Class<T> clz) {
|
||||
try {
|
||||
return (T) ALLOCATE.invoke(UNSAFE, clz);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
199
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/utils/Colored.java
Executable file
199
YuriPlugins/YuriAPI/src/main/java/me/yuri/yuriapi/api/utils/Colored.java
Executable file
|
@ -0,0 +1,199 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Color;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Colored {
|
||||
|
||||
public static final String BLACK = ChatColor.BLACK.toString();
|
||||
public static final String DARK_BLUE = ChatColor.DARK_BLUE.toString();
|
||||
public static final String DARK_GREEN = ChatColor.DARK_GREEN.toString();
|
||||
public static final String DARK_AQUA = ChatColor.DARK_AQUA.toString();
|
||||
public static final String DARK_RED = ChatColor.DARK_RED.toString();
|
||||
public static final String DARK_PURPLE = ChatColor.DARK_PURPLE.toString();
|
||||
public static final String GOLD = ChatColor.GOLD.toString();
|
||||
public static final String GRAY = ChatColor.GRAY.toString();
|
||||
public static final String DARK_GRAY = ChatColor.DARK_GRAY.toString();
|
||||
public static final String BLUE = ChatColor.BLUE.toString();
|
||||
public static final String GREEN = ChatColor.GREEN.toString();
|
||||
public static final String AQUA = ChatColor.AQUA.toString();
|
||||
public static final String RED = ChatColor.RED.toString();
|
||||
public static final String LIGHT_PURPLE = ChatColor.LIGHT_PURPLE.toString();
|
||||
public static final String YELLOW = ChatColor.YELLOW.toString();
|
||||
public static final String WHITE = ChatColor.WHITE.toString();
|
||||
public static final String MAGIC = ChatColor.MAGIC.toString();
|
||||
public static final String STRIKETHROUGH = ChatColor.STRIKETHROUGH.toString();
|
||||
public static final String UNDERLINE = ChatColor.UNDERLINE.toString();
|
||||
public static final String ITALIC = ChatColor.ITALIC.toString();
|
||||
public static final String BOLD = ChatColor.BOLD.toString();
|
||||
public static final String RESET = ChatColor.RESET.toString();
|
||||
private char symbol;
|
||||
|
||||
/**
|
||||
* Creates a new Colored instance
|
||||
*
|
||||
* @param symbol the color code symbol that will be substituted using colorizeInst()
|
||||
*/
|
||||
public Colored(char symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color codes to the given text (!!!substitutes '&' with the color codes!!!)
|
||||
*
|
||||
* @param text the text to apply color codes to
|
||||
* @return colorized text
|
||||
*/
|
||||
public static String colorize(String text) {
|
||||
return colorize('&', text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color codes to the given text (!!!substitutes '&' with the color codes!!!)
|
||||
*
|
||||
* @param text the text to apply color codes to
|
||||
* @return colorized text
|
||||
*/
|
||||
public static String[] colorize(String... text) {
|
||||
return colorize('&', text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color codes to the given text
|
||||
*
|
||||
* @param text the text to apply color codes to
|
||||
* @param symbol the color code symbol that will be substituted
|
||||
* @return colorized text
|
||||
*/
|
||||
public static String colorize(char symbol, String text) {
|
||||
return text == null ? null : ChatColor.translateAlternateColorCodes(symbol, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color codes to the given text
|
||||
*
|
||||
* @param text the text to apply color codes to
|
||||
* @param symboll the color code symbol that will be substituted
|
||||
* @return colorized text
|
||||
*/
|
||||
public static String[] colorize(char symboll, String... text) {
|
||||
return Arrays.stream(text).map(t -> t = t == null ? null : ChatColor.translateAlternateColorCodes(symboll, t)).collect(Collectors.toList()).toArray(new String[]{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns color from a String (!!!Will return Color.BLACK if the parameter 'name' is invalid!!!)
|
||||
*
|
||||
* @param name the string name of a color
|
||||
* @return color as a Color class
|
||||
*/
|
||||
public static Color getColorFromName(String name) {
|
||||
try {
|
||||
Field f = Color.class.getField(name.toUpperCase());
|
||||
f.setAccessible(true);
|
||||
Color cc = (Color) f.get(ChatColor.class);
|
||||
f.setAccessible(false);
|
||||
return cc;
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {
|
||||
return Color.BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ChatColor from a String (!!!Will return ChatColor.BLACK if the parameter 'name' is invalid!!!)
|
||||
*
|
||||
* @param name the string name of a color
|
||||
* @return color as a ChatColor class
|
||||
*/
|
||||
public static ChatColor getChatColorFromName(String name) {
|
||||
try {
|
||||
Field f = ChatColor.class.getField(name.toUpperCase());
|
||||
f.setAccessible(true);
|
||||
ChatColor cc = (ChatColor) f.get(ChatColor.class);
|
||||
f.setAccessible(false);
|
||||
return cc;
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {
|
||||
return ChatColor.BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String name of a Color
|
||||
*
|
||||
* @param color color
|
||||
* @return name of a color as String
|
||||
*/
|
||||
public static String getFromColor(Color color) {
|
||||
if (color.equals(Color.BLACK)) {
|
||||
return "BLACK";
|
||||
} else if (color.equals(Color.BLUE)) {
|
||||
return "BLUE";
|
||||
} else if (color.equals(Color.RED)) {
|
||||
return "RED";
|
||||
} else if (color.equals(Color.GRAY)) {
|
||||
return "GRAY";
|
||||
} else if (color.equals(Color.NAVY)) {
|
||||
return "NAVY";
|
||||
} else if (color.equals(Color.MAROON)) {
|
||||
return "MAROON";
|
||||
} else if (color.equals(Color.YELLOW)) {
|
||||
return "YELLOW";
|
||||
} else if (color.equals(Color.GREEN)) {
|
||||
return "GREEN";
|
||||
} else if (color.equals(Color.ORANGE)) {
|
||||
return "ORANGE";
|
||||
}
|
||||
return "BLACK";
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any color codes from given text
|
||||
*
|
||||
* @param text the text
|
||||
* @return text without color codes
|
||||
*/
|
||||
public static String strip(String text) {
|
||||
return ChatColor.stripColor(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the the color code symbol that will be substituted using colorizeInst()
|
||||
*
|
||||
* @return color symbol
|
||||
*/
|
||||
public char getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the the color code symbol that will be substituted using colorizeInst()
|
||||
*
|
||||
* @param symbol the color code symbol that will be substituted using colorizeInst()
|
||||
*/
|
||||
public void setSymbol(char symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color codes to the given text using symbol stored in the instance
|
||||
*
|
||||
* @param text the text to apply color codes to
|
||||
* @return colorized text
|
||||
*/
|
||||
public String colorizeInst(String text) {
|
||||
return colorize(symbol, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color codes to the given text using symbol stored in the instance
|
||||
*
|
||||
* @param text the text to apply color codes to
|
||||
* @return colorized text
|
||||
*/
|
||||
public String[] colorizeInst(String... text) {
|
||||
return colorize(symbol, text);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CustomScoreboard {
|
||||
|
||||
private final Scoreboard sb;
|
||||
private final Objective ob;
|
||||
private final Map<String, Score> scores = new HashMap<>();
|
||||
private String teamName;
|
||||
|
||||
public CustomScoreboard(DisplaySlot ds, String head) {
|
||||
|
||||
sb = Objects.requireNonNull(Bukkit.getScoreboardManager()).getNewScoreboard();
|
||||
ob = sb.registerNewObjective("yeet", "dummy", head);
|
||||
ob.setDisplayName(head);
|
||||
ob.setDisplaySlot(ds);
|
||||
|
||||
}
|
||||
|
||||
public void addScore(String id, String str) {
|
||||
Score sc = ob.getScore(str);
|
||||
scores.put(id, sc);
|
||||
sc.setScore(0);
|
||||
int i = scores.size();
|
||||
for (Score ss : scores.values().stream().sorted((o1, o2) -> {
|
||||
int a, b;
|
||||
try {
|
||||
a = o1.getScore();
|
||||
} catch (Exception ignored) {
|
||||
a = 0;
|
||||
}
|
||||
try {
|
||||
b = o2.getScore();
|
||||
} catch (Exception ignored) {
|
||||
b = 0;
|
||||
}
|
||||
return a - b;
|
||||
}).collect(Collectors.toList())) {
|
||||
ss.setScore(i);
|
||||
i--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void removeScore(String id) {
|
||||
Score sc = scores.getOrDefault(id, null);
|
||||
if (sc == null) return;
|
||||
Objects.requireNonNull(sc.getScoreboard()).resetScores(sc.getEntry());
|
||||
scores.remove(id);
|
||||
int i = scores.size();
|
||||
for (Score ss : scores.values().stream().sorted((o1, o2) -> {
|
||||
int a, b;
|
||||
try {
|
||||
a = o1.getScore();
|
||||
} catch (Exception ignored) {
|
||||
a = 0;
|
||||
}
|
||||
try {
|
||||
b = o2.getScore();
|
||||
} catch (Exception ignored) {
|
||||
b = 0;
|
||||
}
|
||||
return a - b;
|
||||
}).collect(Collectors.toList())) {
|
||||
ss.setScore(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
public void addToPlayer(Player p) {
|
||||
p.setScoreboard(sb);
|
||||
}
|
||||
|
||||
public void updateScore(String id, String score) {
|
||||
Score sc = scores.getOrDefault(id, null);
|
||||
if (sc == null) return;
|
||||
Objects.requireNonNull(sc.getScoreboard()).resetScores(sc.getEntry());
|
||||
sc = ob.getScore(score);
|
||||
scores.put(id, sc);
|
||||
sc.setScore(0);
|
||||
int i = scores.size();
|
||||
for (Score ss : scores.values().stream().sorted((o1, o2) -> {
|
||||
int a, b;
|
||||
try {
|
||||
a = o1.getScore();
|
||||
} catch (Exception ignored) {
|
||||
a = 0;
|
||||
}
|
||||
try {
|
||||
b = o2.getScore();
|
||||
} catch (Exception ignored) {
|
||||
b = 0;
|
||||
}
|
||||
return a - b;
|
||||
}).collect(Collectors.toList())) {
|
||||
ss.setScore(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ItemUtils {
|
||||
private ItemUtils() {
|
||||
}
|
||||
|
||||
public static boolean removeItem(Inventory inv, Material m, int count) {
|
||||
if (!inv.containsAtLeast(new ItemStack(m), count)) return false;
|
||||
for (ItemStack it : inv.getContents()) {
|
||||
if (it != null) {
|
||||
if (it.getType() == m) {
|
||||
int preAmount = it.getAmount();
|
||||
int newAmount = Math.max(0, preAmount - count);
|
||||
count = Math.max(0, count - preAmount);
|
||||
it.setAmount(newAmount);
|
||||
if (count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
public class Message {
|
||||
|
||||
private final ChatMessageType type;
|
||||
private final BaseComponent[] comp;
|
||||
|
||||
public Message(ChatMessageType type, BaseComponent... comp) {
|
||||
this.type = type;
|
||||
this.comp = comp;
|
||||
}
|
||||
|
||||
public ChatMessageType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public BaseComponent[] getComponents() {
|
||||
return comp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageBuilder implements Cloneable {
|
||||
|
||||
private final List<BaseComponent> buffer = new ArrayList<>();
|
||||
private final ChatMessageType type;
|
||||
private BaseComponent last = new TextComponent();
|
||||
private boolean dirty = false;
|
||||
private StringBuffer textbuff = new StringBuffer();
|
||||
|
||||
public MessageBuilder(ChatMessageType t) {
|
||||
type = t;
|
||||
}
|
||||
|
||||
public MessageBuilder() {
|
||||
this(ChatMessageType.CHAT);
|
||||
}
|
||||
|
||||
public MessageBuilder appendText(char colorCode, String text) {
|
||||
textbuff.append(Colored.colorize(colorCode, text));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder appendText(String text) {
|
||||
return appendText('&', text);
|
||||
}
|
||||
|
||||
public MessageBuilder pushText() {
|
||||
last.addExtra(textbuff.toString());
|
||||
textbuff = new StringBuffer();
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder appendFromBuffer() {
|
||||
last.addExtra(textbuff.toString());
|
||||
textbuff = new StringBuffer();
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder append(char colorCode, String text) {
|
||||
last.addExtra(Colored.colorize(colorCode, text));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder append(String text) {
|
||||
dirty = true;
|
||||
return append('&', text);
|
||||
}
|
||||
|
||||
public MessageBuilder replaceLastInBuffer(int count, char colorCode, String replacement) {
|
||||
textbuff.delete(textbuff.length() - (count + 1), textbuff.length() - 1);
|
||||
textbuff.append(Colored.colorize(colorCode, replacement));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder replaceLastInBuffer(int count, String replacement) {
|
||||
return replaceLastInBuffer(count, '&', replacement);
|
||||
}
|
||||
|
||||
public MessageBuilder hoverText(char colorCode, String hoverText) {
|
||||
last.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Colored.colorize(colorCode, hoverText))));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder hoverText(String hoverText) {
|
||||
return hoverText('&', hoverText);
|
||||
}
|
||||
|
||||
public MessageBuilder clickRunCommand(String cmd) {
|
||||
last.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, cmd));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder clickSuggestCommand(String cmd) {
|
||||
last.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, cmd));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder clickOpenURL(String url) {
|
||||
last.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder push() {
|
||||
buffer.add(last);
|
||||
last = new TextComponent();
|
||||
dirty = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<BaseComponent> getComponents() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public MessageBuilder setComponent(int index, BaseComponent comp) {
|
||||
buffer.set(index, comp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder insertComponent(int index, BaseComponent comp) {
|
||||
buffer.add(index, comp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Message build() {
|
||||
if (dirty)
|
||||
buffer.add(last);
|
||||
return new Message(type, buffer.toArray(new BaseComponent[0]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public enum PlaceholderFormatter {
|
||||
DISPLAY("<DISPLAYNAME>"), NAME("<NAME>"), PREFIXES("<PREFIXES>"), SUFFIX("<SUFFIX>"), GROUP("<GROUP>"), MESSAGE("<MESSAGE>"), HEALTH("<HEALTH>");
|
||||
|
||||
private final String placeholder;
|
||||
|
||||
PlaceholderFormatter(String s) {
|
||||
this.placeholder = s;
|
||||
}
|
||||
|
||||
public static String format(String format, AsyncPlayerChatEvent e) {
|
||||
YPlayer yp = YPlayer.get(e.getPlayer());
|
||||
return Colored.colorize(format(format, yp).replace(MESSAGE.placeholder, e.getMessage()).trim());
|
||||
}
|
||||
|
||||
public static String format(String format, YPlayer p) {
|
||||
Player pl = p.getBasePlayer();
|
||||
return Colored.colorize(format.replace(DISPLAY.placeholder, pl.getDisplayName()).replace(NAME.placeholder, pl.getName())
|
||||
.replace(PREFIXES.placeholder, (p.getChatPrefixes().isEmpty() ? "" : String.join(" ", p.getChatPrefixes())))
|
||||
.replace(HEALTH.placeholder, String.valueOf(pl.getHealth())).replace(GROUP.placeholder, p.getHighestGroup() == null ? "" : p.getHighestGroup().getPrefix()).replace(SUFFIX.placeholder, p.getHighestGroup() == null ? "" : p.getHighestGroup().getSuffix())).trim();
|
||||
}
|
||||
|
||||
public String getPlaceholder() {
|
||||
return placeholder;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public enum PlaceholderUtils {
|
||||
|
||||
PLAYERNAME("{PLAYERNAME}"), PLAYERDISPLAYNAME("{PLAYERDISPLAYNAME}"), PLAYERCUSTOMNAME("{PLAYERCUSTOMNAME}"),
|
||||
PLAYERPLAYERLISTNAME("{PLAYERPLAYERLISTNAME}");
|
||||
|
||||
private final String i;
|
||||
|
||||
PlaceholderUtils(String i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitutes a placeholder with player's name counterpart
|
||||
*
|
||||
* @param placeholder the placeholder
|
||||
* @param player the player whose name will be applied
|
||||
* @return substituted placeholder
|
||||
*/
|
||||
public static String substitutePlaceholder(PlaceholderUtils placeholder, Player player) {
|
||||
switch (placeholder) {
|
||||
case PLAYERNAME:
|
||||
return player.getName();
|
||||
case PLAYERDISPLAYNAME:
|
||||
return player.getDisplayName();
|
||||
case PLAYERCUSTOMNAME:
|
||||
return player.getCustomName();
|
||||
case PLAYERPLAYERLISTNAME:
|
||||
return player.getPlayerListName();
|
||||
}
|
||||
return player.getDisplayName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitutes all placeholders with player's name counterparts
|
||||
* See {@link PlaceholderUtils#substitutePlaceholder(PlaceholderUtils, Player)}
|
||||
*
|
||||
* @param message the message with placeholders
|
||||
* @param player the player whose name will be applied
|
||||
* @return substituted text
|
||||
*/
|
||||
public static String processPlayerPlaceholders(String message, Player player) {
|
||||
for (PlaceholderUtils t : PlaceholderUtils.values()) {
|
||||
message = message.replaceAll(Pattern.quote(t.i), substitutePlaceholder(t, player));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a placeholder as a string
|
||||
*
|
||||
* @return placeholder as string
|
||||
*/
|
||||
public String getPlaceholder() {
|
||||
return i;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
|
||||
public interface PlayerListener {
|
||||
void onLeave(YPlayer p);
|
||||
|
||||
void onJoin(YPlayer p);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SyncedPlayerMap<V> extends HashMap<YPlayer, V> implements PlayerListener {
|
||||
|
||||
public SyncedPlayerMap(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor);
|
||||
YPlayer.sync(this);
|
||||
}
|
||||
|
||||
public SyncedPlayerMap(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
YPlayer.sync(this);
|
||||
}
|
||||
|
||||
public SyncedPlayerMap() {
|
||||
super();
|
||||
YPlayer.sync(this);
|
||||
}
|
||||
|
||||
public SyncedPlayerMap(Map<? extends YPlayer, ? extends V> m) {
|
||||
super(m);
|
||||
YPlayer.sync(this);
|
||||
}
|
||||
|
||||
public V get(Player p) {
|
||||
return get(YPlayer.get(p));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeave(YPlayer p) {
|
||||
this.remove(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(YPlayer p) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import me.yuri.yuriapi.api.YPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class SyncedPlayerSet extends HashSet<YPlayer> implements PlayerListener {
|
||||
|
||||
private final boolean syncJoin;
|
||||
|
||||
public SyncedPlayerSet(int initialCapacity) {
|
||||
this(initialCapacity, false);
|
||||
}
|
||||
|
||||
public SyncedPlayerSet() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public SyncedPlayerSet(Collection<? extends YPlayer> c) {
|
||||
this(c, false);
|
||||
}
|
||||
|
||||
public SyncedPlayerSet(int initialCapacity, boolean syncJoin) {
|
||||
super(initialCapacity);
|
||||
YPlayer.sync(this);
|
||||
this.syncJoin = syncJoin;
|
||||
}
|
||||
|
||||
public SyncedPlayerSet(boolean syncJoin) {
|
||||
super();
|
||||
YPlayer.sync(this);
|
||||
this.syncJoin = syncJoin;
|
||||
}
|
||||
|
||||
public SyncedPlayerSet(Collection<? extends YPlayer> c, boolean addOnJoin) {
|
||||
super(c);
|
||||
YPlayer.sync(this);
|
||||
this.syncJoin = addOnJoin;
|
||||
}
|
||||
|
||||
public boolean contains(Player p) {
|
||||
return this.contains(YPlayer.get(p));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeave(YPlayer p) {
|
||||
this.remove(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJoin(YPlayer p) {
|
||||
if (syncJoin)
|
||||
this.add(p);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package me.yuri.yuriapi.api.utils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDUtils {
|
||||
|
||||
private UUIDUtils() {
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(UUID uuid) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
bb.putLong(uuid.getMostSignificantBits());
|
||||
bb.putLong(uuid.getLeastSignificantBits());
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
public static UUID toUUID(byte[] b) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(b);
|
||||
return new UUID(bb.getLong(), bb.getLong());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package me.yuri.yuriapi.api.utils.configuration;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ConfigVar {
|
||||
/**
|
||||
* The configuration field name (in config.yml)
|
||||
*
|
||||
* @return the configuration field name (in config.yml)
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* (ONLY IF STRING, OTHERWISE LEAVE EMPTY)
|
||||
*
|
||||
* @return the color code char for the field (if is String), leave default to disable
|
||||
*/
|
||||
char color() default ' ';
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package me.yuri.yuriapi.api.utils.configuration;
|
||||
|
||||
public class ConfigVarException extends Exception {
|
||||
|
||||
private final String msg;
|
||||
private final String lmsg;
|
||||
|
||||
public ConfigVarException(Exception e) {
|
||||
msg = e.getMessage();
|
||||
lmsg = e.getLocalizedMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedMessage() {
|
||||
return lmsg;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package me.yuri.yuriapi.api.utils.configuration;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ConfigVarExceptionListener {
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue