This commit is contained in:
femsci 2023-04-21 22:56:48 +02:00
commit 56d69abdc0
Signed by: femsci
GPG key ID: 08F7911F0E650C67
203 changed files with 15543 additions and 0 deletions

4
YuriPlugins/YuriAPI/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
target/
out/
.idea/
errortrace.txt

6
YuriPlugins/YuriAPI/config.yml Executable file
View 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
View 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>

View 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()));
}
}

View 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[]{};
}
}
}

View 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);
}
}

View file

@ -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;
}
}

View 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;
}
}
}

View file

@ -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());
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View 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 "";
}

View file

@ -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;
}
}

View 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;
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,5 @@
package me.yuri.yuriapi.api.command;
public enum CommandResult {
SUCCESS, INVALID_FIELD, TOO_MANY_ARGS, NOT_ENOUGH_ARGS, EXCEPTION
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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() {
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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
}

View file

@ -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
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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("''", "'");
}
}

View file

@ -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;
});
}
}

View file

@ -0,0 +1,7 @@
package me.yuri.yuriapi.api.event;
public interface Cancellable {
boolean isCancelled();
void setCancelled(boolean cancel);
}

View 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;
}
}
}

View file

@ -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 {
}

View 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()));
}
}
}
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,8 @@
package me.yuri.yuriapi.api.inventory;
import me.yuri.yuriapi.api.item.CustomItem;
@FunctionalInterface
public interface CustomItemSupplier {
CustomItem create();
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -0,0 +1,8 @@
package me.yuri.yuriapi.api.inventory;
import org.bukkit.inventory.ItemStack;
@FunctionalInterface
public interface ItemStackSupplier {
ItemStack create();
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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));
}
}
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,4 @@
package me.yuri.yuriapi.api.nms;
public enum CBClasses {
}

View file

@ -0,0 +1,5 @@
package me.yuri.yuriapi.api.nms;
public enum NMSClasses {
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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();
}*/
}
}

View file

@ -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());
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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));
}
}
}
}

View file

@ -0,0 +1,5 @@
package me.yuri.yuriapi.api.reflectionless;
public interface DynamicCaller {
Object call(Object... p);
}

View file

@ -0,0 +1,7 @@
package me.yuri.yuriapi.api.reflectionless;
public interface FieldAccess {
Object get(Object obj);
void set(Object obj, Object value);
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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());
}
}

View file

@ -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));
}
}
}
}

View file

@ -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));
}
}

View file

@ -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);
}
}
}

View file

@ -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();
}
}
}

View 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);
}
}

View file

@ -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--;
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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]));
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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) {
}
}

View file

@ -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);
}
}

View file

@ -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());
}
}

View file

@ -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 ' ';
}

View file

@ -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;
}
}

View file

@ -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