renamed modules dir
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package fr.pandacube.lib.paper;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.WrapperRegistry;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class PandaLibPaper {
|
||||
|
||||
private static Plugin plugin;
|
||||
|
||||
public static void init(Plugin plugin) {
|
||||
PandaLibPaper.plugin = plugin;
|
||||
|
||||
NMSReflect.init();
|
||||
WrapperRegistry.init();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,219 @@
|
||||
package fr.pandacube.lib.paper.gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
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.PlayerDeathEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.paper.util.BukkitEvent;
|
||||
|
||||
/**
|
||||
* Managed a « lobby » type hotbar menu/inventory. It represents items in the player inventory on which you can right click on it.
|
||||
* The player can't move or drop these items.
|
||||
*
|
||||
*/
|
||||
public class GUIHotBar implements Listener {
|
||||
|
||||
private final Map<ItemStack, BiConsumer<PlayerInventory, ItemStack>> itemsAndSetters = new HashMap<>();
|
||||
|
||||
private final Map<ItemStack, Consumer<Player>> itemsAndRunnables = new HashMap<>();
|
||||
|
||||
private final int defltSlot;
|
||||
|
||||
private final List<Player> currentPlayers = new ArrayList<>();
|
||||
|
||||
public GUIHotBar(int defaultSlot) {
|
||||
defltSlot = Math.max(0, Math.min(8, defaultSlot));
|
||||
|
||||
BukkitEvent.register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the item to this hotbar menu. if there is already players hooked to this hotbar, the item will be directly added to
|
||||
* their inventories.
|
||||
* @param i the item stack
|
||||
* @param setter code executed to put the item in the inventory. Additionally check for permission before doing the addition.
|
||||
* @param run the Runnable to run when the user right click on the item in the hotbar.
|
||||
*/
|
||||
public GUIHotBar addItem(ItemStack i, BiConsumer<PlayerInventory, ItemStack> setter, Consumer<Player> run) {
|
||||
itemsAndSetters.put(i, setter);
|
||||
itemsAndRunnables.put(i, run);
|
||||
|
||||
for (Player p : currentPlayers)
|
||||
addItemToPlayer(p, i);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the hotbar elements to this player.
|
||||
*
|
||||
* The players is automatically removed when they quit. You can remove it before by calling {@link #removePlayer(Player)}.
|
||||
*/
|
||||
public void addPlayer(Player p) {
|
||||
if (!currentPlayers.contains(p))
|
||||
currentPlayers.add(p);
|
||||
|
||||
for (ItemStack is : itemsAndSetters.keySet()) {
|
||||
addItemToPlayer(p, is);
|
||||
}
|
||||
|
||||
p.getInventory().setHeldItemSlot(defltSlot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach this player from this hotbar manager and removes the managed items from the players inventory.
|
||||
*/
|
||||
public void removePlayer(Player p) {
|
||||
if (!currentPlayers.contains(p))
|
||||
return;
|
||||
|
||||
for (ItemStack is : itemsAndSetters.keySet()) {
|
||||
removeItemFromPlayer(p, is);
|
||||
}
|
||||
|
||||
currentPlayers.remove(p);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean containsPlayer(Player p) {
|
||||
return currentPlayers.contains(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void removeAllPlayers() {
|
||||
for (Player p : new ArrayList<>(currentPlayers))
|
||||
removePlayer(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void addItemToPlayer(Player p, ItemStack is) {
|
||||
if (!itemsAndSetters.containsKey(is))
|
||||
throw new IllegalArgumentException("The provided ItemStack is not registered in this HotbarMenu");
|
||||
if (!currentPlayers.contains(p))
|
||||
throw new IllegalArgumentException("The provided Player is not registered in this HotbarMenu");
|
||||
itemsAndSetters.get(is).accept(p.getInventory(), is.clone());
|
||||
}
|
||||
|
||||
public void removeItemFromPlayer(Player p, ItemStack is) {
|
||||
p.getInventory().remove(is);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||
if (!currentPlayers.contains(event.getPlayer()))
|
||||
return;
|
||||
|
||||
ItemStack item = event.getItemDrop().getItemStack();
|
||||
for (ItemStack managed : itemsAndSetters.keySet()) {
|
||||
if (item.isSimilar(managed)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (!currentPlayers.contains(event.getPlayer()))
|
||||
return;
|
||||
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR)
|
||||
return;
|
||||
|
||||
ItemStack item = event.getItem();
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
Player p = event.getPlayer();
|
||||
|
||||
for (ItemStack is : itemsAndRunnables.keySet()) {
|
||||
if (item.isSimilar(is)) {
|
||||
try {
|
||||
itemsAndRunnables.get(is).accept(p);
|
||||
} catch (Exception e) {
|
||||
Log.severe(e);
|
||||
}
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (event.getClickedInventory() == null || !(event.getClickedInventory() instanceof PlayerInventory inv))
|
||||
return;
|
||||
|
||||
if (!currentPlayers.contains((Player) inv.getHolder()))
|
||||
return;
|
||||
|
||||
ItemStack item = event.getCurrentItem();
|
||||
|
||||
for (ItemStack is : itemsAndSetters.keySet()) {
|
||||
if (item != null && item.isSimilar(is)) {
|
||||
try {
|
||||
itemsAndRunnables.get(is).accept((Player) inv.getHolder());
|
||||
} catch (Exception e) {
|
||||
Log.severe(e);
|
||||
}
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
removePlayer(event.getPlayer());
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
if (!currentPlayers.contains(event.getEntity()))
|
||||
return;
|
||||
event.getDrops().removeAll(itemsAndSetters.keySet());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
if (!currentPlayers.contains(event.getPlayer()))
|
||||
return;
|
||||
|
||||
currentPlayers.remove(event.getPlayer());
|
||||
addPlayer(event.getPlayer());
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,261 @@
|
||||
package fr.pandacube.lib.paper.gui;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import fr.pandacube.lib.core.players.IPlayerManager;
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.paper.util.ItemStackBuilder;
|
||||
|
||||
public class GUIInventory implements Listener {
|
||||
|
||||
public static final Map<Enchantment, Integer> FAKE_ENCHANT = ImmutableMap.of(Enchantment.DURABILITY, 1);
|
||||
|
||||
private final Player player;
|
||||
private final Inventory inv;
|
||||
private Consumer<InventoryCloseEvent> onCloseEvent;
|
||||
private boolean isOpened = false;
|
||||
private final Map<Integer, Consumer<InventoryClickEvent>> onClickEvents;
|
||||
|
||||
public GUIInventory(Player p, int nbLines, Chat title, Consumer<InventoryCloseEvent> closeEventAction,
|
||||
Plugin pl) {
|
||||
if (title == null)
|
||||
inv = Bukkit.createInventory(null, nbLines * 9);
|
||||
else
|
||||
inv = Bukkit.createInventory(null, nbLines * 9, title.getAdv());
|
||||
|
||||
if (IPlayerManager.getInstance().get(p.getUniqueId()).isBedrockClient()) {
|
||||
Log.warning("Opening GUI inventory for player on Bedrock client " + p.getName() + " (" + p.getUniqueId() + "). Please use a Form instead.", new Throwable());
|
||||
}
|
||||
|
||||
setCloseEvent(closeEventAction);
|
||||
|
||||
onClickEvents = new HashMap<>();
|
||||
|
||||
player = p;
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, pl);
|
||||
|
||||
}
|
||||
|
||||
protected void setCloseEvent(Consumer<InventoryCloseEvent> closeEventAction) {
|
||||
onCloseEvent = closeEventAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clickEventActions (l'event passé en paramètre de la méthode done a
|
||||
* été pré-annulée. Pour la rétablir, faites un
|
||||
* event.setCancelled(false)).
|
||||
*/
|
||||
public void setButtonIfEmpty(int p, ItemStack iStack, Consumer<InventoryClickEvent> clickEventActions) {
|
||||
if (inv.getItem(p) == null)
|
||||
setButton(p, iStack, clickEventActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clickEventActions (l'event passé en paramètre de la méthode done a
|
||||
* été pré-annulée. Pour la rétablir, faites un
|
||||
* event.setCancelled(false)).
|
||||
*/
|
||||
public void setButton(int p, ItemStack iStack, Consumer<InventoryClickEvent> clickEventActions) {
|
||||
inv.setItem(p, iStack);
|
||||
changeClickEventAction(p, clickEventActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clickEventActions (l'event passé en paramètre de la méthode done a
|
||||
* été pré-annulée. Pour la rétablir, faites un
|
||||
* event.setCancelled(false)).
|
||||
*/
|
||||
public void changeClickEventAction(int p, Consumer<InventoryClickEvent> clickEventActions) {
|
||||
onClickEvents.put(p, clickEventActions);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(int p) {
|
||||
return inv.getItem(p);
|
||||
}
|
||||
|
||||
public void open() {
|
||||
if (isOpened) return;
|
||||
player.openInventory(inv);
|
||||
isOpened = true;
|
||||
}
|
||||
|
||||
public void forceClose() {
|
||||
if (!isOpened) return;
|
||||
player.closeInventory(); // internally calls the InventoryCloseEvent
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return isOpened;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
onClickEvents.clear();
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
public void clear(int firstElement, int nbElement) {
|
||||
for (int i = firstElement; i < firstElement + nbElement; i++) {
|
||||
inv.setItem(i, null);
|
||||
onClickEvents.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
public Inventory getInventory() {
|
||||
return inv;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!event.getWhoClicked().equals(player)) return;
|
||||
if (!isOpened) return;
|
||||
if (!event.getView().getTopInventory().equals(inv)) return;
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
// on ne réagit pas aux clics hors de l'inventaire du dessus.
|
||||
if (event.getClickedInventory() != event.getView().getTopInventory()) return;
|
||||
|
||||
Consumer<InventoryClickEvent> callback = onClickEvents.get(event.getSlot());
|
||||
if (callback != null)
|
||||
callback.accept(event);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (!event.getPlayer().equals(player)) return;
|
||||
if (!isOpened) return;
|
||||
if (!event.getView().getTopInventory().equals(inv)) return;
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
|
||||
if (onCloseEvent != null)
|
||||
onCloseEvent.accept(event);
|
||||
isOpened = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static ItemStack buildButton(ItemStack base, Integer amount, Chat displayName,
|
||||
List<Chat> lores, Map<Enchantment, Integer> enchantments) {
|
||||
|
||||
ItemStackBuilder iStackBuilder = ItemStackBuilder.of(base);
|
||||
|
||||
if (amount != null)
|
||||
iStackBuilder.amount(amount);
|
||||
if (displayName != null)
|
||||
iStackBuilder.displayName(displayName);
|
||||
if (lores != null)
|
||||
iStackBuilder.lore(lores);
|
||||
if (enchantments != null) {
|
||||
if (enchantments == FAKE_ENCHANT)
|
||||
iStackBuilder.fakeEnchant();
|
||||
else {
|
||||
for (Entry<Enchantment, Integer> e : enchantments.entrySet()) {
|
||||
iStackBuilder.enchant(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iStackBuilder.build();
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Chat displayName, List<Chat> lores, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(base, null, displayName, lores, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Integer amount, Chat displayName, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(base, amount, displayName, null, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Chat displayName, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(base, null, displayName, null, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Integer amount, Chat displayName, List<Chat> lores) {
|
||||
return buildButton(base, amount, displayName, lores, null);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Chat displayName, List<Chat> lores) {
|
||||
return buildButton(base, null, displayName, lores, null);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Integer amount, Chat displayName) {
|
||||
return buildButton(base, amount, displayName, null, null);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Chat displayName) {
|
||||
return buildButton(base, null, displayName, null, null);
|
||||
}
|
||||
public static ItemStack buildButton(ItemStack base, Integer amount) {
|
||||
return buildButton(base, amount, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static ItemStack buildButton(Material m, int amount, Chat displayName, List<Chat> lores, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(new ItemStack(m, amount), displayName, lores, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, Chat displayName, List<Chat> lores, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(m, 1, displayName, lores, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, int amount, Chat displayName, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(m, amount, displayName, null, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, Chat displayName, Map<Enchantment, Integer> enchantments) {
|
||||
return buildButton(m, 1, displayName, null, enchantments);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, int amount, Chat displayName, List<Chat> lores) {
|
||||
return buildButton(m, amount, displayName, lores, null);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, Chat displayName, List<Chat> lores) {
|
||||
return buildButton(m, 1, displayName, lores, null);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, int amount, Chat displayName) {
|
||||
return buildButton(m, amount, displayName, null, null);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, Chat displayName) {
|
||||
return buildButton(m, 1, displayName, null, null);
|
||||
}
|
||||
public static ItemStack buildButton(Material m, int amount) {
|
||||
return buildButton(m, amount, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static int nbLineForNbElements(int nb) {
|
||||
return nb / 9 + ((nb % 9 == 0) ? 0 : 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,692 @@
|
||||
package fr.pandacube.lib.paper.reflect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectClass;
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectField;
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectMember;
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectMethod;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class NMSReflect {
|
||||
|
||||
|
||||
private static String OBF_NAMESPACE;
|
||||
private static String MOJ_NAMESPACE;
|
||||
|
||||
/* package */ static final Map<String, ClassMapping> CLASSES_BY_OBF = new TreeMap<>();
|
||||
/* package */ static final Map<String, ClassMapping> CLASSES_BY_MOJ = new TreeMap<>();
|
||||
|
||||
private static Boolean IS_SERVER_OBFUSCATED;
|
||||
|
||||
private static boolean isInit = false;
|
||||
|
||||
public static void init() {
|
||||
|
||||
synchronized (NMSReflect.class) {
|
||||
if (isInit)
|
||||
return;
|
||||
isInit = true;
|
||||
}
|
||||
|
||||
Log.info("[NMSReflect] Initializing NMS obfuscation mapping...");
|
||||
|
||||
try {
|
||||
ReflectClass<?> obfHelperClass;
|
||||
try {
|
||||
obfHelperClass = Reflect.ofClass("io.papermc.paper.util.ObfHelper");
|
||||
|
||||
OBF_NAMESPACE = (String) obfHelperClass.field("SPIGOT_NAMESPACE").getStaticValue();
|
||||
MOJ_NAMESPACE = (String) obfHelperClass.field("MOJANG_PLUS_YARN_NAMESPACE").getStaticValue();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectiveOperationException("Unable to find the Paper ofbuscation mapping class or class members.", e);
|
||||
}
|
||||
|
||||
List<ClassMapping> mappings = loadMappings(obfHelperClass);
|
||||
for (ClassMapping clazz : mappings) {
|
||||
CLASSES_BY_OBF.put(clazz.obfName, clazz);
|
||||
CLASSES_BY_MOJ.put(clazz.mojName, clazz);
|
||||
}
|
||||
|
||||
// determine if the runtime server is obfuscated
|
||||
ClassNotFoundException exIfUnableToDetermine = null;
|
||||
for (ClassMapping clazz : CLASSES_BY_OBF.values()) {
|
||||
if (clazz.obfName.equals(clazz.mojName) // avoid direct collision between obf and unobf class names
|
||||
|| CLASSES_BY_MOJ.containsKey(clazz.obfName) // avoid indirect collision
|
||||
|| CLASSES_BY_OBF.containsKey(clazz.mojName))// avoid indirect collision
|
||||
continue;
|
||||
|
||||
try {
|
||||
Class.forName(clazz.obfName);
|
||||
IS_SERVER_OBFUSCATED = true;
|
||||
break;
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
Class.forName(clazz.mojName);
|
||||
IS_SERVER_OBFUSCATED = false;
|
||||
break;
|
||||
} catch (ClassNotFoundException ee) {
|
||||
ee.addSuppressed(e);
|
||||
if (exIfUnableToDetermine == null)
|
||||
exIfUnableToDetermine = ee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_SERVER_OBFUSCATED == null) {
|
||||
throw new IllegalStateException("Unable to determine if this server is obfuscated or not", exIfUnableToDetermine);
|
||||
}
|
||||
if (IS_SERVER_OBFUSCATED) {
|
||||
Log.info("[NMSReflect] NMS runtime classes are obfuscated.");
|
||||
}
|
||||
else {
|
||||
Log.info("[NMSReflect] NMS runtime classes are mojang mapped.");
|
||||
}
|
||||
|
||||
int missingRuntimeClasses = 0;
|
||||
for (ClassMapping clazz : mappings) {
|
||||
try {
|
||||
clazz.cacheReflectClass();
|
||||
} catch (Throwable e) {
|
||||
missingRuntimeClasses++;
|
||||
if (e instanceof ClassNotFoundException cnfe) {
|
||||
Log.warning("[NMSReflect] Missing runtime class " + cnfe.getMessage() + (IS_SERVER_OBFUSCATED ? (" (moj class: " + clazz.mojName + ")") : ""));
|
||||
}
|
||||
else {
|
||||
Log.warning("[NMSReflect] Unable to load runtime class " + (IS_SERVER_OBFUSCATED ? (clazz.obfName + " (moj class: " + clazz.mojName + ")") : clazz.mojName));
|
||||
Log.warning(e); // throwable on separate log message due to sometimes the message not showing at all because of this exception
|
||||
}
|
||||
CLASSES_BY_OBF.remove(clazz.obfName);
|
||||
CLASSES_BY_MOJ.remove(clazz.mojName);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingRuntimeClasses > 0) {
|
||||
Log.warning("[NMSReflect] " + missingRuntimeClasses + " class have been removed from the mapping data due to the previously stated errors.");
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
CLASSES_BY_OBF.clear();
|
||||
CLASSES_BY_MOJ.clear();
|
||||
Log.severe("[NMSReflect] The plugin will not have access to NMS stuff due to an error while loading the obfuscation mapping.", t);
|
||||
}
|
||||
Log.info("[NMSReflect] Obfuscation mapping loaded for " + CLASSES_BY_OBF.size() + " classes.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mojName the binary name of the desired class, on the mojang mapping.
|
||||
* @throws NullPointerException if there is no mapping for the provided Mojang mapped class.
|
||||
*/
|
||||
public static ClassMapping mojClass(String mojName) {
|
||||
return Objects.requireNonNull(CLASSES_BY_MOJ.get(mojName), "Unable to find the Mojang mapped class '" + mojName + "'");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static List<ClassMapping> loadMappings(ReflectClass<?> obfHelperClass) throws IOException {
|
||||
try (final InputStream mappingsInputStream = obfHelperClass.get().getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) {
|
||||
if (mappingsInputStream == null) {
|
||||
throw new RuntimeException("Unable to find the ofbuscation mapping file in the Paper jar.");
|
||||
}
|
||||
|
||||
MemoryMappingTree tree = new MemoryMappingTree();
|
||||
MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2, tree);
|
||||
|
||||
List<ClassMapping> classes = new ArrayList<>();
|
||||
for (MappingTree.ClassMapping cls : tree.getClasses()) {
|
||||
classes.add(new ClassMapping(cls));
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void printHTMLMapping(PrintStream out) {
|
||||
String title = "Obfuscation mapping - " + Bukkit.getName() + " version " + Bukkit.getVersion();
|
||||
out.println("<!DOCTYPE html><html><head>\n"
|
||||
+ "<title>" + title + "</title>\n"
|
||||
+ """
|
||||
<style>
|
||||
html {
|
||||
background-color: #2F2F2F;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-family: Consolas, monospace;
|
||||
}
|
||||
a:not(.cl) {
|
||||
color: #1290C3;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
tr:nth-child(2n) {
|
||||
background-color: #373737;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
tr > *:first-child {
|
||||
padding-right: .5em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
b.pu {
|
||||
color: #0C0;
|
||||
}
|
||||
b.pt {
|
||||
color: #FC0;
|
||||
}
|
||||
b.pv {
|
||||
color: #F00;
|
||||
}
|
||||
b.pk {
|
||||
color: #66F;
|
||||
}
|
||||
td {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
font-size: 1.1em;
|
||||
border-top: solid 1px white;
|
||||
}
|
||||
.kw {
|
||||
color: #CC6C1D;
|
||||
}
|
||||
.cl {
|
||||
color: #1290C3;
|
||||
}
|
||||
.mtd {
|
||||
color: #1EB540;
|
||||
}
|
||||
.fld {
|
||||
color: #8DDAF8;
|
||||
}
|
||||
.st {
|
||||
font-style: italic;
|
||||
}
|
||||
.st.fn {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
"""
|
||||
+ "<h1>" + title + "</h1>\n"
|
||||
+ """
|
||||
<p>
|
||||
<b>C</b>: <span class='kw'>class</span>
|
||||
<b>E</b>: <span class='kw'>enum</span>
|
||||
<b>I</b>: <span class='kw'>interface</span>
|
||||
<b>@</b>: <span class='kw'>@interface</span>
|
||||
<b>R</b>: <span class='kw'>record</span><br>
|
||||
<b>●</b>: field
|
||||
<b>c</b>: constructor
|
||||
<b>⬤</b>: method<br>
|
||||
<b class='pu'>⬤</b>: <span class='kw'>public</span>
|
||||
<b class='pt'>⬤</b>: <span class='kw'>protected</span>
|
||||
<b class='pk'>⬤</b>: package
|
||||
<b class='pv'>⬤</b>: <span class='kw'>private</span><br>
|
||||
<sup>S</sup>: <span class='kw'>static</span>
|
||||
<sup>A</sup>: <span class='kw'>abstract</span>
|
||||
<sup>F</sup>: <span class='kw'>final</span>
|
||||
</p>
|
||||
<table>
|
||||
""");
|
||||
out.println("<tr><th>ns</th><th>" + OBF_NAMESPACE + "</th><th>" + MOJ_NAMESPACE + "</th></tr>");
|
||||
for (ClassMapping clazz : CLASSES_BY_OBF.values()) {
|
||||
clazz.printHTML(out);
|
||||
}
|
||||
out.println("</table><p>Generated by <a href='https://github.com/marcbal'>marcbal</a>"
|
||||
+ " using <a href='https://github.com/PandacubeFr/PandaLib/blob/master/Paper/src/main/java/fr/pandacube/lib/paper/reflect/NMSReflect.java'>this tool</a>"
|
||||
+ " running on <a href='https://papermc.io/'>" + Bukkit.getName() + "</a> version " + Bukkit.getVersion() + "</p>"
|
||||
+ "</body></html>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static class ClassMapping {
|
||||
private static int nextID = 0;
|
||||
|
||||
/* package */ final int id = nextID++;
|
||||
/* package */ final String obfName;
|
||||
/* package */ final String mojName;
|
||||
|
||||
private final Map<MethodId, MemberMapping<MethodId, ReflectMethod<?>>> methodsByObf = new TreeMap<>();
|
||||
private final Map<MethodId, MemberMapping<MethodId, ReflectMethod<?>>> methodsByMoj = new TreeMap<>();
|
||||
private final Map<String, MemberMapping<String, ReflectField<?>>> fieldsByObf = new TreeMap<>();
|
||||
private final Map<String, MemberMapping<String, ReflectField<?>>> fieldsByMoj = new TreeMap<>();
|
||||
|
||||
private ReflectClass<?> runtimeReflectClass = null;
|
||||
|
||||
private ClassMapping(MappingTree.ClassMapping cls) {
|
||||
obfName = binaryClassName(cls.getName(OBF_NAMESPACE));
|
||||
mojName = binaryClassName(cls.getName(MOJ_NAMESPACE));
|
||||
|
||||
cls.getMethods().stream().map(MemberMapping::of).forEach(method -> {
|
||||
method.declaringClass = this;
|
||||
methodsByObf.put(method.obfDesc.identifier, method);
|
||||
methodsByMoj.put(method.mojDesc.identifier, method);
|
||||
});
|
||||
cls.getFields().stream().map(MemberMapping::of).forEach(field -> {
|
||||
field.declaringClass = this;
|
||||
fieldsByObf.put(field.obfDesc.identifier, field);
|
||||
fieldsByMoj.put(field.mojDesc.identifier, field);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private synchronized void cacheReflectClass() throws ClassNotFoundException {
|
||||
if (runtimeReflectClass == null)
|
||||
runtimeReflectClass = Reflect.ofClass(IS_SERVER_OBFUSCATED ? obfName : mojName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public ReflectClass<?> runtimeReflect() {
|
||||
return runtimeReflectClass;
|
||||
}
|
||||
|
||||
public Class<?> runtimeClass() {
|
||||
return runtimeReflectClass.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mojName the Mojang mapped name of the method.
|
||||
* @param mojParametersType the list of parameters of the method.
|
||||
* Each parameter type must be an instance of one of the following type:
|
||||
* {@link Type}, {@link Class}, {@link ReflectClass} or {@link ClassMapping}.
|
||||
* @throws IllegalArgumentException if one of the parameter has an invalid type
|
||||
* @throws NullPointerException if one of the parameter is null, or if there is no mapping for the provided Mojang mapped method.
|
||||
* @throws ClassNotFoundException if there is no runtime class to represent one of the provided parametersType.
|
||||
* @throws NoSuchMethodException if there is no runtime method to represent the provided method.
|
||||
*/
|
||||
public ReflectMethod<?> mojMethod(String mojName, Object... mojParametersType) throws ClassNotFoundException, NoSuchMethodException {
|
||||
MethodId mId = new MethodId(mojName, Type.toTypeList(Arrays.asList(mojParametersType)));
|
||||
MemberMapping<MethodId, ReflectMethod<?>> mm = methodsByMoj.get(mId);
|
||||
Objects.requireNonNull(mm, "Unable to find the Mojang mapped method " + mId);
|
||||
|
||||
try {
|
||||
return mm.getReflectMember();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
if (e instanceof ClassNotFoundException cnfe)
|
||||
throw cnfe;
|
||||
if (e instanceof NoSuchMethodException nsme)
|
||||
throw nsme;
|
||||
// should not have another exception
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mojName the Mojang mapped name of the field.
|
||||
* @throws NullPointerException if there is no mapping for the provided Mojang mapped field.
|
||||
* @throws NoSuchFieldException if there is no runtime method to represent the provided method.
|
||||
*/
|
||||
public ReflectField<?> mojField(String mojName) throws NoSuchFieldException {
|
||||
MemberMapping<String, ReflectField<?>> fm = fieldsByMoj.get(mojName);
|
||||
Objects.requireNonNull(fm, "Unable to find the Mojang mapped field '" + mojName + "'");
|
||||
try {
|
||||
return fm.getReflectMember();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
if (e instanceof NoSuchFieldException nsfe)
|
||||
throw nsfe;
|
||||
// should not have another exception
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ String toClickableHTML(boolean isObfClass) {
|
||||
String classToPrint = isObfClass ? obfName : mojName;
|
||||
String classSimpleName = classToPrint.substring(classToPrint.lastIndexOf('.') + 1);
|
||||
String htmlTitle = classSimpleName.equals(classToPrint) ? "" : (" title='" + classToPrint + "'");
|
||||
return "<a href='#c" + id + "'" + htmlTitle + " class='cl'>" + classSimpleName + "</a>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ Type toType(boolean obf) {
|
||||
return new Type(obf ? obfName : mojName, 0);
|
||||
}
|
||||
|
||||
|
||||
private void printHTML(PrintStream out) {
|
||||
String modifiersHTML = classModifiersToHTML(runtimeClass());
|
||||
out.println("<tr id='c" + id + "'><th>" + modifiersHTML + "</th><th>" + nameToHTML(true) + "</th><th>" + nameToHTML(false) + "</th></tr>");
|
||||
fieldsByObf.values().stream().filter(mm -> mm.isStatic()).forEach(f -> f.printHTML(out));
|
||||
methodsByObf.values().stream().filter(mm -> mm.isStatic()).forEach(m -> m.printHTML(out));
|
||||
printConstructorsHTML(out);
|
||||
fieldsByObf.values().stream().filter(mm -> !mm.isStatic()).forEach(f -> f.printHTML(out));
|
||||
methodsByObf.values().stream().filter(mm -> !mm.isStatic()).forEach(m -> m.printHTML(out));
|
||||
}
|
||||
|
||||
private String nameToHTML(boolean obf) {
|
||||
String classToPrint = obf ? obfName : mojName;
|
||||
int packageSep = classToPrint.lastIndexOf('.');
|
||||
String classSimpleName = classToPrint.substring(packageSep + 1);
|
||||
String classPackages = classToPrint.substring(0, Math.max(packageSep, 0));
|
||||
String classHTML = (packageSep >= 0 ? (classPackages + ".") : "") + "<b class='cl'>" + classSimpleName + "</b>";
|
||||
|
||||
Type superClass = superClass(obf);
|
||||
String superClassHTML = superClass == null ? "" : (" <span class='kw'>extends</span> " + superClass.toHTML(obf));
|
||||
|
||||
List<Type> superInterfaces = superInterfaces(obf);
|
||||
String superInterfacesHTML = superInterfaces.isEmpty() ? ""
|
||||
: (" <span class='kw'>implements</span> " + superInterfaces.stream().map(t -> t.toHTML(obf)).collect(Collectors.joining(", ")));
|
||||
|
||||
return classHTML + superClassHTML + superInterfacesHTML;
|
||||
}
|
||||
|
||||
private Type superClass(boolean obf) {
|
||||
Class<?> superClass = runtimeClass().getSuperclass();
|
||||
if (superClass == null || superClass.equals(Object.class) || superClass.equals(Enum.class) || superClass.equals(Record.class))
|
||||
return null;
|
||||
ClassMapping cm = (IS_SERVER_OBFUSCATED ? CLASSES_BY_OBF : CLASSES_BY_MOJ).get(superClass.getName());
|
||||
return (cm != null) ? cm.toType(obf) : Type.of(superClass);
|
||||
}
|
||||
|
||||
private List<Type> superInterfaces(boolean obf) {
|
||||
Class<?>[] interfaces = runtimeClass().getInterfaces();
|
||||
List<Type> types = new ArrayList<>(interfaces.length);
|
||||
for (Class<?> interfce : interfaces) {
|
||||
ClassMapping cm = (IS_SERVER_OBFUSCATED ? CLASSES_BY_OBF : CLASSES_BY_MOJ).get(interfce.getName());
|
||||
types.add((cm != null) ? cm.toType(obf) : Type.of(interfce));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
private void printConstructorsHTML(PrintStream out) {
|
||||
String classObfSimpleName = obfName.substring(obfName.lastIndexOf('.') + 1);
|
||||
String classMojSimpleName = mojName.substring(mojName.lastIndexOf('.') + 1);
|
||||
for (Constructor<?> ct : runtimeClass().getDeclaredConstructors()) {
|
||||
List<Type> obfParams = new ArrayList<>();
|
||||
List<Type> mojParams = new ArrayList<>();
|
||||
for (Class<?> param : ct.getParameterTypes()) {
|
||||
ClassMapping cm = (IS_SERVER_OBFUSCATED ? CLASSES_BY_OBF : CLASSES_BY_MOJ).get(param.getName());
|
||||
if (cm == null) {
|
||||
Type t = Type.of(param);
|
||||
obfParams.add(t);
|
||||
mojParams.add(t);
|
||||
}
|
||||
else {
|
||||
obfParams.add(cm.toType(true));
|
||||
mojParams.add(cm.toType(false));
|
||||
}
|
||||
}
|
||||
out.println("<tr>"
|
||||
+ "<td>" + elementModifiersToHTML("c", ct.getModifiers()) + "</td>"
|
||||
+ "<td><b class='mtd'>" + classObfSimpleName + "</b>(" + obfParams.stream().map(t -> t.toHTML(true)).collect(Collectors.joining(", ")) + ")</td>"
|
||||
+ "<td><b class='mtd'>" + classMojSimpleName + "</b>(" + mojParams.stream().map(t -> t.toHTML(false)).collect(Collectors.joining(", ")) + ")</td>"
|
||||
+ "</tr>");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private record MethodId(String name, List<Type> parametersType) implements Comparable<MethodId> {
|
||||
@Override
|
||||
public int compareTo(MethodId o) {
|
||||
int cmp = name.compareTo(o.name);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
return toString().compareTo(o.toString());
|
||||
}
|
||||
|
||||
private String toHTML(boolean isObfClass, boolean isStatic, boolean isFinal) {
|
||||
String paramsHTML = parametersType.stream().map(p -> p.toHTML(isObfClass)).collect(Collectors.joining(", "));
|
||||
String cl = "mtd";
|
||||
if (isStatic)
|
||||
cl += " st";
|
||||
if (isFinal)
|
||||
cl += " fn";
|
||||
return "<span class='" + cl + "'>" + name + "</span>(" + paramsHTML + ")";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String paramsStr = parametersType.stream().map(Type::toString).collect(Collectors.joining(", "));
|
||||
return name + "(" + paramsStr + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private record MemberDesc<I extends Comparable<I>>(I identifier, Type returnType) {
|
||||
private String toHTML(boolean isObfClass, boolean isStatic, boolean isFinal) {
|
||||
String identifierHTML = "";
|
||||
if (identifier instanceof MethodId mId)
|
||||
identifierHTML = mId.toHTML(isObfClass, isStatic, isFinal);
|
||||
else if (identifier instanceof String n) {
|
||||
String cl = "fld";
|
||||
if (isStatic)
|
||||
cl += " st";
|
||||
if (isFinal)
|
||||
cl += " fn";
|
||||
identifierHTML = "<span class='" + cl + "'>" + n + "</span>";
|
||||
}
|
||||
return returnType.toHTML(isObfClass) + " " + identifierHTML;
|
||||
}
|
||||
|
||||
private static MemberDesc<MethodId> of(MappingTree.MethodMapping member, String namespace) {
|
||||
String desc = member.getDesc(namespace);
|
||||
try (StringReader descReader = new StringReader(desc)) {
|
||||
char r = (char) descReader.read();
|
||||
if (r != '(')
|
||||
throw new IllegalArgumentException("Invalid method description '" + desc + "'. Must start with '('.");
|
||||
|
||||
List<Type> paramsType = new ArrayList<>();
|
||||
|
||||
while (((char) descReader.read()) != ')') {
|
||||
descReader.skip(-1);
|
||||
paramsType.add(Type.parse(descReader));
|
||||
}
|
||||
|
||||
Type retType = Type.parse(descReader);
|
||||
return new MemberDesc<>(new MethodId(member.getName(namespace), Collections.unmodifiableList(paramsType)), retType);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("StringReader read error", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static MemberDesc<String> of(MappingTree.FieldMapping member, String namespace) {
|
||||
StringReader descReader = new StringReader(member.getDesc(namespace));
|
||||
return new MemberDesc<>(member.getName(namespace), Type.parse(descReader));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static abstract class MemberMapping<I extends Comparable<I>, R extends ReflectMember<?, ?, ?, ?>> {
|
||||
private final String htmlTypeChar;
|
||||
/* package */ final MemberDesc<I> obfDesc, mojDesc;
|
||||
/* package */ ClassMapping declaringClass;
|
||||
private MemberMapping(String htmlType, MemberDesc<I> obfDesc, MemberDesc<I> mojDesc) {
|
||||
htmlTypeChar = htmlType;
|
||||
this.obfDesc = obfDesc;
|
||||
this.mojDesc = mojDesc;
|
||||
}
|
||||
|
||||
/* package */ void printHTML(PrintStream out) {
|
||||
int mod = 0;
|
||||
try {
|
||||
mod = getReflectMember().getModifiers();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
// ignore
|
||||
}
|
||||
boolean isStatic = Modifier.isStatic(mod);
|
||||
boolean isFinal = Modifier.isFinal(mod);
|
||||
out.println("<tr>"
|
||||
+ "<td>" + elementModifiersToHTML(htmlTypeChar, mod) + "</td>"
|
||||
+ "<td>" + obfDesc.toHTML(true, isStatic, isFinal) + "</td>"
|
||||
+ "<td>" + mojDesc.toHTML(false, isStatic, isFinal) + "</td>"
|
||||
+ "</tr>");
|
||||
}
|
||||
|
||||
/* package */ MemberDesc<I> getReflectDesc() {
|
||||
return (IS_SERVER_OBFUSCATED ? obfDesc : mojDesc);
|
||||
}
|
||||
|
||||
/* package */ abstract R getReflectMember() throws ReflectiveOperationException;
|
||||
|
||||
/* package */ boolean isStatic() {
|
||||
try {
|
||||
return Modifier.isStatic(getReflectMember().getModifiers());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
Log.severe(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static MemberMapping<MethodId, ReflectMethod<?>> of(MappingTree.MethodMapping mioMapping) {
|
||||
return new MemberMapping<>("⬤", MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE)) {
|
||||
@Override
|
||||
ReflectMethod<?> getReflectMember() throws ClassNotFoundException, NoSuchMethodException {
|
||||
MethodId id = getReflectDesc().identifier;
|
||||
return declaringClass.runtimeReflectClass.method(id.name, Type.toClassArray(id.parametersType));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static MemberMapping<String, ReflectField<?>> of(MappingTree.FieldMapping mioMapping) {
|
||||
return new MemberMapping<>("●", MemberDesc.of(mioMapping, OBF_NAMESPACE), MemberDesc.of(mioMapping, MOJ_NAMESPACE)) {
|
||||
@Override
|
||||
ReflectField<?> getReflectMember() throws NoSuchFieldException {
|
||||
String id = getReflectDesc().identifier;
|
||||
return declaringClass.runtimeReflectClass.field(id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ static String binaryClassName(String cl) {
|
||||
return cl.replace('/', '.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String classModifiersToHTML(Class<?> clazz) {
|
||||
String elementHTMLType;
|
||||
|
||||
if (clazz.isEnum())
|
||||
elementHTMLType = "E";
|
||||
else if (clazz.isAnnotation())
|
||||
elementHTMLType = "@";
|
||||
else if (clazz.isInterface())
|
||||
elementHTMLType = "I";
|
||||
else if (clazz.isRecord())
|
||||
elementHTMLType = "R";
|
||||
else if (clazz.isPrimitive())
|
||||
elementHTMLType = "";
|
||||
else
|
||||
elementHTMLType = "C";
|
||||
|
||||
return elementModifiersToHTML(elementHTMLType, clazz.getModifiers());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String elementModifiersToHTML(String elementHTMLType, int elModifiers) {
|
||||
String html = "<b class='";
|
||||
|
||||
if (Modifier.isPublic(elModifiers))
|
||||
html += "pu";
|
||||
else if (Modifier.isProtected(elModifiers))
|
||||
html += "pt";
|
||||
else if (Modifier.isPrivate(elModifiers))
|
||||
html += "pv";
|
||||
else
|
||||
html += "pk";
|
||||
|
||||
html += "'>" + elementHTMLType + "</b>";
|
||||
|
||||
boolean isStatic = Modifier.isStatic(elModifiers);
|
||||
boolean isAbstract = Modifier.isAbstract(elModifiers);
|
||||
boolean isFinal = Modifier.isFinal(elModifiers);
|
||||
|
||||
if (isStatic || isAbstract || isFinal) {
|
||||
html += "<sup>";
|
||||
if (isStatic)
|
||||
html += "S";
|
||||
if (isAbstract)
|
||||
html += "A";
|
||||
if (isFinal)
|
||||
html += "F";
|
||||
html += "</sup>";
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
// ● (field)
|
||||
// ⬤ (method)
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package fr.pandacube.lib.paper.reflect;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectClass;
|
||||
|
||||
public class OBCReflect {
|
||||
|
||||
private static final String OBC_PACKAGE_PREFIX = "org.bukkit.craftbukkit.";
|
||||
|
||||
private static final String OBC_PACKAGE_VERSION;
|
||||
|
||||
static {
|
||||
String name = Bukkit.getServer().getClass().getName()
|
||||
.substring(OBC_PACKAGE_PREFIX.length());
|
||||
name = name.substring(0, name.indexOf("."));
|
||||
|
||||
OBC_PACKAGE_VERSION = name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ReflectClass<?> ofClass(String obcClass) throws ClassNotFoundException {
|
||||
return Reflect.ofClass(OBC_PACKAGE_PREFIX + OBC_PACKAGE_VERSION + "." + obcClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,198 @@
|
||||
package fr.pandacube.lib.paper.reflect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectClass;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
|
||||
|
||||
public class Type implements Comparable<Type> {
|
||||
private final String type;
|
||||
private final int arrayDepth;
|
||||
|
||||
/* package */ Type(String type, int arrayDepth) {
|
||||
this.type = type;
|
||||
this.arrayDepth = arrayDepth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Type ot && type.equals(ot.type) && arrayDepth == ot.arrayDepth;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return type.hashCode() ^ arrayDepth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Type o) {
|
||||
return toString().compareTo(o.toString());
|
||||
}
|
||||
|
||||
Class<?> toClass() throws ClassNotFoundException {
|
||||
|
||||
Class<?> cl = switch(type) {
|
||||
case "boolean" -> boolean.class;
|
||||
case "byte" -> byte.class;
|
||||
case "char" -> char.class;
|
||||
case "double" -> double.class;
|
||||
case "float" -> float.class;
|
||||
case "int" -> int.class;
|
||||
case "long" -> long.class;
|
||||
case "short" -> short.class;
|
||||
case "void" -> void.class;
|
||||
default -> Class.forName(type);
|
||||
};
|
||||
|
||||
for (int i = 0; i < arrayDepth; i++) {
|
||||
cl = cl.arrayType();
|
||||
}
|
||||
|
||||
return cl;
|
||||
}
|
||||
|
||||
public Type arrayType() {
|
||||
return new Type(type, arrayDepth + 1);
|
||||
}
|
||||
|
||||
/* package */ static Type of(Class<?> cl) {
|
||||
int arrayDepth = 0;
|
||||
while (cl.isArray()) {
|
||||
cl = cl.getComponentType();
|
||||
arrayDepth++;
|
||||
}
|
||||
return new Type(cl.getName(), arrayDepth);
|
||||
}
|
||||
|
||||
public static Type of(ReflectClass<?> rc) {
|
||||
return arrayOf(rc, 0);
|
||||
}
|
||||
|
||||
public static Type arrayOf(ReflectClass<?> rc, int arrayDepth) {
|
||||
return new Type(rc.get().getName(), arrayDepth);
|
||||
}
|
||||
|
||||
public static Type mojOf(ClassMapping cm) {
|
||||
return arrayMojOf(cm, 0);
|
||||
}
|
||||
|
||||
public static Type arrayMojOf(ClassMapping cm, int arrayDepth) {
|
||||
return new Type(cm.mojName, arrayDepth);
|
||||
}
|
||||
|
||||
/* package */ static Type toType(Object typeObj) {
|
||||
Objects.requireNonNull(typeObj, "typeObj cannot be null");
|
||||
if (typeObj instanceof Class<?> cl) {
|
||||
return of(cl);
|
||||
}
|
||||
else if (typeObj instanceof ClassMapping cm) {
|
||||
return mojOf(cm);
|
||||
}
|
||||
else if (typeObj instanceof ReflectClass<?> rc) {
|
||||
return of(rc);
|
||||
}
|
||||
else if (typeObj instanceof Type t) {
|
||||
return t;
|
||||
}
|
||||
else
|
||||
throw new IllegalArgumentException("Unsupported object of type " + typeObj.getClass());
|
||||
}
|
||||
|
||||
/* package */ String toHTML(boolean isObfClass) {
|
||||
ClassMapping clMapping = (isObfClass ? NMSReflect.CLASSES_BY_OBF : NMSReflect.CLASSES_BY_MOJ).get(type);
|
||||
String typeHTML;
|
||||
if (clMapping != null) {
|
||||
typeHTML = clMapping.toClickableHTML(isObfClass);
|
||||
}
|
||||
else {
|
||||
String classToPrint = type;
|
||||
String classSimpleName = classToPrint.substring(classToPrint.lastIndexOf('.') + 1);
|
||||
String htmlTitle = classSimpleName.equals(classToPrint) ? "" : (" title='" + classToPrint + "'");
|
||||
if (!htmlTitle.equals("")) {
|
||||
typeHTML = "<span" + htmlTitle + " class='cl'>" + classSimpleName + "</span>";
|
||||
}
|
||||
else {
|
||||
typeHTML = "<span class='" + (isPrimitive() ? "kw" : "cl") + "'>" + classSimpleName + "</span>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return typeHTML + "[]".repeat(arrayDepth);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + "[]".repeat(arrayDepth);
|
||||
}
|
||||
|
||||
|
||||
public boolean isPrimitive() {
|
||||
try {
|
||||
return toClass().isPrimitive();
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ static Type parse(StringReader desc) {
|
||||
try {
|
||||
int arrayDepth = 0;
|
||||
char c;
|
||||
while ((c = (char) desc.read()) == '[') {
|
||||
arrayDepth++;
|
||||
}
|
||||
String type = switch(c) {
|
||||
case 'Z' -> "boolean";
|
||||
case 'B' -> "byte";
|
||||
case 'C' -> "char";
|
||||
case 'D' -> "double";
|
||||
case 'F' -> "float";
|
||||
case 'I' -> "int";
|
||||
case 'J' -> "long";
|
||||
case 'S' -> "short";
|
||||
case 'L' -> {
|
||||
StringBuilder sbClass = new StringBuilder();
|
||||
char r;
|
||||
while ((r = (char) desc.read()) != ';') {
|
||||
sbClass.append(r);
|
||||
}
|
||||
yield NMSReflect.binaryClassName(sbClass.toString());
|
||||
}
|
||||
default -> "void";
|
||||
};
|
||||
return new Type(type, arrayDepth);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("StringReader read error", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ static List<Type> toTypeList(List<Object> paramsType) {
|
||||
List<Type> types = new ArrayList<>(paramsType.size());
|
||||
for (int i = 0; i < paramsType.size(); i++) {
|
||||
Object param = paramsType.get(i);
|
||||
try {
|
||||
types.add(Type.toType(param));
|
||||
} catch (NullPointerException|IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Invalid parameterType at index " + i, e);
|
||||
}
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/* package */ static Class<?>[] toClassArray(List<Type> types) throws ClassNotFoundException {
|
||||
Class<?>[] classes = new Class<?>[types.size()];
|
||||
for (int i = 0; i < types.size(); i++) {
|
||||
classes[i] = types.get(i).toClass();
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicate a concrete wrapper class that implements the annotated interface or abstract class, in case there is no
|
||||
* proper wrapper for a provided runtime object.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ConcreteWrapper {
|
||||
Class<? extends ReflectWrapper> value();
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import fr.pandacube.lib.util.MappedListView;
|
||||
|
||||
public class ReflectListWrapper<W extends ReflectWrapperI> extends MappedListView<Object, W> implements ReflectWrapperTypedI<List<Object>> {
|
||||
|
||||
private final Class<W> expectedWrapperClass;
|
||||
|
||||
/* package */ ReflectListWrapper(Class<W> expectedWrapperClass) {
|
||||
this(ArrayList::new, expectedWrapperClass);
|
||||
}
|
||||
|
||||
/* package */
|
||||
@SuppressWarnings("unchecked")
|
||||
ReflectListWrapper(Supplier<List<?>> listCreator, Class<W> expectedWrapperClass) {
|
||||
this((List<Object>) (listCreator == null ? new ArrayList<>() : listCreator.get()), expectedWrapperClass);
|
||||
}
|
||||
/* package */ ReflectListWrapper(List<Object> wrappedList, Class<W> expectedWrapperClass) {
|
||||
super(wrappedList, el -> ReflectWrapper.wrap(el, expectedWrapperClass), ReflectWrapper::unwrap);
|
||||
this.expectedWrapperClass = expectedWrapperClass;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<List<Object>> __getRuntimeClass() {
|
||||
return (Class<List<Object>>) backend.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> __getRuntimeInstance() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<W> subList(int fromIndex, int toIndex) {
|
||||
return new ReflectListWrapper<>(backend.subList(fromIndex, toIndex), expectedWrapperClass);
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public abstract class ReflectWrapper implements ReflectWrapperI {
|
||||
|
||||
|
||||
private static final Map<Object, ReflectWrapperI> objectWrapperCache = new MapMaker().weakKeys().makeMap();
|
||||
|
||||
public static Object unwrap(ReflectWrapperI wr) {
|
||||
return wr == null ? null : wr.__getRuntimeInstance();
|
||||
}
|
||||
|
||||
public static <T> T unwrap(ReflectWrapperTypedI<T> wr) {
|
||||
return wr == null ? null : wr.__getRuntimeInstance();
|
||||
}
|
||||
|
||||
public static <W extends ReflectWrapperI> W wrap(Object runtimeObj) {
|
||||
return wrap(runtimeObj, null);
|
||||
}
|
||||
public static <T, W extends ReflectWrapperTypedI<T>> W wrapTyped(T runtimeObj, Class<W> expectedWrapperClass) {
|
||||
return wrap(runtimeObj, expectedWrapperClass);
|
||||
}
|
||||
public static <W extends ReflectWrapperI> W wrap(Object runtimeObj, Class<W> expectedWrapperClass) {
|
||||
if (runtimeObj == null)
|
||||
return null;
|
||||
synchronized (objectWrapperCache) {
|
||||
if (objectWrapperCache.containsKey(runtimeObj)) {
|
||||
ReflectWrapperI wrapper = objectWrapperCache.get(runtimeObj);
|
||||
if (expectedWrapperClass == null || expectedWrapperClass.isInstance(wrapper)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
W wr = (W) wrapper;
|
||||
return wr;
|
||||
}
|
||||
}
|
||||
Class<?> runtimeClass = runtimeObj.getClass();
|
||||
Class<?> expectedRuntimeClass = (expectedWrapperClass == null) ? null : WrapperRegistry.getRuntimeClassOfWrapperClass(expectedWrapperClass);
|
||||
if (expectedRuntimeClass != null && !expectedRuntimeClass.isAssignableFrom(runtimeClass)) {
|
||||
throw new ClassCastException("Runtime class " + runtimeClass + " is not a sub-class or a sub-interface of expected runtime class " + expectedRuntimeClass + "" +
|
||||
" (expected wrapper class " + expectedWrapperClass + ").");
|
||||
}
|
||||
Class<? extends ReflectWrapperI> wrapperClass = WrapperRegistry.getWrapperOfRuntimeClass(runtimeClass);
|
||||
if (wrapperClass == null) {
|
||||
// trying to use the provided expectedWrapperClass
|
||||
if (expectedWrapperClass == null || expectedRuntimeClass == null) { // implicitly: expectedWrapperClass is null or it has no corresponding runtimeClass
|
||||
// TODO try to search among all registered wrapper class for one that can support the provided object
|
||||
throw new IllegalArgumentException("No wrapper available to wrap an instance of runtime class " + runtimeClass + "." +
|
||||
(expectedWrapperClass != null ? (" Expected wrapper class " + expectedWrapperClass + " is also not valid.") : ""));
|
||||
}
|
||||
wrapperClass = expectedWrapperClass;
|
||||
}
|
||||
|
||||
if (expectedWrapperClass != null && !expectedWrapperClass.isAssignableFrom(wrapperClass)) {
|
||||
throw new ClassCastException("Wrapper class " + wrapperClass + " is not a sub-class or a sub-interface of expected wrapper class" + expectedWrapperClass);
|
||||
}
|
||||
Reflect.ReflectConstructor<? extends ReflectWrapperI> constructor = WrapperRegistry.getWrapperConstructorOfWrapperClass(wrapperClass);
|
||||
if (constructor == null) {
|
||||
throw new IllegalStateException("Unable to find a constructor to instanciate " + wrapperClass + " to wrap an instance of " + runtimeObj);
|
||||
}
|
||||
ReflectWrapperI wrapper = wrapEx(() -> constructor.instanciate(runtimeObj));
|
||||
// added to cache by constructor
|
||||
@SuppressWarnings("unchecked")
|
||||
W wr = (W) wrapper;
|
||||
return wr;
|
||||
}
|
||||
}
|
||||
|
||||
public static <W extends ReflectWrapperI> ReflectListWrapper<W> wrapList(List<Object> runtimeList, Class<W> expectedWrapperClass) {
|
||||
return new ReflectListWrapper<>(runtimeList, expectedWrapperClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected final Object reflectObject;
|
||||
|
||||
protected ReflectWrapper(Object obj) {
|
||||
Objects.requireNonNull(obj);
|
||||
if (!__getRuntimeClass().isInstance(obj)) {
|
||||
throw new ClassCastException(obj.getClass() + " object is not instanceof " + __getRuntimeClass());
|
||||
}
|
||||
reflectObject = obj;
|
||||
objectWrapperCache.put(obj, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object __getRuntimeInstance() {
|
||||
return reflectObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ReflectWrapper wr) {
|
||||
return Objects.equals(reflectObject, wr.reflectObject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(reflectObject);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
public interface ReflectWrapperI {
|
||||
|
||||
default Class<?> __getRuntimeClass() {
|
||||
return WrapperRegistry.getRuntimeClassOfWrapperClass(getClass());
|
||||
}
|
||||
|
||||
Object __getRuntimeInstance();
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
public abstract class ReflectWrapperTyped<T> extends ReflectWrapper implements ReflectWrapperTypedI<T> {
|
||||
|
||||
protected ReflectWrapperTyped(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> __getRuntimeClass() {
|
||||
return ReflectWrapperTypedI.super.__getRuntimeClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T __getRuntimeInstance() {
|
||||
return (T) super.__getRuntimeInstance();
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
public interface ReflectWrapperTypedI<T> extends ReflectWrapperI {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
default Class<? extends T> __getRuntimeClass() {
|
||||
return (Class<? extends T>) ReflectWrapperI.super.__getRuntimeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
T __getRuntimeInstance();
|
||||
}
|
@@ -0,0 +1,233 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper;
|
||||
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectConstructor;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.brigadier.CommandNode;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftMapView;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftNamespacedKey;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftPlayer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftVector;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftWorld;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.RenderData;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.DetectedVersion;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.SharedConstants;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.WorldVersion;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.BlockPosArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.CommandSourceStack;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Commands;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ComponentArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Coordinates;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntityArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntitySelector;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.GameProfileArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ResourceLocationArgument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Vec3Argument;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.Vec3i;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.NbtIo;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.StringTag;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.Tag;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.FriendlyByteBuf;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol.ClientboundCustomPayloadPacket;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol.ClientboundGameEventPacket;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol.Packet;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.resources.ResourceLocation;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ChunkMap;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.DedicatedPlayerList;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.DedicatedServer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.DedicatedServerProperties;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.MinecraftServer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerChunkCache;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerGamePacketListenerImpl;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerLevel;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.Settings;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.util.ProgressListener;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.AABB;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ChunkPos;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ChunkStorage;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.DamageSource;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Level;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.MapItemSavedData;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.SavedData;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Vec3;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.VoxelShape;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.block.BambooBlock;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.netty.ByteBuf;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.netty.Unpooled;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.AABBVoxelShape;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.PaperAdventure;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.QueuedChangesMapLong2Object;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.configuration.FallbackValue_Int;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.configuration.WorldConfiguration;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WrapperRegistry {
|
||||
|
||||
public static void init() {
|
||||
|
||||
// craftbukkit
|
||||
initWrapper(CommandNode.class, CommandNode.REFLECT.get());
|
||||
|
||||
// craftbukkit
|
||||
initWrapper(CraftMapView.class, CraftMapView.REFLECT.get());
|
||||
initWrapper(CraftNamespacedKey.class, CraftNamespacedKey.REFLECT.get());
|
||||
initWrapper(CraftPlayer.class, CraftPlayer.REFLECT.get());
|
||||
initWrapper(CraftServer.class, CraftServer.REFLECT.get());
|
||||
initWrapper(CraftVector.class, CraftVector.REFLECT.get());
|
||||
initWrapper(CraftWorld.class, CraftWorld.REFLECT.get());
|
||||
initWrapper(RenderData.class, RenderData.REFLECT.get());
|
||||
initWrapper(VanillaCommandWrapper.class, VanillaCommandWrapper.REFLECT.get());
|
||||
|
||||
// minecraft.commands
|
||||
initWrapper(BlockPosArgument.class, BlockPosArgument.MAPPING.runtimeClass());
|
||||
initWrapper(Commands.class, Commands.MAPPING.runtimeClass());
|
||||
initWrapper(CommandSourceStack.class, CommandSourceStack.MAPPING.runtimeClass());
|
||||
initWrapper(ComponentArgument.class, ComponentArgument.MAPPING.runtimeClass());
|
||||
initWrapper(Coordinates.class, Coordinates.MAPPING.runtimeClass());
|
||||
initWrapper(EntityArgument.class, EntityArgument.MAPPING.runtimeClass());
|
||||
initWrapper(EntitySelector.class, EntitySelector.MAPPING.runtimeClass());
|
||||
initWrapper(GameProfileArgument.class, GameProfileArgument.MAPPING.runtimeClass());
|
||||
initWrapper(ResourceLocationArgument.class, ResourceLocationArgument.MAPPING.runtimeClass());
|
||||
initWrapper(Vec3Argument.class, Vec3Argument.MAPPING.runtimeClass());
|
||||
// minecraft.core
|
||||
initWrapper(BlockPos.class, BlockPos.MAPPING.runtimeClass());
|
||||
initWrapper(Vec3i.class, Vec3i.MAPPING.runtimeClass());
|
||||
// minecraft.nbt
|
||||
initWrapper(CompoundTag.class, CompoundTag.MAPPING.runtimeClass());
|
||||
initWrapper(NbtIo.class, NbtIo.MAPPING.runtimeClass());
|
||||
initWrapper(StringTag.class, StringTag.MAPPING.runtimeClass());
|
||||
initWrapper(Tag.class, Tag.MAPPING.runtimeClass());
|
||||
// minecraft.network.chat
|
||||
initWrapper(Component.class, Component.MAPPING.runtimeClass());
|
||||
// minecraft.network.protocol
|
||||
initWrapper(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket.MAPPING.runtimeClass());
|
||||
initWrapper(ClientboundGameEventPacket.class, ClientboundGameEventPacket.MAPPING.runtimeClass());
|
||||
initWrapper(ClientboundGameEventPacket.Type.class, ClientboundGameEventPacket.Type.MAPPING.runtimeClass());
|
||||
initWrapper(Packet.class, Packet.MAPPING.runtimeClass());
|
||||
// minecraft.network
|
||||
initWrapper(FriendlyByteBuf.class, FriendlyByteBuf.MAPPING.runtimeClass());
|
||||
// minecraft.resources
|
||||
initWrapper(ResourceLocation.class, ResourceLocation.MAPPING.runtimeClass());
|
||||
// minecraft.server
|
||||
initWrapper(ChunkMap.class, ChunkMap.MAPPING.runtimeClass());
|
||||
initWrapper(DedicatedPlayerList.class, DedicatedPlayerList.MAPPING.runtimeClass());
|
||||
initWrapper(DedicatedServer.class, DedicatedServer.MAPPING.runtimeClass());
|
||||
initWrapper(DedicatedServerProperties.class, DedicatedServerProperties.MAPPING.runtimeClass());
|
||||
initWrapper(MinecraftServer.class, MinecraftServer.MAPPING.runtimeClass());
|
||||
initWrapper(ServerChunkCache.class, ServerChunkCache.MAPPING.runtimeClass());
|
||||
initWrapper(ServerGamePacketListenerImpl.class, ServerGamePacketListenerImpl.MAPPING.runtimeClass());
|
||||
initWrapper(ServerLevel.class, ServerLevel.MAPPING.runtimeClass());
|
||||
initWrapper(ServerPlayer.class, ServerPlayer.MAPPING.runtimeClass());
|
||||
initWrapper(Settings.class, Settings.MAPPING.runtimeClass());
|
||||
// minecraft.util
|
||||
initWrapper(ProgressListener.class, ProgressListener.MAPPING.runtimeClass());
|
||||
// minecraft.world.block
|
||||
initWrapper(BambooBlock.class, BambooBlock.MAPPING.runtimeClass());
|
||||
// minecraft.world
|
||||
initWrapper(AABB.class, AABB.MAPPING.runtimeClass());
|
||||
initWrapper(ChunkPos.class, ChunkPos.MAPPING.runtimeClass());
|
||||
initWrapper(ChunkStorage.class, ChunkStorage.MAPPING.runtimeClass());
|
||||
initWrapper(DamageSource.class, DamageSource.MAPPING.runtimeClass());
|
||||
initWrapper(Entity.class, Entity.MAPPING.runtimeClass());
|
||||
initWrapper(Level.class, Level.MAPPING.runtimeClass());
|
||||
initWrapper(MapItemSavedData.class, MapItemSavedData.MAPPING.runtimeClass());
|
||||
initWrapper(SavedData.class, SavedData.MAPPING.runtimeClass());
|
||||
initWrapper(Vec3.class, Vec3.MAPPING.runtimeClass());
|
||||
initWrapper(VoxelShape.class, VoxelShape.MAPPING.runtimeClass());
|
||||
// minecraft
|
||||
initWrapper(DetectedVersion.class, DetectedVersion.MAPPING.runtimeClass());
|
||||
initWrapper(SharedConstants.class, SharedConstants.MAPPING.runtimeClass());
|
||||
initWrapper(WorldVersion.class, WorldVersion.MAPPING.runtimeClass());
|
||||
|
||||
// netty
|
||||
initWrapper(ByteBuf.class, ByteBuf.REFLECT.get());
|
||||
initWrapper(Unpooled.class, Unpooled.REFLECT.get());
|
||||
|
||||
// paper.configuration
|
||||
initWrapper(FallbackValue_Int.class, FallbackValue_Int.REFLECT.get());
|
||||
initWrapper(WorldConfiguration.class, WorldConfiguration.REFLECT.get());
|
||||
initWrapper(WorldConfiguration.Chunks.class, WorldConfiguration.Chunks.REFLECT.get());
|
||||
// paper
|
||||
initWrapper(AABBVoxelShape.class, AABBVoxelShape.REFLECT.get());
|
||||
initWrapper(PaperAdventure.class, PaperAdventure.REFLECT.get());
|
||||
initWrapper(QueuedChangesMapLong2Object.class, QueuedChangesMapLong2Object.REFLECT.get());
|
||||
}
|
||||
|
||||
|
||||
/* package */ static Class<? extends ReflectWrapperI> getWrapperOfRuntimeClass(Class<?> runtime) {
|
||||
RegistryEntry e = WRAPPER_DATA_BY_RUNTIME_CLASS.get(runtime);
|
||||
return e == null ? null : e.wrapperClass;
|
||||
}
|
||||
|
||||
/* package */ static Class<?> getRuntimeClassOfWrapperClass(Class<? extends ReflectWrapperI> wrapperClass) {
|
||||
RegistryEntry e = WRAPPER_DATA_BY_WRAPPER_CLASS.get(wrapperClass);
|
||||
return e == null ? null : e.runtimeClass;
|
||||
}
|
||||
|
||||
/* package */ static ReflectConstructor<? extends ReflectWrapperI> getWrapperConstructorOfWrapperClass(Class<? extends ReflectWrapperI> wrapperClass) {
|
||||
RegistryEntry e = WRAPPER_DATA_BY_WRAPPER_CLASS.get(wrapperClass);
|
||||
return e == null ? null : e.objectWrapperConstructor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static final Map<Class<?>, RegistryEntry> WRAPPER_DATA_BY_RUNTIME_CLASS = new HashMap<>();
|
||||
private static final Map<Class<? extends ReflectWrapperI>, RegistryEntry> WRAPPER_DATA_BY_WRAPPER_CLASS = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void initWrapper(Class<? extends ReflectWrapperI> wrapper, Class<?> runtime) {
|
||||
Class<? extends ReflectWrapperI> concreteWrapper = wrapper;
|
||||
ReflectConstructor<? extends ReflectWrapperI> objectWrapperConstructor;
|
||||
if (wrapper.isInterface() || Modifier.isAbstract(wrapper.getModifiers())) {
|
||||
ConcreteWrapper concreteWrapperAnnotation = wrapper.getAnnotation(ConcreteWrapper.class);
|
||||
if (concreteWrapperAnnotation == null || concreteWrapperAnnotation.value() == null) {
|
||||
Log.severe("The provided non-concrete (interface or abstract class) wrapper " + wrapper + " does not" +
|
||||
" provide any concrete wrapper.");
|
||||
return;
|
||||
}
|
||||
concreteWrapper = concreteWrapperAnnotation.value();
|
||||
if (!wrapper.isAssignableFrom(concreteWrapper)) {
|
||||
Log.severe("The concrete wrapper " + concreteWrapper + " does not extends or implements " + wrapper + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
objectWrapperConstructor = Reflect.ofClass(concreteWrapper).constructor(Object.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.severe("The wrapper " + concreteWrapper + " does not provide a constructor that takes a unique" +
|
||||
" Object parameter.", e);
|
||||
return;
|
||||
}
|
||||
RegistryEntry e = new RegistryEntry(runtime, wrapper, concreteWrapper, objectWrapperConstructor);
|
||||
WRAPPER_DATA_BY_RUNTIME_CLASS.put(runtime, e);
|
||||
WRAPPER_DATA_BY_WRAPPER_CLASS.put(wrapper, e);
|
||||
if (concreteWrapper != wrapper) {
|
||||
WRAPPER_DATA_BY_WRAPPER_CLASS.put(concreteWrapper, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private record RegistryEntry(Class<?> runtimeClass,
|
||||
Class<? extends ReflectWrapperI> wrapperClass,
|
||||
Class<? extends ReflectWrapperI> concreteWrapperClass,
|
||||
ReflectConstructor<? extends ReflectWrapperI> objectWrapperConstructor) {
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.brigadier;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CommandNode<S> extends ReflectWrapperTyped<com.mojang.brigadier.tree.CommandNode<S>> {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = Reflect.ofClass(com.mojang.brigadier.tree.CommandNode.class);
|
||||
private static final Reflect.ReflectMethod<?> removeCommand = wrapEx(() -> REFLECT.method("removeCommand", String.class));
|
||||
|
||||
public void removeCommand(String cmd) {
|
||||
wrapReflectEx(() -> removeCommand.invoke(__getRuntimeInstance(), cmd));
|
||||
}
|
||||
|
||||
protected CommandNode(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.MapItemSavedData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CraftMapView extends ReflectWrapperTyped<MapView> {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("map.CraftMapView"));
|
||||
public static final Reflect.ReflectField<?> worldMap = wrapEx(() -> REFLECT.field("worldMap"));
|
||||
public static final Reflect.ReflectMethod<?> render = wrapEx(() -> REFLECT.method("render", CraftPlayer.REFLECT.get()));
|
||||
|
||||
protected CraftMapView(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public RenderData render(Player player) {
|
||||
return wrap(wrapReflectEx(() -> render.invoke(__getRuntimeInstance(), player)), RenderData.class);
|
||||
}
|
||||
|
||||
public RenderData render(CraftPlayer player) {
|
||||
return render(unwrap(player));
|
||||
}
|
||||
|
||||
public MapItemSavedData worldMap() {
|
||||
return wrap(wrapReflectEx(() -> worldMap.getValue(__getRuntimeInstance())), MapItemSavedData.class);
|
||||
}
|
||||
|
||||
public void worldMap(MapItemSavedData data) {
|
||||
wrapReflectEx(() -> worldMap.setValue(__getRuntimeInstance(), unwrap(data)));
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.resources.ResourceLocation;
|
||||
import org.bukkit.NamespacedKey;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CraftNamespacedKey extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("util.CraftNamespacedKey"));
|
||||
public static final Reflect.ReflectMethod<?> toMinecraft = wrapEx(() -> REFLECT.method("toMinecraft", NamespacedKey.class));
|
||||
public static final Reflect.ReflectMethod<?> fromMinecraft = wrapEx(() -> REFLECT.method("fromMinecraft", ResourceLocation.MAPPING.runtimeClass()));
|
||||
|
||||
public static ResourceLocation toMinecraft(NamespacedKey key) {
|
||||
return wrap(wrapReflectEx(() -> toMinecraft.invokeStatic(key)), ResourceLocation.class);
|
||||
}
|
||||
|
||||
public static NamespacedKey fromMinecraft(ResourceLocation key) {
|
||||
return (NamespacedKey) wrapReflectEx(() -> toMinecraft.invokeStatic(unwrap(key)));
|
||||
}
|
||||
|
||||
protected CraftNamespacedKey(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CraftPlayer extends ReflectWrapperTyped<Player> {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("entity.CraftPlayer"));
|
||||
public static final Reflect.ReflectMethod<?> getHandle = wrapEx(() -> REFLECT.method("getHandle"));
|
||||
|
||||
public ServerPlayer getHandle() {
|
||||
return wrap(wrapReflectEx(() -> getHandle.invoke(__getRuntimeInstance())), ServerPlayer.class);
|
||||
}
|
||||
|
||||
protected CraftPlayer(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.DedicatedPlayerList;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.DedicatedServer;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CraftServer extends ReflectWrapperTyped<Server> {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("CraftServer"));
|
||||
public static final Reflect.ReflectMethod<?> getServer = wrapEx(() -> REFLECT.method("getServer"));
|
||||
public static final Reflect.ReflectMethod<?> getHandle = wrapEx(() -> REFLECT.method("getHandle"));
|
||||
|
||||
public DedicatedServer getServer() {
|
||||
return wrap(wrapReflectEx(() -> getServer.invoke(__getRuntimeInstance())), DedicatedServer.class);
|
||||
}
|
||||
|
||||
public DedicatedPlayerList getHandle() {
|
||||
return wrap(wrapReflectEx(() -> getHandle.invoke(__getRuntimeInstance())), DedicatedPlayerList.class);
|
||||
}
|
||||
|
||||
protected CraftServer(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Vec3;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CraftVector extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("util.CraftVector"));
|
||||
public static final Reflect.ReflectMethod<?> toBukkit_Vec3 = wrapEx(() -> REFLECT.method("toBukkit", Vec3.MAPPING.runtimeClass()));
|
||||
public static final Reflect.ReflectMethod<?> toBukkit_BlockPos = wrapEx(() -> REFLECT.method("toBukkit", BlockPos.MAPPING.runtimeClass()));
|
||||
public static final Reflect.ReflectMethod<?> toNMS = wrapEx(() -> REFLECT.method("toNMS", Vector.class));
|
||||
public static final Reflect.ReflectMethod<?> toBlockPos = wrapEx(() -> REFLECT.method("toNMS", Vector.class));
|
||||
|
||||
public static Vector toBukkit(Vec3 nms) {
|
||||
return (Vector) wrapReflectEx(() -> toBukkit_Vec3.invokeStatic(unwrap(nms)));
|
||||
}
|
||||
|
||||
public static Vector toBukkit(BlockPos blockPos) {
|
||||
return (Vector) wrapReflectEx(() -> toBukkit_BlockPos.invokeStatic(unwrap(blockPos)));
|
||||
}
|
||||
|
||||
public static Vec3 toNMS(Vector bukkit) {
|
||||
return wrap(wrapReflectEx(() -> toNMS.invokeStatic(bukkit)), Vec3.class);
|
||||
}
|
||||
|
||||
public static BlockPos toBlockPos(Vector bukkit) {
|
||||
return wrap(wrapReflectEx(() -> toBlockPos.invokeStatic(bukkit)), BlockPos.class);
|
||||
}
|
||||
|
||||
|
||||
protected CraftVector(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerLevel;
|
||||
import org.bukkit.World;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class CraftWorld extends ReflectWrapperTyped<World> {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("CraftWorld"));
|
||||
public static final Reflect.ReflectMethod<?> getHandle = wrapEx(() -> REFLECT.method("getHandle"));
|
||||
|
||||
public ServerLevel getHandle() {
|
||||
return wrap(wrapReflectEx(() -> getHandle.invoke(__getRuntimeInstance())), ServerLevel.class);
|
||||
}
|
||||
|
||||
protected CraftWorld(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class RenderData extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("map.RenderData"));
|
||||
private static final Reflect.ReflectField<?> buffer = wrapEx(() -> REFLECT.field("buffer"));
|
||||
|
||||
protected RenderData(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public byte[] buffer() {
|
||||
return (byte[]) wrapReflectEx(() -> buffer.getValue(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public void buffer(byte[] buff) {
|
||||
wrapReflectEx(() -> buffer.setValue(__getRuntimeInstance(), buff));
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.OBCReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Commands;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.defaults.BukkitCommand;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class VanillaCommandWrapper extends ReflectWrapperTyped<BukkitCommand> {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("command.VanillaCommandWrapper"));
|
||||
public static final Reflect.ReflectConstructor<?> CONSTRUTOR = wrapEx(() -> REFLECT.constructor(Commands.MAPPING.runtimeClass(), CommandNode.class));
|
||||
public static final Reflect.ReflectField<?> vanillaCommand = wrapEx(() -> REFLECT.field("vanillaCommand"));
|
||||
public static final Reflect.ReflectMethod<?> getListener = wrapEx(() -> REFLECT.method("getListener", CommandSender.class));
|
||||
|
||||
public VanillaCommandWrapper(Commands dispatcher, CommandNode<BukkitBrigadierCommandSource> vanillaCommand) {
|
||||
this(wrapReflectEx(() -> CONSTRUTOR.instanciate(unwrap(dispatcher), vanillaCommand)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public CommandNode<BukkitBrigadierCommandSource> vanillaCommand() {
|
||||
return (CommandNode<BukkitBrigadierCommandSource>) wrapReflectEx(() -> vanillaCommand.getValue(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public static BukkitBrigadierCommandSource getListener(CommandSender sender) {
|
||||
return (BukkitBrigadierCommandSource) wrapReflectEx(() -> getListener.invokeStatic(sender));
|
||||
}
|
||||
|
||||
protected VanillaCommandWrapper(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class DetectedVersion extends ReflectWrapper implements WorldVersion {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.DetectedVersion"));
|
||||
|
||||
protected DetectedVersion(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class SharedConstants extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.SharedConstants"));
|
||||
private static final Reflect.ReflectMethod<?> getCurrentVersion = wrapEx(() -> MAPPING.mojMethod("getCurrentVersion"));
|
||||
private static final Reflect.ReflectMethod<?> getProtocolVersion = wrapEx(() -> MAPPING.mojMethod("getProtocolVersion"));
|
||||
|
||||
|
||||
|
||||
public static WorldVersion getCurrentVersion() {
|
||||
return wrap(wrapReflectEx(() -> getCurrentVersion.invokeStatic()), WorldVersion.class);
|
||||
}
|
||||
|
||||
public static int getProtocolVersion() {
|
||||
return (int) wrapReflectEx(() -> getProtocolVersion.invokeStatic());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected SharedConstants(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ConcreteWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperI;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
@ConcreteWrapper(WorldVersion.__concrete.class)
|
||||
public interface WorldVersion extends ReflectWrapperI {
|
||||
ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.WorldVersion"));
|
||||
|
||||
|
||||
|
||||
class __concrete extends ReflectWrapper implements WorldVersion {
|
||||
private __concrete(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class BlockPosArgument extends ReflectWrapperTyped<ArgumentType<?>> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.BlockPosArgument"));
|
||||
private static final Reflect.ReflectMethod<?> blockPos = wrapEx(() -> MAPPING.mojMethod("blockPos"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> blockPos() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> blockPos.invokeStatic());
|
||||
}
|
||||
|
||||
protected BlockPosArgument(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class CommandSourceStack extends ReflectWrapperTyped<BukkitBrigadierCommandSource> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.CommandSourceStack"));
|
||||
|
||||
protected CommandSourceStack(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Commands extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.Commands"));
|
||||
public static final Reflect.ReflectField<?> dispatcher = wrapEx(() -> MAPPING.mojField("dispatcher"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public CommandDispatcher<BukkitBrigadierCommandSource> dispatcher() {
|
||||
return (CommandDispatcher<BukkitBrigadierCommandSource>) wrapReflectEx(() -> dispatcher.getValue(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
protected Commands(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ComponentArgument extends ReflectWrapperTyped<ArgumentType<?>> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.ComponentArgument"));
|
||||
private static final Reflect.ReflectMethod<?> textComponent = wrapEx(() -> MAPPING.mojMethod("textComponent"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> textComponent() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> textComponent.invokeStatic());
|
||||
}
|
||||
|
||||
protected ComponentArgument(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ConcreteWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperI;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Vec3;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
import static fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper.wrap;
|
||||
|
||||
@ConcreteWrapper(Coordinates.__concrete.class)
|
||||
public interface Coordinates extends ReflectWrapperI {
|
||||
NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.Coordinates"));
|
||||
Reflect.ReflectMethod<?> getPosition = wrapEx(() -> MAPPING.mojMethod("getPosition", CommandSourceStack.MAPPING));
|
||||
Reflect.ReflectMethod<?> getBlockPos = wrapEx(() -> MAPPING.mojMethod("getBlockPos", CommandSourceStack.MAPPING));
|
||||
|
||||
default Vec3 getPosition(BukkitBrigadierCommandSource source) {
|
||||
return wrap(wrapReflectEx(() -> getPosition.invoke(__getRuntimeInstance(), source)), Vec3.class);
|
||||
}
|
||||
|
||||
default BlockPos getBlockPos(BukkitBrigadierCommandSource source) {
|
||||
return wrap(wrapReflectEx(() -> getBlockPos.invoke(__getRuntimeInstance(), source)), BlockPos.class);
|
||||
}
|
||||
|
||||
class __concrete extends ReflectWrapper implements Coordinates {
|
||||
protected __concrete(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class EntityArgument extends ReflectWrapperTyped<ArgumentType<?>> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.EntityArgument"));
|
||||
private static final Reflect.ReflectMethod<?> entity = wrapEx(() -> MAPPING.mojMethod("entity"));
|
||||
private static final Reflect.ReflectMethod<?> entities = wrapEx(() -> MAPPING.mojMethod("entities"));
|
||||
private static final Reflect.ReflectMethod<?> player = wrapEx(() -> MAPPING.mojMethod("player"));
|
||||
private static final Reflect.ReflectMethod<?> players = wrapEx(() -> MAPPING.mojMethod("players"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> entity() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> entity.invokeStatic());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> entities() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> entities.invokeStatic());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> player() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> player.invokeStatic());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> players() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> players.invokeStatic());
|
||||
}
|
||||
|
||||
|
||||
protected EntityArgument(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectListWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class EntitySelector extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.selector.EntitySelector"));
|
||||
private static final Reflect.ReflectMethod<?> findEntities = wrapEx(() -> MAPPING.mojMethod("findEntities", CommandSourceStack.MAPPING));
|
||||
private static final Reflect.ReflectMethod<?> findPlayers = wrapEx(() -> MAPPING.mojMethod("findPlayers", CommandSourceStack.MAPPING));
|
||||
private static final Reflect.ReflectMethod<?> findSingleEntity = wrapEx(() -> MAPPING.mojMethod("findSingleEntity", CommandSourceStack.MAPPING));
|
||||
private static final Reflect.ReflectMethod<?> findSinglePlayer = wrapEx(() -> MAPPING.mojMethod("findSinglePlayer", CommandSourceStack.MAPPING));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ReflectListWrapper<Entity> findEntities(BukkitBrigadierCommandSource source) {
|
||||
return wrapList((List<Object>) wrapReflectEx(() -> findEntities.invoke(__getRuntimeInstance(), source)), Entity.class);
|
||||
}
|
||||
|
||||
public Entity findSingleEntity(BukkitBrigadierCommandSource source) {
|
||||
return wrap(wrapReflectEx(() -> findSingleEntity.invoke(__getRuntimeInstance(), source)), Entity.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ReflectListWrapper<ServerPlayer> findPlayers(BukkitBrigadierCommandSource source) {
|
||||
return wrapList((List<Object>) wrapReflectEx(() -> findPlayers.invoke(__getRuntimeInstance(), source)), ServerPlayer.class);
|
||||
}
|
||||
|
||||
public ServerPlayer findSinglePlayer(BukkitBrigadierCommandSource source) {
|
||||
return wrap(wrapReflectEx(() -> findSinglePlayer.invoke(__getRuntimeInstance(), source)), ServerPlayer.class);
|
||||
}
|
||||
|
||||
|
||||
protected EntitySelector(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class GameProfileArgument extends ReflectWrapperTyped<ArgumentType<?>> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.GameProfileArgument"));
|
||||
private static final Reflect.ReflectMethod<?> gameProfile = wrapEx(() -> MAPPING.mojMethod("gameProfile"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> gameProfile() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> gameProfile.invokeStatic());
|
||||
}
|
||||
|
||||
protected GameProfileArgument(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ResourceLocationArgument extends ReflectWrapperTyped<ArgumentType<?>> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.ResourceLocationArgument"));
|
||||
private static final Reflect.ReflectMethod<?> id = wrapEx(() -> MAPPING.mojMethod("id"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> id() {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> id.invokeStatic());
|
||||
}
|
||||
|
||||
protected ResourceLocationArgument(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperTyped;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Vec3Argument extends ReflectWrapperTyped<ArgumentType<?>> {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.Vec3Argument"));
|
||||
private static final Reflect.ReflectMethod<?> vec3 = wrapEx(() -> MAPPING.mojMethod("vec3", boolean.class));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArgumentType<Object> vec3(boolean centerIntegers) {
|
||||
return (ArgumentType<Object>) wrapReflectEx(() -> vec3.invokeStatic(centerIntegers));
|
||||
}
|
||||
|
||||
|
||||
protected Vec3Argument(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.core;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class BlockPos extends Vec3i {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.core.BlockPos"));
|
||||
|
||||
protected BlockPos(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.core;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Vec3i extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.core.Vec3i"));
|
||||
public static final Reflect.ReflectMethod<?> getX = wrapEx(() -> MAPPING.mojMethod("getX"));
|
||||
public static final Reflect.ReflectMethod<?> getY = wrapEx(() -> MAPPING.mojMethod("getY"));
|
||||
public static final Reflect.ReflectMethod<?> getZ = wrapEx(() -> MAPPING.mojMethod("getZ"));
|
||||
|
||||
public int getX() {
|
||||
return (int) wrapReflectEx(() -> getX.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return (int) wrapReflectEx(() -> getY.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return (int) wrapReflectEx(() -> getZ.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
protected Vec3i(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,160 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectMethod;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
public class CompoundTag extends ReflectWrapper implements Tag {
|
||||
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.nbt.CompoundTag"));
|
||||
private static final ReflectMethod<?> putBoolean = wrapEx(() -> MAPPING.mojMethod("putBoolean", String.class, boolean.class));
|
||||
private static final ReflectMethod<?> putByte = wrapEx(() -> MAPPING.mojMethod("putByte", String.class, byte.class));
|
||||
private static final ReflectMethod<?> putByteArray = wrapEx(() -> MAPPING.mojMethod("putByteArray", String.class, byte[].class));
|
||||
private static final ReflectMethod<?> putByteArray_List = wrapEx(() -> MAPPING.mojMethod("putByteArray", String.class, List.class));
|
||||
private static final ReflectMethod<?> putDouble = wrapEx(() -> MAPPING.mojMethod("putDouble", String.class, double.class));
|
||||
private static final ReflectMethod<?> putFloat = wrapEx(() -> MAPPING.mojMethod("putFloat", String.class, float.class));
|
||||
private static final ReflectMethod<?> putInt = wrapEx(() -> MAPPING.mojMethod("putInt", String.class, int.class));
|
||||
private static final ReflectMethod<?> putIntArray = wrapEx(() -> MAPPING.mojMethod("putIntArray", String.class, int[].class));
|
||||
private static final ReflectMethod<?> putIntArray_List = wrapEx(() -> MAPPING.mojMethod("putIntArray", String.class, List.class));
|
||||
private static final ReflectMethod<?> putString = wrapEx(() -> MAPPING.mojMethod("putString", String.class, String.class));
|
||||
private static final ReflectMethod<?> putUUID = wrapEx(() -> MAPPING.mojMethod("putUUID", String.class, UUID.class));
|
||||
private static final ReflectMethod<?> putLong = wrapEx(() -> MAPPING.mojMethod("putLong", String.class, long.class));
|
||||
private static final ReflectMethod<?> putLongArray = wrapEx(() -> MAPPING.mojMethod("putLongArray", String.class, long[].class));
|
||||
private static final ReflectMethod<?> putLongArray_List = wrapEx(() -> MAPPING.mojMethod("putLongArray", String.class, List.class));
|
||||
private static final ReflectMethod<?> putShort = wrapEx(() -> MAPPING.mojMethod("putShort", String.class, short.class));
|
||||
private static final ReflectMethod<?> put = wrapEx(() -> MAPPING.mojMethod("put", String.class, Tag.MAPPING));
|
||||
|
||||
private static final ReflectMethod<?> getTagType = wrapEx(() -> MAPPING.mojMethod("getTagType", String.class));
|
||||
private static final ReflectMethod<?> getByte = wrapEx(() -> MAPPING.mojMethod("getByte", String.class));
|
||||
private static final ReflectMethod<?> getShort = wrapEx(() -> MAPPING.mojMethod("getShort", String.class));
|
||||
private static final ReflectMethod<?> getInt = wrapEx(() -> MAPPING.mojMethod("getInt", String.class));
|
||||
private static final ReflectMethod<?> getLong = wrapEx(() -> MAPPING.mojMethod("getLong", String.class));
|
||||
private static final ReflectMethod<?> getFloat = wrapEx(() -> MAPPING.mojMethod("getFloat", String.class));
|
||||
private static final ReflectMethod<?> getDouble = wrapEx(() -> MAPPING.mojMethod("getDouble", String.class));
|
||||
private static final ReflectMethod<?> getString = wrapEx(() -> MAPPING.mojMethod("getString", String.class));
|
||||
private static final ReflectMethod<?> getByteArray = wrapEx(() -> MAPPING.mojMethod("getByteArray", String.class));
|
||||
private static final ReflectMethod<?> getIntArray = wrapEx(() -> MAPPING.mojMethod("getIntArray", String.class));
|
||||
private static final ReflectMethod<?> getLongArray = wrapEx(() -> MAPPING.mojMethod("getLongArray", String.class));
|
||||
private static final ReflectMethod<?> getCompound = wrapEx(() -> MAPPING.mojMethod("getCompound", String.class));
|
||||
private static final ReflectMethod<?> getBoolean = wrapEx(() -> MAPPING.mojMethod("getBoolean", String.class));
|
||||
|
||||
private static final ReflectMethod<?> get = wrapEx(() -> MAPPING.mojMethod("get", String.class));
|
||||
private static final ReflectMethod<?> getAllKeys = wrapEx(() -> MAPPING.mojMethod("getAllKeys"));
|
||||
private static final ReflectMethod<?> entries = wrapEx(() -> MAPPING.mojMethod("entries"));
|
||||
private static final ReflectMethod<?> size = wrapEx(() -> MAPPING.mojMethod("size"));
|
||||
private static final ReflectMethod<?> contains = wrapEx(() -> MAPPING.mojMethod("contains", String.class));
|
||||
|
||||
public CompoundTag(Object nms) {
|
||||
super(nms);
|
||||
}
|
||||
|
||||
public void putBoolean(String key, boolean value) {
|
||||
wrapReflectEx(() -> putBoolean.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putByte(String key, byte value) {
|
||||
wrapReflectEx(() -> putByte.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putByteArray(String key, byte[] value) {
|
||||
wrapReflectEx(() -> putByteArray.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putDouble(String key, double value) {
|
||||
wrapReflectEx(() -> putDouble.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putFloat(String key, float value) {
|
||||
wrapReflectEx(() -> putFloat.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putInt(String key, int value) {
|
||||
wrapReflectEx(() -> putInt.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putIntArray(String key, int[] value) {
|
||||
wrapReflectEx(() -> putIntArray.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putString(String key, String value) {
|
||||
wrapReflectEx(() -> putString.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putUUID(String key, UUID value) {
|
||||
wrapReflectEx(() -> putUUID.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putLong(String key, long value) {
|
||||
wrapReflectEx(() -> putLong.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putLongArray(String key, long[] value) {
|
||||
wrapReflectEx(() -> putLongArray.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void putShort(String key, short value) {
|
||||
wrapReflectEx(() -> putShort.invoke(__getRuntimeInstance(), key, value));
|
||||
}
|
||||
public void put(String key, Tag value) {
|
||||
wrapReflectEx(() -> put.invoke(__getRuntimeInstance(), key, unwrap(value)));
|
||||
}
|
||||
public byte getTagType(String key) {
|
||||
return (byte) wrapReflectEx(() -> getTagType.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public byte getByte(String key) {
|
||||
return (byte) wrapReflectEx(() -> getByte.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public short getShort(String key) {
|
||||
return (short) wrapReflectEx(() -> getShort.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public int getInt(String key) {
|
||||
return (int) wrapReflectEx(() -> getInt.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public long getLong(String key) {
|
||||
return (long) wrapReflectEx(() -> getLong.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public float getFloat(String key) {
|
||||
return (float) wrapReflectEx(() -> getFloat.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public double getDouble(String key) {
|
||||
return (double) wrapReflectEx(() -> getDouble.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public String getString(String key) {
|
||||
return (String) wrapReflectEx(() -> getString.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public byte[] getByteArray(String key) {
|
||||
return (byte[]) wrapReflectEx(() -> getByteArray.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public int[] getIntArray(String key) {
|
||||
return (int[]) wrapReflectEx(() -> getIntArray.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public long[] getLongArray(String key) {
|
||||
return (long[]) wrapReflectEx(() -> getLongArray.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public CompoundTag getCompound(String key) {
|
||||
return wrap(wrapReflectEx(() -> getCompound.invoke(__getRuntimeInstance(), key)), CompoundTag.class);
|
||||
}
|
||||
public boolean getBoolean(String key) {
|
||||
return (boolean) wrapReflectEx(() -> getBoolean.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
public Tag get(String key) {
|
||||
return wrap(wrapReflectEx(() -> get.invoke(__getRuntimeInstance(), key)), Tag.class);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> getAllKeys() {
|
||||
return (Set<String>) wrapReflectEx(() -> getAllKeys.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The values in the returned Map are not wrapped.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, ?> entries() {
|
||||
// we cannot easily wrap every value of the map without being able to synch the returned map with the wrapped map
|
||||
return (Map<String, ?>) wrapReflectEx(() -> entries.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
public int size() {
|
||||
return (int) wrapReflectEx(() -> size.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
public boolean contains(String key) {
|
||||
return (boolean) wrapReflectEx(() -> contains.invoke(__getRuntimeInstance(), key));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectMethod;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
public class NbtIo extends ReflectWrapper {
|
||||
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.nbt.NbtIo"));
|
||||
private static final ReflectMethod<?> readCompressed = wrapEx(() -> MAPPING.mojMethod("readCompressed", File.class));
|
||||
private static final ReflectMethod<?> writeCompressed = wrapEx(() -> MAPPING.mojMethod("writeCompressed", CompoundTag.MAPPING, File.class));
|
||||
|
||||
private NbtIo(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static CompoundTag readCompressed(File f) {
|
||||
return new CompoundTag(wrapEx(() -> readCompressed.invokeStatic(f)));
|
||||
}
|
||||
public static void writeCompressed(CompoundTag tag, File f) {
|
||||
Object nmsTag = ReflectWrapper.unwrap(tag);
|
||||
wrapEx(() -> writeCompressed.invokeStatic(nmsTag, f));
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
public class StringTag extends ReflectWrapper implements Tag {
|
||||
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.nbt.StringTag"));
|
||||
|
||||
|
||||
public StringTag(Object nms) {
|
||||
super(nms);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect.ReflectMethod;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ConcreteWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperI;
|
||||
|
||||
@ConcreteWrapper(Tag.__concrete.class)
|
||||
public interface Tag extends ReflectWrapperI {
|
||||
ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.nbt.Tag"));
|
||||
ReflectMethod<?> getAsString = wrapEx(() -> MAPPING.mojMethod("getAsString"));
|
||||
|
||||
|
||||
default String getAsString() {
|
||||
return wrapReflectEx(() -> (String) getAsString.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
class __concrete extends ReflectWrapper implements Tag {
|
||||
private __concrete(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.network;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.netty.ByteBuf;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class FriendlyByteBuf extends ByteBuf {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.FriendlyByteBuf"));
|
||||
private static final Reflect.ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(ByteBuf.REFLECT.get()));
|
||||
private static final Reflect.ReflectMethod<?> writeUtf = wrapEx(() -> MAPPING.mojMethod("writeUtf", String.class));
|
||||
|
||||
public FriendlyByteBuf(ByteBuf parent) {
|
||||
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(parent))));
|
||||
}
|
||||
|
||||
public FriendlyByteBuf writeUtf(String string) {
|
||||
return wrap(wrapReflectEx(() -> writeUtf.invoke(__getRuntimeInstance(), string)), FriendlyByteBuf.class);
|
||||
}
|
||||
|
||||
protected FriendlyByteBuf(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ConcreteWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperI;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
@ConcreteWrapper(Component.__concrete.class)
|
||||
public interface Component extends ReflectWrapperI {
|
||||
NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.chat.Component"));
|
||||
|
||||
|
||||
class __concrete extends ReflectWrapper implements Component {
|
||||
protected __concrete(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.FriendlyByteBuf;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.resources.ResourceLocation;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ClientboundCustomPayloadPacket extends ReflectWrapper implements Packet {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket"));
|
||||
private static final Reflect.ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(ResourceLocation.MAPPING.runtimeClass(), FriendlyByteBuf.MAPPING.runtimeClass()));
|
||||
private static final Reflect.ReflectField<?> FIELD_BRAND = wrapEx(() -> MAPPING.mojField("BRAND"));
|
||||
|
||||
public static ResourceLocation BRAND() {
|
||||
return wrap(wrapReflectEx(FIELD_BRAND::getStaticValue), ResourceLocation.class);
|
||||
}
|
||||
|
||||
protected ClientboundCustomPayloadPacket(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public ClientboundCustomPayloadPacket(ResourceLocation res, FriendlyByteBuf buff) {
|
||||
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(res), unwrap(buff))));
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ClientboundGameEventPacket extends ReflectWrapper implements Packet {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.protocol.game.ClientboundGameEventPacket"));
|
||||
private static final Reflect.ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(Type.MAPPING.runtimeClass(), float.class));
|
||||
private static final Reflect.ReflectField<?> FIELD_RAIN_LEVEL_CHANGE = wrapEx(() -> MAPPING.mojField("RAIN_LEVEL_CHANGE"));
|
||||
private static final Reflect.ReflectField<?> FIELD_THUNDER_LEVEL_CHANGE = wrapEx(() -> MAPPING.mojField("THUNDER_LEVEL_CHANGE"));
|
||||
|
||||
public static Type RAIN_LEVEL_CHANGE() {
|
||||
return wrap(wrapReflectEx(FIELD_RAIN_LEVEL_CHANGE::getStaticValue), Type.class);
|
||||
}
|
||||
public static Type THUNDER_LEVEL_CHANGE() {
|
||||
return wrap(wrapReflectEx(FIELD_THUNDER_LEVEL_CHANGE::getStaticValue), Type.class);
|
||||
}
|
||||
|
||||
public ClientboundGameEventPacket(Type type, float value) {
|
||||
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(type), value)));
|
||||
}
|
||||
|
||||
protected ClientboundGameEventPacket(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
|
||||
public static class Type extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.protocol.game.ClientboundGameEventPacket$Type"));
|
||||
|
||||
protected Type(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ConcreteWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperI;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
@ConcreteWrapper(Packet.__concrete.class)
|
||||
public interface Packet extends ReflectWrapperI {
|
||||
NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.protocol.Packet"));
|
||||
|
||||
class __concrete extends ReflectWrapper implements Packet {
|
||||
protected __concrete(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.resources;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class ResourceLocation extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.resources.ResourceLocation"));
|
||||
|
||||
|
||||
protected ResourceLocation(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ChunkStorage;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.QueuedChangesMapLong2Object;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ChunkMap extends ChunkStorage {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.level.ChunkMap"));
|
||||
private static final Reflect.ReflectField<?> FIELD_autoSaveQueue = wrapEx(() -> MAPPING.runtimeReflect().field("autoSaveQueue")); // spigot/paper field
|
||||
public static final Reflect.ReflectField<?> FIELD_level = wrapEx(() -> MAPPING.mojField("level"));
|
||||
public static final Reflect.ReflectField<?> FIELD_pendingUnloads = wrapEx(() -> MAPPING.mojField("pendingUnloads"));
|
||||
public static final Reflect.ReflectField<?> FIELD_toDrop = wrapEx(() -> MAPPING.mojField("toDrop"));
|
||||
public static final Reflect.ReflectField<?> FIELD_updatingChunks = wrapEx(() -> MAPPING.runtimeReflect().field("updatingChunks")); // spigot/paper field
|
||||
|
||||
/** This field in unmapped */
|
||||
public final ObjectRBTreeSet<?> autoSaveQueue;
|
||||
public final ServerLevel level;
|
||||
/** This field in unmapped */
|
||||
public final Long2ObjectLinkedOpenHashMap<?> pendingUnloads;
|
||||
/** This field in unmapped */
|
||||
public final LongSet toDrop;
|
||||
public final QueuedChangesMapLong2Object updatingChunks;
|
||||
|
||||
protected ChunkMap(Object obj) {
|
||||
super(obj);
|
||||
|
||||
autoSaveQueue = (ObjectRBTreeSet<?>) wrapReflectEx(() -> FIELD_autoSaveQueue.getValue(obj));
|
||||
level = wrap(wrapReflectEx(() -> FIELD_level.getValue(obj)), ServerLevel.class);
|
||||
pendingUnloads = (Long2ObjectLinkedOpenHashMap<?>) wrapReflectEx(() -> FIELD_pendingUnloads.getValue(obj));
|
||||
toDrop = (LongSet) wrapReflectEx(() -> FIELD_toDrop.getValue(obj));
|
||||
updatingChunks = wrap(wrapReflectEx(() -> FIELD_updatingChunks.getValue(obj)), QueuedChangesMapLong2Object.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class DedicatedPlayerList extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.dedicated.DedicatedPlayerList"));
|
||||
|
||||
protected DedicatedPlayerList(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class DedicatedServer extends MinecraftServer {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.dedicated.DedicatedServer"));
|
||||
private static final Reflect.ReflectMethod<?> getLevelIdName = wrapEx(() -> MAPPING.mojMethod("getLevelIdName"));
|
||||
private static final Reflect.ReflectMethod<?> getProperties = wrapEx(() -> MAPPING.mojMethod("getProperties"));
|
||||
|
||||
public String getLevelIdName() {
|
||||
return (String) wrapReflectEx(() -> getLevelIdName.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public DedicatedServerProperties getProperties() {
|
||||
return wrap(wrapReflectEx(() -> getProperties.invoke(__getRuntimeInstance())), DedicatedServerProperties.class);
|
||||
}
|
||||
|
||||
protected DedicatedServer(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class DedicatedServerProperties extends Settings {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.dedicated.DedicatedServerProperties"));
|
||||
|
||||
protected DedicatedServerProperties(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Commands;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class MinecraftServer extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.MinecraftServer"));
|
||||
private static final Reflect.ReflectField<?> vanillaCommandDispatcher = wrapEx(() -> MAPPING.runtimeReflect().field("vanillaCommandDispatcher"));
|
||||
|
||||
public Commands vanillaCommandDispatcher() {
|
||||
return wrap(wrapReflectEx(() -> vanillaCommandDispatcher.getValue(__getRuntimeInstance())), Commands.class);
|
||||
}
|
||||
|
||||
protected MinecraftServer(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ServerChunkCache extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.level.ServerChunkCache"));
|
||||
private static final Reflect.ReflectField<?> FIELD_chunkMap = wrapEx(() -> MAPPING.mojField("chunkMap"));
|
||||
|
||||
public final ChunkMap chunkMap;
|
||||
|
||||
protected ServerChunkCache(Object obj) {
|
||||
super(obj);
|
||||
|
||||
chunkMap = wrap(wrapReflectEx(() -> FIELD_chunkMap.getValue(obj)));
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol.Packet;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ServerGamePacketListenerImpl extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.network.ServerGamePacketListenerImpl"));
|
||||
public static final Reflect.ReflectMethod<?> send = wrapEx(() -> MAPPING.mojMethod("send", Packet.MAPPING));
|
||||
|
||||
public void send(Packet packet) {
|
||||
wrapReflectEx(() -> send.invoke(__getRuntimeInstance(), unwrap(packet)));
|
||||
}
|
||||
|
||||
protected ServerGamePacketListenerImpl(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.util.ProgressListener;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Level;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ServerLevel extends Level {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.level.ServerLevel"));
|
||||
public static final Reflect.ReflectMethod<?> save = wrapEx(() -> MAPPING.mojMethod("save", ProgressListener.MAPPING, boolean.class, boolean.class));
|
||||
public static final Reflect.ReflectMethod<?> getChunkSource = wrapEx(() -> MAPPING.mojMethod("getChunkSource"));
|
||||
|
||||
|
||||
public ServerChunkCache getChunkSource() {
|
||||
return wrap(wrapReflectEx(() -> getChunkSource.invoke(__getRuntimeInstance())), ServerChunkCache.class);
|
||||
}
|
||||
|
||||
public void save(ProgressListener listener, boolean flush, boolean savingDisabled) {
|
||||
wrapReflectEx(() -> save.invoke(__getRuntimeInstance(), unwrap(listener), flush, savingDisabled));
|
||||
}
|
||||
|
||||
|
||||
protected ServerLevel(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.DamageSource;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ServerPlayer extends Entity { // in NMS, ServerPlayer is not a direct subclass of Entity
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.level.ServerPlayer"));
|
||||
public static final Reflect.ReflectField<?> connection = wrapEx(() -> MAPPING.mojField("connection"));
|
||||
public static final Reflect.ReflectMethod<?> hurt = wrapEx(() -> MAPPING.mojMethod("hurt", DamageSource.MAPPING, float.class));
|
||||
public static final Reflect.ReflectMethod<?> isTextFilteringEnabled = wrapEx(() -> MAPPING.mojMethod("isTextFilteringEnabled"));
|
||||
public static final Reflect.ReflectMethod<?> allowsListing = wrapEx(() -> MAPPING.mojMethod("allowsListing"));
|
||||
|
||||
public boolean hurt(DamageSource source, float amount) {
|
||||
return (boolean) wrapReflectEx(() -> hurt.invoke(__getRuntimeInstance(), unwrap(source), amount));
|
||||
}
|
||||
|
||||
public boolean isTextFilteringEnabled() {
|
||||
return (boolean) wrapReflectEx(() -> isTextFilteringEnabled.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public boolean allowsListing() {
|
||||
return (boolean) wrapReflectEx(() -> allowsListing.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public ServerGamePacketListenerImpl connection() {
|
||||
return wrap(wrapReflectEx(() -> connection.getValue(__getRuntimeInstance())), ServerGamePacketListenerImpl.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getBukkitEntity() {
|
||||
return (Player) super.getBukkitEntity();
|
||||
}
|
||||
|
||||
protected ServerPlayer(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Settings extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.dedicated.Settings"));
|
||||
public static final Reflect.ReflectField<?> properties = wrapEx(() -> MAPPING.mojField("properties"));
|
||||
|
||||
public Properties properties() {
|
||||
return (Properties) wrapReflectEx(() -> properties.getValue(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
protected Settings(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.util;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ConcreteWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapperI;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
@ConcreteWrapper(ProgressListener.__concrete.class)
|
||||
public interface ProgressListener extends ReflectWrapperI {
|
||||
NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.util.ProgressListener"));
|
||||
|
||||
|
||||
class __concrete extends ReflectWrapper implements ProgressListener {
|
||||
protected __concrete(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class AABB extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.phys.AABB"));
|
||||
private static final Reflect.ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(double.class, double.class, double.class, double.class, double.class, double.class));
|
||||
|
||||
public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(x1, y1, z1, x2, y2, z2)));
|
||||
}
|
||||
|
||||
protected AABB(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ChunkPos extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.level.ChunkPos"));
|
||||
public static final Reflect.ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(int.class, int.class));
|
||||
|
||||
public ChunkPos(int x, int z) {
|
||||
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(x, z)));
|
||||
}
|
||||
|
||||
protected ChunkPos(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class ChunkStorage extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.level.chunk.storage.ChunkStorage"));
|
||||
private static final Reflect.ReflectMethod<?> read = wrapEx(() -> MAPPING.mojMethod("read", ChunkPos.MAPPING));
|
||||
private static final Reflect.ReflectMethod<?> readSync = wrapEx(() -> MAPPING.runtimeReflect().method("readSync", ChunkPos.MAPPING.runtimeReflect().get())); // spigot/paper method
|
||||
|
||||
public CompoundTag readSync(ChunkPos pos) {
|
||||
return wrap(wrapReflectEx(() -> readSync.invoke(__getRuntimeInstance(), unwrap(pos))), CompoundTag.class);
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<CompoundTag>> read(ChunkPos pos) {
|
||||
@SuppressWarnings("unchecked")
|
||||
CompletableFuture<Optional<?>> nmsFuture = (CompletableFuture<Optional<?>>) wrapReflectEx(() -> readSync.invoke(__getRuntimeInstance(), unwrap(pos)));
|
||||
return nmsFuture.thenApply(o -> o.map(c -> wrap(c, CompoundTag.class)));
|
||||
}
|
||||
|
||||
protected ChunkStorage(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class DamageSource extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.damagesource.DamageSource"));
|
||||
private static final Reflect.ReflectField<?> FIELD_OUT_OF_WORLD = wrapEx(() -> MAPPING.mojField("OUT_OF_WORLD"));
|
||||
|
||||
public static DamageSource OUT_OF_WORLD() {
|
||||
return wrap(wrapReflectEx(FIELD_OUT_OF_WORLD::getStaticValue), DamageSource.class);
|
||||
}
|
||||
|
||||
protected DamageSource(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Entity extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.entity.Entity"));
|
||||
public static final Reflect.ReflectMethod<?> getBukkitEntity = wrapEx(() -> MAPPING.runtimeReflect().method("getBukkitEntity")); // spigot field
|
||||
|
||||
public org.bukkit.entity.Entity getBukkitEntity() {
|
||||
return (org.bukkit.entity.Entity) wrapReflectEx(() -> getBukkitEntity.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
protected Entity(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.paper.configuration.WorldConfiguration;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Level extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.level.Level"));
|
||||
public static final Reflect.ReflectMethod<?> getGameTime = wrapEx(() -> MAPPING.mojMethod("getGameTime"));
|
||||
public static final Reflect.ReflectMethod<?> getFreeMapId = wrapEx(() -> MAPPING.mojMethod("getFreeMapId"));
|
||||
public static final Reflect.ReflectMethod<?> paperConfig = wrapEx(() -> MAPPING.runtimeReflect().method("paperConfig")); // paper method
|
||||
|
||||
public long getGameTime() {
|
||||
return (long) wrapReflectEx(() -> getGameTime.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public int getFreeMapId() {
|
||||
return (int) wrapReflectEx(() -> getFreeMapId.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public WorldConfiguration paperConfig() {
|
||||
return wrap(wrapReflectEx(() -> paperConfig.invoke(__getRuntimeInstance())), WorldConfiguration.class);
|
||||
}
|
||||
|
||||
protected Level(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class MapItemSavedData extends SavedData {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.level.saveddata.maps.MapItemSavedData"));
|
||||
public static final Reflect.ReflectField<?> colors = wrapEx(() -> MAPPING.mojField("colors"));
|
||||
public static final Reflect.ReflectField<?> locked = wrapEx(() -> MAPPING.mojField("locked"));
|
||||
|
||||
protected MapItemSavedData(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public boolean locked() {
|
||||
return (boolean) wrapReflectEx(() -> locked.getValue(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public void locked(boolean l) {
|
||||
wrapReflectEx(() -> locked.setValue(__getRuntimeInstance(), l));
|
||||
}
|
||||
|
||||
public byte[] colors() {
|
||||
return (byte[]) wrapReflectEx(() -> colors.getValue(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
public void colors(byte[] c) {
|
||||
wrapReflectEx(() -> colors.setValue(__getRuntimeInstance(), c));
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class SavedData extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.level.saveddata.SavedData"));
|
||||
private static final Reflect.ReflectMethod<?> setDirty = wrapEx(() -> MAPPING.mojMethod("setDirty"));
|
||||
|
||||
protected SavedData(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public void setDirty() {
|
||||
wrapReflectEx(() -> setDirty.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class Vec3 extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.phys.Vec3"));
|
||||
|
||||
protected Vec3(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
|
||||
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class VoxelShape extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.phys.shapes.VoxelShape"));
|
||||
|
||||
protected VoxelShape(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.block;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.NMSReflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.VoxelShape;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class BambooBlock extends ReflectWrapper {
|
||||
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.level.block.BambooBlock"));
|
||||
public static final Reflect.ReflectField<?> COLLISION_SHAPE = wrapEx(() -> MAPPING.mojField("COLLISION_SHAPE"));
|
||||
|
||||
public static VoxelShape COLLISION_SHAPE() {
|
||||
return wrap(wrapReflectEx(COLLISION_SHAPE::getStaticValue), VoxelShape.class);
|
||||
}
|
||||
|
||||
public static void COLLISION_SHAPE(VoxelShape shape) {
|
||||
wrapReflectEx(() -> COLLISION_SHAPE.setStaticValue(unwrap(shape)));
|
||||
}
|
||||
|
||||
protected BambooBlock(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.netty;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
|
||||
public class ByteBuf extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.netty.buffer.ByteBuf"));
|
||||
|
||||
protected ByteBuf(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.netty;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class Unpooled extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.netty.buffer.Unpooled"));
|
||||
private static final Reflect.ReflectMethod<?> buffer = wrapEx(() -> REFLECT.method("buffer"));
|
||||
|
||||
|
||||
public static ByteBuf buffer() {
|
||||
return wrap(wrapReflectEx(() -> buffer.invokeStatic()), ByteBuf.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected Unpooled(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.paper;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.AABB;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.VoxelShape;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class AABBVoxelShape extends VoxelShape {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.voxel.AABBVoxelShape"));
|
||||
private static final Reflect.ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> REFLECT.constructor(AABB.MAPPING.runtimeClass()));
|
||||
|
||||
public AABBVoxelShape(AABB aabb) {
|
||||
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(aabb))));
|
||||
}
|
||||
|
||||
protected AABBVoxelShape(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.paper;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class PaperAdventure extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.adventure.PaperAdventure"));
|
||||
private static final Reflect.ReflectMethod<?> asAdventure = wrapEx(() -> REFLECT.method("asAdventure", Component.MAPPING.runtimeClass()));
|
||||
|
||||
public static net.kyori.adventure.text.Component asAdventure(Component component) {
|
||||
return (net.kyori.adventure.text.Component) wrapReflectEx(() -> asAdventure.invokeStatic(unwrap(component)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected PaperAdventure(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.paper;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class QueuedChangesMapLong2Object extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object"));
|
||||
public static final Reflect.ReflectMethod<?> getVisibleMap = wrapEx(() -> REFLECT.method("getVisibleMap"));
|
||||
|
||||
/** The entries in the returned value are not mapped */
|
||||
public Long2ObjectLinkedOpenHashMap<?> getVisibleMap() {
|
||||
return (Long2ObjectLinkedOpenHashMap<?>) wrapReflectEx(() -> getVisibleMap.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
protected QueuedChangesMapLong2Object(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.paper.configuration;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class FallbackValue_Int extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.configuration.type.fallback.FallbackValue$Int"));
|
||||
public static final Reflect.ReflectMethod<?> value = wrapEx(() -> REFLECT.method("value"));
|
||||
|
||||
public int value() {
|
||||
return (int) wrapReflectEx(() -> value.invoke(__getRuntimeInstance()));
|
||||
}
|
||||
|
||||
protected FallbackValue_Int(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package fr.pandacube.lib.paper.reflect.wrapper.paper.configuration;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.reflect.wrapper.ReflectWrapper;
|
||||
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
|
||||
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
|
||||
|
||||
public class WorldConfiguration extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.configuration.WorldConfiguration"));
|
||||
public static final Reflect.ReflectField<?> chunks = wrapEx(() -> REFLECT.field("chunks"));
|
||||
|
||||
public Chunks chunks() {
|
||||
return wrap(wrapReflectEx(() -> chunks.getValue(__getRuntimeInstance())), Chunks.class);
|
||||
}
|
||||
|
||||
protected WorldConfiguration(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public static class Chunks extends ReflectWrapper {
|
||||
public static final Reflect.ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.configuration.WorldConfiguration$Chunks"));
|
||||
public static final Reflect.ReflectField<?> autoSavePeriod = wrapEx(() -> REFLECT.field("autoSaveInterval"));
|
||||
|
||||
public FallbackValue_Int autoSavePeriod() {
|
||||
return wrap(wrapReflectEx(() -> autoSavePeriod.getValue(__getRuntimeInstance())), FallbackValue_Int.class);
|
||||
}
|
||||
|
||||
protected Chunks(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package fr.pandacube.lib.paper.scheduler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import fr.pandacube.lib.paper.PandaLibPaper;
|
||||
|
||||
public class AutoUpdatedObject {
|
||||
private static final Plugin plugin = PandaLibPaper.getPlugin();
|
||||
|
||||
private Runnable updater;
|
||||
|
||||
private final List<BukkitTask> tasks = new ArrayList<>();
|
||||
|
||||
|
||||
protected AutoUpdatedObject() { }
|
||||
public AutoUpdatedObject(Runnable updater) {
|
||||
this.updater = Objects.requireNonNull(updater);
|
||||
}
|
||||
|
||||
public synchronized void updateSync() {
|
||||
tasks.add(Bukkit.getScheduler().runTask(plugin, this::update));
|
||||
}
|
||||
|
||||
public synchronized void updateAsync() {
|
||||
tasks.add(Bukkit.getScheduler().runTaskAsynchronously(plugin, this::update));
|
||||
}
|
||||
|
||||
public synchronized void updateLater(long delay)
|
||||
throws IllegalArgumentException, IllegalStateException {
|
||||
tasks.add(Bukkit.getScheduler().runTaskLater(plugin, this::update, delay));
|
||||
}
|
||||
|
||||
public synchronized void updateLaterAsync(long delay)
|
||||
throws IllegalArgumentException, IllegalStateException {
|
||||
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, this::update, delay));
|
||||
}
|
||||
|
||||
public synchronized void updateTimer(long delay, long period)
|
||||
throws IllegalArgumentException, IllegalStateException {
|
||||
tasks.add(Bukkit.getScheduler().runTaskTimer(plugin, this::update, delay, period));
|
||||
}
|
||||
|
||||
public synchronized void updateTimerAsync(long delay, long period)
|
||||
throws IllegalArgumentException, IllegalStateException {
|
||||
tasks.add(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, this::update, delay, period));
|
||||
}
|
||||
|
||||
public synchronized void cancel() {
|
||||
tasks.forEach(BukkitTask::cancel);
|
||||
tasks.clear();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Objects.requireNonNull(updater, "Please use new AutoUpdatedObject(Runnable) or override the run method.");
|
||||
updater.run();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package fr.pandacube.lib.paper.scheduler;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.paper.PandaLibPaper;
|
||||
|
||||
public class SchedulerUtil {
|
||||
|
||||
public static void runOnServerThread(Runnable task) {
|
||||
if (Bukkit.isPrimaryThread())
|
||||
task.run();
|
||||
|
||||
Bukkit.getScheduler().runTask(PandaLibPaper.getPlugin(), task);
|
||||
}
|
||||
|
||||
public static <T> T runOnServerThreadAndWait(Callable<T> task) throws Exception {
|
||||
if (Bukkit.isPrimaryThread())
|
||||
return task.call();
|
||||
|
||||
return Bukkit.getScheduler().callSyncMethod(PandaLibPaper.getPlugin(), () -> {
|
||||
try {
|
||||
return task.call();
|
||||
} catch (Exception e) {
|
||||
Log.severe("Exception while running callback code on server Thread. The source exception is:", e);
|
||||
throw e;
|
||||
}
|
||||
}).get();
|
||||
}
|
||||
|
||||
public static void runOnServerThreadAndWait(Runnable task) throws Exception {
|
||||
runOnServerThreadAndWait((Callable<Void>)() -> {
|
||||
task.run();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import fr.pandacube.lib.util.RandomUtil;
|
||||
|
||||
/**
|
||||
* Checkpoint represented as a 3D Axis and Block Aligned Bounding Box (sort of AABB).
|
||||
* Represent the littelest cuboid selection of blocks that contains the bounding box
|
||||
* passed to the constructor.
|
||||
*/
|
||||
public class AABBBlock implements Iterable<BlockVector> {
|
||||
|
||||
public final Vector pos1, pos2;
|
||||
|
||||
private final Vector center;
|
||||
|
||||
private final long volume;
|
||||
|
||||
public AABBBlock(Vector p1, Vector p2) {
|
||||
this(p1.getBlockX(), p1.getBlockY(), p1.getBlockZ(), p2.getBlockX(), p2.getBlockY(), p2.getBlockZ());
|
||||
}
|
||||
|
||||
public AABBBlock(Location l1, Location l2) {
|
||||
this(l1.getBlockX(), l1.getBlockY(), l1.getBlockZ(), l2.getBlockX(), l2.getBlockY(), l2.getBlockZ());
|
||||
}
|
||||
|
||||
public AABBBlock(BlockVector l1, BlockVector l2) {
|
||||
this(l1.getBlockX(), l1.getBlockY(), l1.getBlockZ(), l2.getBlockX(), l2.getBlockY(), l2.getBlockZ());
|
||||
}
|
||||
|
||||
public AABBBlock(int p1x, int p1y, int p1z, int p2x, int p2y, int p2z) {
|
||||
/*
|
||||
* Prends les points extérieurs permettant de former un bouding box englobant
|
||||
* celui représenté par v1 et v2, et étant aligné au quadrillage des blocs.
|
||||
*/
|
||||
int p1x_ = Math.min(p1x, p2x);
|
||||
int p1y_ = Math.min(p1y, p2y);
|
||||
int p1z_ = Math.min(p1z, p2z);
|
||||
int p2x_ = Math.max(p1x, p2x) + 1;
|
||||
int p2y_ = Math.max(p1y, p2y) + 1;
|
||||
int p2z_ = Math.max(p1z, p2z) + 1;
|
||||
pos1 = new Vector(p1x_, p1y_, p1z_);
|
||||
pos2 = new Vector(p2x_, p2y_, p2z_);
|
||||
|
||||
center = new Vector((p1x_ + p2x_) / 2d, (p1y_ + p2y_) / 2d, (p1z_ + p2z_) / 2d);
|
||||
|
||||
volume = (long) Math.abs(p2x_ - p1x_) * Math.abs(p2x_ - p1x_) * Math.abs(p2x_ - p1x_);
|
||||
}
|
||||
|
||||
public boolean overlaps(Entity e) {
|
||||
return overlaps(e.getBoundingBox());
|
||||
}
|
||||
|
||||
public boolean overlaps(BoundingBox bb) {
|
||||
return asBukkitBoundingBox().overlaps(bb);
|
||||
}
|
||||
|
||||
public boolean isInside(Vector v) {
|
||||
return v.isInAABB(pos1, pos2);
|
||||
}
|
||||
public boolean isInside(Location l) {
|
||||
return isInside(l.toVector());
|
||||
}
|
||||
public boolean isInside(Entity p) {
|
||||
return isInside(p.getLocation());
|
||||
}
|
||||
|
||||
public Vector getCenter() {
|
||||
return center.clone();
|
||||
}
|
||||
|
||||
public long getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public BoundingBox asBukkitBoundingBox() {
|
||||
return new BoundingBox(pos1.getX(), pos1.getY(), pos1.getZ(),
|
||||
pos2.getX(), pos2.getY(), pos2.getZ());
|
||||
}
|
||||
|
||||
public Vector getRandomPosition() {
|
||||
double x = RandomUtil.nextDoubleBetween(pos1.getX(), pos2.getX());
|
||||
double y = RandomUtil.nextDoubleBetween(pos1.getY(), pos2.getY());
|
||||
double z = RandomUtil.nextDoubleBetween(pos1.getZ(), pos2.getZ());
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector> iterator() {
|
||||
return new Iterator<>() {
|
||||
private int x = pos1.getBlockX(),
|
||||
y = pos1.getBlockY(),
|
||||
z = pos1.getBlockZ();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return x < pos2.getBlockX();
|
||||
}
|
||||
@Override
|
||||
public BlockVector next() {
|
||||
BlockVector bv = new BlockVector(x, y, z);
|
||||
|
||||
z++;
|
||||
if (z >= pos2.getBlockZ()) {
|
||||
y++;
|
||||
z = pos1.getBlockZ();
|
||||
if (y >= pos2.getBlockY()) {
|
||||
x++;
|
||||
y = pos1.getBlockY();
|
||||
}
|
||||
}
|
||||
|
||||
return bv;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public Iterable<Block> asBlockIterable(World w) {
|
||||
return () -> new Iterator<>() {
|
||||
final Iterator<BlockVector> nested = AABBBlock.this.iterator();
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nested.hasNext();
|
||||
}
|
||||
@Override
|
||||
public Block next() {
|
||||
BlockVector bv = nested.next();
|
||||
return w.getBlockAt(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import fr.pandacube.lib.util.IteratorIterator;
|
||||
import fr.pandacube.lib.util.RandomUtil;
|
||||
|
||||
public class AABBBlockGroup implements Iterable<BlockVector> {
|
||||
|
||||
public final List<AABBBlock> aabbBlocks;
|
||||
|
||||
public AABBBlockGroup(Collection<AABBBlock> in) {
|
||||
aabbBlocks = List.copyOf(in);
|
||||
}
|
||||
|
||||
public AABBBlockGroup(AABBBlock... in) {
|
||||
aabbBlocks = List.of(in);
|
||||
}
|
||||
|
||||
|
||||
public boolean isInside(Vector v) {
|
||||
for (AABBBlock b : aabbBlocks)
|
||||
if (b.isInside(v))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
public boolean isInside(Location l) {
|
||||
return isInside(l.toVector());
|
||||
}
|
||||
public boolean isInside(Entity p) {
|
||||
return isInside(p.getLocation());
|
||||
}
|
||||
|
||||
public Vector getRandomPosition() {
|
||||
double[] freq = aabbBlocks.stream().mapToDouble(AABBBlock::getVolume).toArray();
|
||||
int i = RandomUtil.randomIndexOfFrequencies(freq);
|
||||
return aabbBlocks.get(i).getRandomPosition();
|
||||
}
|
||||
|
||||
public long getVolume() {
|
||||
long v = 0;
|
||||
for (AABBBlock b : aabbBlocks)
|
||||
v += b.getVolume();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector> iterator() {
|
||||
return IteratorIterator.ofCollectionOfIterator(aabbBlocks.stream().map(AABBBlock::iterator).toList());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,198 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.paper.PandaLibPaper;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.bossbar.BossBar.Color;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class AutoUpdatedBossBar implements Listener {
|
||||
|
||||
public final BossBar bar;
|
||||
public final BarUpdater updater;
|
||||
|
||||
private Timer timer = null;
|
||||
private BukkitTask bukkitTask = null;
|
||||
|
||||
private boolean scheduled = false;
|
||||
|
||||
private boolean followPlayerList = false;
|
||||
private Predicate<Player> playerCondition = null;
|
||||
|
||||
public AutoUpdatedBossBar(BossBar bar, BarUpdater updater) {
|
||||
this.bar = bar;
|
||||
this.updater = updater;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Schedule the update of this bossbar with synchronisation with the system clock.
|
||||
* The underlying method called is {@link Timer#schedule(TimerTask, long, long)}.
|
||||
* The updater is executed in a separate Thread.
|
||||
* @param msDelay ms before running the first update of this bossbar
|
||||
* @param msPeriod ms between each call of the updater
|
||||
*/
|
||||
public synchronized void scheduleUpdateTimeSyncThreadAsync(long msDelay, long msPeriod) {
|
||||
if (scheduled)
|
||||
throw new IllegalStateException("Can't schedule an already scheduled bossbar update");
|
||||
|
||||
scheduled = true;
|
||||
timer = new Timer("Panda BossBarUpdater - " + Chat.chatComponent(bar.name()).getPlainText());
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
updater.update(AutoUpdatedBossBar.this);
|
||||
} catch(Throwable e) {
|
||||
Log.severe("Error while updating an AutoUpdatedBossBar", e);
|
||||
}
|
||||
}
|
||||
}, msDelay, msPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the update of this bossbar with synchronisation with the main Thread of the
|
||||
* current Minecraft server (follow the tick count progress).
|
||||
* The underlying method called is {@link BukkitScheduler#runTaskTimer(org.bukkit.plugin.Plugin, Runnable, long, long)}.
|
||||
* The updater is executed by the Server Thread.
|
||||
* @param tickDelay number of server tick before running the first update of this bossbar
|
||||
* @param tickPeriod number of server tick between each call of the updater
|
||||
*/
|
||||
public synchronized void scheduleUpdateTickSyncThreadSync(long tickDelay, long tickPeriod) {
|
||||
if (scheduled)
|
||||
throw new IllegalStateException("Can't schedule an already scheduled bossbar update");
|
||||
|
||||
scheduled = true;
|
||||
bukkitTask = Bukkit.getServer().getScheduler()
|
||||
.runTaskTimer(PandaLibPaper.getPlugin(), () -> {
|
||||
synchronized (bar) {
|
||||
try {
|
||||
updater.update(this);
|
||||
} catch(Throwable e) {
|
||||
Log.severe("Error while updating an AutoUpdatedBossBar", e);
|
||||
}
|
||||
}
|
||||
}, tickDelay, tickPeriod);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public synchronized void followLoginLogout(Predicate<Player> condition) {
|
||||
playerCondition = condition;
|
||||
if (followPlayerList)
|
||||
return;
|
||||
followPlayerList = true;
|
||||
BukkitEvent.register(this);
|
||||
Bukkit.getServer().getOnlinePlayers().forEach(p -> onPlayerJoin(new PlayerJoinEvent(p, Component.text(""))));
|
||||
}
|
||||
|
||||
public synchronized void unfollowPlayerList() {
|
||||
if (!followPlayerList)
|
||||
return;
|
||||
followPlayerList = false;
|
||||
playerCondition = null;
|
||||
PlayerJoinEvent.getHandlerList().unregister(this);
|
||||
PlayerQuitEvent.getHandlerList().unregister(this);
|
||||
}
|
||||
|
||||
@EventHandler(priority=EventPriority.MONITOR)
|
||||
public synchronized void onPlayerJoin(PlayerJoinEvent event) {
|
||||
if (!followPlayerList)
|
||||
return;
|
||||
if (playerCondition != null && !playerCondition.test(event.getPlayer()))
|
||||
return;
|
||||
synchronized (bar) {
|
||||
event.getPlayer().showBossBar(bar);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority=EventPriority.HIGH)
|
||||
public synchronized void onPlayerQuit(PlayerQuitEvent event) {
|
||||
if (!followPlayerList)
|
||||
return;
|
||||
synchronized (bar) {
|
||||
event.getPlayer().hideBossBar(bar);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
synchronized (bar) {
|
||||
for (Player p : Bukkit.getOnlinePlayers())
|
||||
p.hideBossBar(bar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public synchronized void cancel() {
|
||||
if (!scheduled)
|
||||
throw new IllegalStateException("Can't cancel a not scheduled bossbar update");
|
||||
scheduled = false;
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
if (bukkitTask != null) {
|
||||
bukkitTask.cancel();
|
||||
bukkitTask = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BarUpdater {
|
||||
void update(AutoUpdatedBossBar bar);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Utility method to update the title of the bossbar without unnecessary packet.
|
||||
*/
|
||||
public void setTitle(Chat title) {
|
||||
synchronized (bar) {
|
||||
bar.name(title); // already check if the title is the same
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the color of the bossbar without unnecessary packet.
|
||||
*/
|
||||
public void setColor(Color color) {
|
||||
synchronized (bar) {
|
||||
bar.color(color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the progress of the bossbar without unnecessary packet.
|
||||
*/
|
||||
public void setProgress(double progress) {
|
||||
synchronized (bar) {
|
||||
bar.progress((float) progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import org.bukkit.DyeColor;
|
||||
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
public class BukkitChatColorUtil {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link ChatColor} that is visually the closest from the provided {@link DyeColor} when used on a sign.
|
||||
*
|
||||
* Multiple {@link DyeColor} may return the same
|
||||
* @param dye the provided dye color
|
||||
* @return the closest chat color from {@code dye}
|
||||
*/
|
||||
public static ChatColor fromDyeToSignColor(DyeColor dye) {
|
||||
//org.bukkit.Color col = dye.getColor();
|
||||
//return ChatColor.of(new Color(col.asRGB()));
|
||||
// hmmm this is not that simple, of course
|
||||
|
||||
// black
|
||||
return switch (dye) {
|
||||
case BLACK -> ChatColor.of("#000000");
|
||||
case RED -> ChatColor.of("#650000");
|
||||
case GREEN -> ChatColor.of("#006500");
|
||||
case BROWN -> ChatColor.of("#361B07");
|
||||
case BLUE -> ChatColor.of("#000065");
|
||||
case PURPLE -> ChatColor.of("#3F0C5F");
|
||||
case CYAN -> ChatColor.of("#006565");
|
||||
case LIGHT_GRAY -> ChatColor.of("#535353");
|
||||
case GRAY -> ChatColor.of("#323232");
|
||||
case PINK -> ChatColor.of("#652947");
|
||||
case LIME -> ChatColor.of("#4B6500");
|
||||
case YELLOW -> ChatColor.of("#656500");
|
||||
case LIGHT_BLUE -> ChatColor.of("#3C4B51");
|
||||
case MAGENTA -> ChatColor.of("#650065");
|
||||
case ORANGE -> ChatColor.of("#65280C");
|
||||
case WHITE -> ChatColor.of("#656565");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static org.bukkit.ChatColor toBukkit(ChatColor color) {
|
||||
return org.bukkit.ChatColor.valueOf(color.getName().toUpperCase());
|
||||
}
|
||||
|
||||
public static org.bukkit.ChatColor toBukkit(TextColor color) {
|
||||
return toBukkit(NamedTextColor.nearestTo(color));
|
||||
}
|
||||
|
||||
public static org.bukkit.ChatColor toBukkit(NamedTextColor color) {
|
||||
return org.bukkit.ChatColor.valueOf(color.toString().toUpperCase());
|
||||
}
|
||||
|
||||
public static NamedTextColor toAdventure(org.bukkit.ChatColor color) {
|
||||
return NamedTextColor.NAMES.value(color.name().toLowerCase());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import fr.pandacube.lib.reflect.Reflect;
|
||||
import fr.pandacube.lib.paper.PandaLibPaper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventException;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.EventExecutor;
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class BukkitEvent {
|
||||
|
||||
public static <E extends Event> Listener register(Class<E> eventClass, EventListener<E> eventExecutor) {
|
||||
return register(eventClass, eventExecutor, EventPriority.NORMAL, false);
|
||||
}
|
||||
|
||||
public static <E extends Event> Listener register(Class<E> eventClass, EventListener<E> eventExecutor, EventPriority priority) {
|
||||
return register(eventClass, eventExecutor, priority, false);
|
||||
}
|
||||
|
||||
public static <E extends Event> Listener register(Class<E> eventClass, EventListener<E> eventExecutor, boolean ignoreCancelled) {
|
||||
return register(eventClass, eventExecutor, EventPriority.NORMAL, ignoreCancelled);
|
||||
}
|
||||
|
||||
public static <E extends Event> Listener register(Class<E> eventClass, EventListener<E> eventExecutor, EventPriority priority, boolean ignoreCancelled) {
|
||||
Bukkit.getPluginManager().registerEvent(eventClass, eventExecutor, priority, eventExecutor, PandaLibPaper.getPlugin(), ignoreCancelled);
|
||||
return eventExecutor;
|
||||
}
|
||||
|
||||
public static void register(Listener l) {
|
||||
Bukkit.getPluginManager().registerEvents(l, PandaLibPaper.getPlugin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void unregister(Listener listener) {
|
||||
HandlerList.unregisterAll(listener);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static List<Class<? extends Event>> getAllEventClasses() {
|
||||
List<Class<? extends Event>> classes = Reflect.ofClass(Event.class).getAllSubclasses(false);
|
||||
classes.removeIf(e -> getHandlerList(e) == null);
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// method retrieved from OB.plugin.SimplePluginManager#getEventListeners
|
||||
public static HandlerList getHandlerList(Class<? extends Event> type) {
|
||||
try {
|
||||
return (HandlerList) Reflect.ofClass(getRegistrationClass(type)).method("getHandlerList").invokeStatic();
|
||||
}
|
||||
catch (ReflectiveOperationException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// method retrieved from OB.plugin.SimplePluginManager
|
||||
private static Class<? extends Event> getRegistrationClass(Class<? extends Event> clazz) {
|
||||
try {
|
||||
clazz.getDeclaredMethod("getHandlerList");
|
||||
return clazz;
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Event.class) && Event.class.isAssignableFrom(clazz.getSuperclass())) {
|
||||
return getRegistrationClass(clazz.getSuperclass().asSubclass(Event.class));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface EventListener<E extends Event> extends Listener, EventExecutor {
|
||||
|
||||
void onEvent(E event);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
default void execute(Listener var1, Event var2) throws EventException {
|
||||
onEvent((E)var2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link EventListener} that ensure as best as it can,
|
||||
* that it is the last listener called to handle the event.
|
||||
*
|
||||
* @param <E> the type of the event
|
||||
*/
|
||||
public static abstract class EnforcedLastListener<E extends Event> implements EventListener<E> {
|
||||
private final Class<E> eventClass;
|
||||
private final boolean ignoreCancelled;
|
||||
|
||||
public EnforcedLastListener(Class<E> eventClass, boolean ignoreCancelled) {
|
||||
this.eventClass = eventClass;
|
||||
this.ignoreCancelled = ignoreCancelled;
|
||||
register();
|
||||
}
|
||||
|
||||
private void register() {
|
||||
BukkitEvent.register(eventClass, this, EventPriority.MONITOR, ignoreCancelled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Listener var1, Event var2) throws EventException {
|
||||
EventListener.super.execute(var1, var2);
|
||||
checkIfListenerIsLast();
|
||||
}
|
||||
|
||||
|
||||
private final AtomicReference<BukkitTask> listenerCheckTask = new AtomicReference<>();
|
||||
|
||||
private void checkIfListenerIsLast() {
|
||||
synchronized (listenerCheckTask) {
|
||||
if (listenerCheckTask.get() != null)
|
||||
return;
|
||||
HandlerList hList = BukkitEvent.getHandlerList(eventClass);
|
||||
if (hList == null)
|
||||
return;
|
||||
RegisteredListener[] listeners = hList.getRegisteredListeners();
|
||||
if (listeners[listeners.length - 1].getListener() != this) {
|
||||
listenerCheckTask.set(Bukkit.getScheduler().runTask(PandaLibPaper.getPlugin(), () -> {
|
||||
// need to re-register the event so we are last
|
||||
BukkitEvent.unregister(this);
|
||||
register();
|
||||
listenerCheckTask.set(null);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Color;
|
||||
|
||||
public class ColorUtil {
|
||||
|
||||
/*
|
||||
* Rainbow
|
||||
*/
|
||||
private static final List<Color> rainbowColors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Get a rainbow color
|
||||
* @param variation from 0 (include) to 1 (exclude).
|
||||
* 0 is red, 1/6 is yellow, 2/6 is green, 3/6 is cyan, 4/6 is blue, 5/6 is magenta
|
||||
*/
|
||||
public static Color getRainbowColor(double variation) {
|
||||
synchronized (rainbowColors) {
|
||||
if (rainbowColors.isEmpty()) {
|
||||
for (int g=0; g<255; g++) rainbowColors.add(Color.fromRGB(255, g, 0));
|
||||
for (int r=255; r>0; r--) rainbowColors.add(Color.fromRGB(r, 255, 0));
|
||||
for (int b=0; b<255; b++) rainbowColors.add(Color.fromRGB(0, 255, b));
|
||||
for (int g=255; g>0; g--) rainbowColors.add(Color.fromRGB(0, g, 255));
|
||||
for (int r=0; r<255; r++) rainbowColors.add(Color.fromRGB(r, 0, 255));
|
||||
for (int b=255; b>0; b--) rainbowColors.add(Color.fromRGB(255, 0, b));
|
||||
}
|
||||
}
|
||||
|
||||
while (variation >= 1) variation -= 1d;
|
||||
while (variation < 0) variation += 1d;
|
||||
|
||||
return rainbowColors.get((int)(variation * rainbowColors.size()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
/**
|
||||
* Permet de gérer les entités qui se transportent les uns les autres
|
||||
*
|
||||
* Ce groupement d'entité est appelé une "pile d'entité".
|
||||
*
|
||||
* Par exemple, un cheval et son monteur représente à eux deux une pile
|
||||
* d'entité, dont
|
||||
* l'élement tout en bas est le cheval
|
||||
*/
|
||||
public class EntityStackUtil {
|
||||
|
||||
/**
|
||||
* Déplace une pile d'entité vers l'endroit défini
|
||||
*
|
||||
* @param e Une entité faisant parti de la pile d'entité à téléporter
|
||||
* @param l La position vers lequel envoyer toute la pile
|
||||
*/
|
||||
public static void teleportStack(Entity e, Location l) {
|
||||
|
||||
// on se place sur l'entité tout en bas de la pile
|
||||
Entity entTemp = e;
|
||||
while (entTemp.getVehicle() != null)
|
||||
entTemp = entTemp.getVehicle();
|
||||
|
||||
/* la possibilité d'avoir plusieurs passagers sur un entité rend le code
|
||||
* commenté qui suit invalide. On le remplace temporairement (voire
|
||||
* définitivement si ça suffit) par le code encore en dessous
|
||||
List<Entity> stack = new ArrayList<>();
|
||||
do {
|
||||
stack.add(entTemp);
|
||||
entTemp = entTemp.getPassenger();
|
||||
} while (entTemp != null);
|
||||
|
||||
if (stack.size() == 1) {
|
||||
stack.get(0).teleport(l);
|
||||
return;
|
||||
}
|
||||
|
||||
stack.get(0).eject();
|
||||
stack.get(0).teleport(l);
|
||||
stack.get(0).setPassenger(stack.get(1));
|
||||
*/
|
||||
|
||||
entTemp.teleport(l); // entTemp est l'entité le plus en bas de la "pile" d'entité
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* A utility for managing Player experience properly.<br/>
|
||||
* <a href="https://gist.github.com/Jikoo/30ec040443a4701b8980">Github Gist - Jikoo</a>
|
||||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
public class ExperienceUtil {
|
||||
|
||||
/**
|
||||
* Calculates a player's total exp based on level and progress to next.
|
||||
*
|
||||
* @see <a href="http://minecraft.gamepedia.com/Experience#Leveling_up">Experience (#leveling up) - Minecraft Wiki</a>
|
||||
*
|
||||
* @param player the Player
|
||||
*
|
||||
* @return the amount of exp the Player has
|
||||
*/
|
||||
public static int getExp(Player player) {
|
||||
return getExpFromLevel(player.getLevel()) + Math.round(getExpToNext(player.getLevel()) * player.getExp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates total experience based on level.
|
||||
*
|
||||
* @see <a href="http://minecraft.gamepedia.com/Experience#Leveling_up">Experience (#leveling up) - Minecraft Wiki</a>
|
||||
*
|
||||
* @param level the level
|
||||
*
|
||||
* @return the total experience calculated
|
||||
*/
|
||||
public static int getExpFromLevel(int level) {
|
||||
if (level > 30) return (int) (4.5 * level * level - 162.5 * level + 2220);
|
||||
if (level > 15) return (int) (2.5 * level * level - 40.5 * level + 360);
|
||||
return level * level + 6 * level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates level based on total experience.
|
||||
*
|
||||
* @param exp the total experience
|
||||
*
|
||||
* @return the level calculated
|
||||
*/
|
||||
public static double getLevelFromExp(int exp) {
|
||||
if (exp > 1395) return (Math.sqrt(72 * exp - 54215) + 325) / 18;
|
||||
if (exp > 315) return Math.sqrt(40 * exp - 7839) / 10 + 8.1;
|
||||
if (exp > 0) return Math.sqrt(exp + 9) - 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <a href="http://minecraft.gamepedia.com/Experience#Leveling_up">Experience (#leveling up) - Minecraft Wiki</a>
|
||||
*
|
||||
* "The formulas for figuring out how many experience orbs you need to
|
||||
* get to the next level are as follows:
|
||||
* Experience Required = 2[Current Level] + 7 (at levels 0-15)
|
||||
* 5[Current Level] - 38 (at levels 16-30)
|
||||
* 9[Current Level] - 158 (at level 31+)"
|
||||
*/
|
||||
private static int getExpToNext(int level) {
|
||||
if (level > 30) return 9 * level - 158;
|
||||
if (level > 15) return 5 * level - 38;
|
||||
return 2 * level + 7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a Player's exp.
|
||||
* <p>
|
||||
* This method should be used in place of {@link Player#giveExp(int)}, which
|
||||
* does not properly
|
||||
* account for different levels requiring different amounts of experience.
|
||||
*
|
||||
* @param player the Player affected
|
||||
* @param exp the amount of experience to add or remove
|
||||
*/
|
||||
public static void changeExp(Player player, int exp) {
|
||||
exp += getExp(player);
|
||||
|
||||
if (exp < 0) exp = 0;
|
||||
|
||||
double levelAndExp = getLevelFromExp(exp);
|
||||
|
||||
int level = (int) levelAndExp;
|
||||
player.setLevel(level);
|
||||
player.setExp((float) (levelAndExp - level));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import fr.pandacube.lib.util.BiMap;
|
||||
import fr.pandacube.lib.util.FileUtils;
|
||||
import fr.pandacube.lib.util.Log;
|
||||
import fr.pandacube.lib.util.RandomUtil;
|
||||
|
||||
public class GameWorldUtils implements Listener {
|
||||
|
||||
private static final BiMap<String, World> gameWorld = new BiMap<>();
|
||||
|
||||
|
||||
public static World getOrLoadGameWorld(String world, Consumer<World> operationOnLoad) throws IOException {
|
||||
if (gameWorld.containsKey(world)) {
|
||||
return gameWorld.get(world);
|
||||
}
|
||||
try {
|
||||
return loadGameWorld(world, operationOnLoad);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.severe(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static World getGameWorldIfLoaded(String world) {
|
||||
if (gameWorld.containsKey(world)) {
|
||||
return gameWorld.get(world);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static boolean unloadGameWorld(String world) {
|
||||
if (gameWorld.containsKey(world)) {
|
||||
World rem = gameWorld.remove(world);
|
||||
String copiedName = rem.getName();
|
||||
boolean ret = Bukkit.unloadWorld(rem, false);
|
||||
if (ret)
|
||||
FileUtils.delete(new File(Bukkit.getWorldContainer(), copiedName));
|
||||
return ret;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static boolean isGameWorldLoaded(String world) {
|
||||
return gameWorld.containsKey(world);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static World loadGameWorld(String world, Consumer<World> operationOnLoad) throws IOException {
|
||||
if (gameWorld.containsKey(world))
|
||||
throw new IllegalStateException("GameWorld '"+world+"' is already loaded.");
|
||||
|
||||
if (!new File(Bukkit.getWorldContainer(), world).isDirectory())
|
||||
throw new IllegalStateException("GameWorld '"+world+"' does not exist");
|
||||
|
||||
String copiedName = world + "_gen" + RandomUtil.nextIntBetween(100000, 999999);
|
||||
|
||||
File srcDir = new File(Bukkit.getWorldContainer(), world);
|
||||
File destDir = new File(Bukkit.getWorldContainer(), copiedName);
|
||||
FileUtils.delete(destDir);
|
||||
FileUtils.copy(srcDir, destDir);
|
||||
new File(destDir, "session.lock").delete();
|
||||
new File(destDir, "uid.dat").delete();
|
||||
|
||||
World w = Bukkit.createWorld(new WorldCreator(copiedName).environment(Environment.NORMAL));
|
||||
w.setAutoSave(false);
|
||||
gameWorld.put(world, w);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mvm set hidden true "+copiedName);
|
||||
operationOnLoad.accept(w);
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,410 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class GeometryUtil {
|
||||
|
||||
/**
|
||||
* Value equal to <code>{@link Math#PI}</code>.
|
||||
*/
|
||||
public static final double PI = Math.PI;
|
||||
|
||||
/**
|
||||
* Value equal to <code>{@link Math#PI} / 2</code>.
|
||||
*/
|
||||
public static final double PId2 = PI/2;
|
||||
|
||||
/**
|
||||
* Value equal to <code>{@link Math#PI} * 2</code>.
|
||||
*/
|
||||
public static final double PIx2 = PI*2;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Player geometry
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The visual height of a Minecraft player skin, when he is standing up and not sneaking,
|
||||
* from the ground where the player is standing on, to the above of the first layer of the head skin.
|
||||
* It doesn't correspond to the player hitbox height.<br/>
|
||||
* <br/>
|
||||
* <code>1.88</code> is an approximated value, estimated by ingame tests.
|
||||
*/
|
||||
public static final double PLAYER_SKIN_HEIGHT = 1.88;
|
||||
/**
|
||||
* Value provided by Craftbukkit's {@code CraftPlayer#getEyeHeight(boolean)} source code
|
||||
*/
|
||||
public static final double PLAYER_EYE_HEIGHT = 1.62;
|
||||
/**
|
||||
* The visual height of a Minecraft player skin, when he is standing up and sneaking,
|
||||
* from the ground where the player is standing on, to the above of the first layer of the head skin.
|
||||
* It may not correspond to the player hitbox height.<br/>
|
||||
* <br/>
|
||||
* The current value is the height of the player's hitbox when sneaking. Even if this
|
||||
* is close to the real value (tested in game), this is not the exact value.
|
||||
*/
|
||||
public static final double PLAYER_SKIN_HEIGHT_SNEAK = 1.65;
|
||||
/**
|
||||
* Value provided by Craftbukkit's {@code CraftPlayer#getEyeHeight(boolean)} source code
|
||||
*/
|
||||
public static final double PLAYER_EYE_HEIGHT_SNEAK = 1.54;
|
||||
public static final double PLAYER_SKIN_PIXEL_SIZE = PLAYER_SKIN_HEIGHT / 32;
|
||||
public static final double PLAYER_HEAD_ROTATION_HEIGHT = PLAYER_SKIN_PIXEL_SIZE * 24;
|
||||
public static final double PLAYER_HEAD_ROTATION_HEIGHT_SNEAK = PLAYER_HEAD_ROTATION_HEIGHT - (PLAYER_SKIN_HEIGHT - PLAYER_SKIN_HEIGHT_SNEAK);
|
||||
public static final double PLAYER_HEAD_SIZE = PLAYER_SKIN_PIXEL_SIZE * 8;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the {@link Location}s of the 8 vertex of the player head<br/>
|
||||
* This method only work if the player is standing up
|
||||
* (not dead, not glyding, not sleeping).
|
||||
* @param playerLocation the location of the player, generally provided by {@link Player#getLocation()}
|
||||
* @param isSneaking if the player is sneaking. Generally {@link Player#isSneaking()}
|
||||
* @return an array of 8 {@link Location}s with x, y, and z values filled (yaw and pitch are ignored).
|
||||
* <pre>return[0] // top front left
|
||||
*return[1] // top front right
|
||||
*return[2] // bottom front left
|
||||
*return[3] // bottom front right
|
||||
*return[4] // top back left
|
||||
*return[5] // top back right
|
||||
*return[6] // bottom back left
|
||||
*return[7] // bottom back right
|
||||
*/
|
||||
public static Location[] getPlayerHeadGeometry(Location playerLocation, boolean isSneaking) {
|
||||
Location[] headAnglesPoints = new Location[8];
|
||||
|
||||
Location playerHeadRotationLocation = playerLocation.clone()
|
||||
.add(0, isSneaking ? PLAYER_HEAD_ROTATION_HEIGHT_SNEAK : PLAYER_HEAD_ROTATION_HEIGHT, 0);
|
||||
|
||||
DirectionalVector frontDirection = new DirectionalVector(playerHeadRotationLocation);
|
||||
Vector frontHalfVector = frontDirection.toVector().multiply(PLAYER_HEAD_SIZE/2);
|
||||
Vector backHalfDirection = frontDirection.getBackDirection().toVector().multiply(PLAYER_HEAD_SIZE/2);
|
||||
Vector leftHalfVector = frontDirection.getLeftDirection().toVector().multiply(PLAYER_HEAD_SIZE/2);
|
||||
Vector rightHalfVector = frontDirection.getRightDirection().toVector().multiply(PLAYER_HEAD_SIZE/2);
|
||||
Vector topVector = frontDirection.getTopDirection().toVector().multiply(PLAYER_HEAD_SIZE);
|
||||
|
||||
Location bottomFrontMiddle = playerHeadRotationLocation.clone().add(frontHalfVector);
|
||||
Location bottomBackMiddle = playerHeadRotationLocation.clone().add(backHalfDirection);
|
||||
|
||||
Location topFrontMiddle = bottomFrontMiddle.clone().add(topVector);
|
||||
Location topBackMiddle = bottomBackMiddle.clone().add(topVector);
|
||||
|
||||
headAnglesPoints[0] = topFrontMiddle.clone().add(leftHalfVector);
|
||||
headAnglesPoints[1] = topFrontMiddle.clone().add(rightHalfVector);
|
||||
headAnglesPoints[2] = bottomFrontMiddle.clone().add(leftHalfVector);
|
||||
headAnglesPoints[3] = bottomFrontMiddle.clone().add(rightHalfVector);
|
||||
headAnglesPoints[4] = topBackMiddle.clone().add(leftHalfVector);
|
||||
headAnglesPoints[5] = topBackMiddle.clone().add(rightHalfVector);
|
||||
headAnglesPoints[6] = bottomBackMiddle.clone().add(leftHalfVector);
|
||||
headAnglesPoints[7] = bottomBackMiddle.clone().add(rightHalfVector);
|
||||
|
||||
return headAnglesPoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the path from <i>start</i> location to <i>end</i> pass through
|
||||
* the axis aligned bounding box defined by <i>min</i> and <i>max</i>.
|
||||
*/
|
||||
public static boolean hasIntersection(Vector start, Vector end, Vector min, Vector max) {
|
||||
final double epsilon = 0.0001f;
|
||||
|
||||
Vector d = end.clone().subtract(start).multiply(0.5);
|
||||
Vector e = max.clone().subtract(min).multiply(0.5);
|
||||
Vector c = start.clone().add(d).subtract(min.clone().add(max).multiply(0.5));
|
||||
Vector ad = d.clone();
|
||||
ad.setX(Math.abs(ad.getX()));
|
||||
ad.setY(Math.abs(ad.getY()));
|
||||
ad.setZ(Math.abs(ad.getZ()));
|
||||
|
||||
if (Math.abs(c.getX()) > e.getX() + ad.getX()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.abs(c.getY()) > e.getY() + ad.getY()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.abs(c.getZ()) > e.getX() + ad.getZ()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.abs(d.getY() * c.getZ() - d.getZ() * c.getY()) > e.getY() * ad.getZ() + e.getZ() * ad.getY() + epsilon){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.abs(d.getZ() * c.getX() - d.getX() * c.getZ()) > e.getZ() * ad.getX() + e.getX() * ad.getZ() + epsilon){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.abs(d.getX() * c.getY() - d.getY() * c.getX()) > e.getX() * ad.getY() + e.getY() * ad.getX() + epsilon){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This vector consider Minecraft X Y Z axis orientation,
|
||||
* but consider standard (not Minecraft) radian values for yaw and pitch.<br/>
|
||||
* The length of this Vector (based on {@link #x}, {@link #y} and {@link #z} values)
|
||||
* Is always 1.
|
||||
*
|
||||
* <pre>Yaw :
|
||||
* North (-z) = -PI/2
|
||||
* East (+x) = 0
|
||||
* South (+z) = PI/2
|
||||
* West (-x) = ±PI
|
||||
*
|
||||
* Pitch :
|
||||
* Up (+y) = PI/2
|
||||
* Down (-y) = -PI/2</pre>
|
||||
*/
|
||||
public static class DirectionalVector {
|
||||
/**
|
||||
* The X cartesian coordinate of this {@link DirectionalVector}.
|
||||
* It correspond to the X (west to east) axis in a Minecraft world.
|
||||
*/
|
||||
public final double x;
|
||||
|
||||
/**
|
||||
* The Y cartesian coordinate of this {@link DirectionalVector}.
|
||||
* It correspond to the Y (bottom to top) axis in a Minecraft world.
|
||||
*/
|
||||
public final double y;
|
||||
|
||||
/**
|
||||
* The Z cartesian coordinate of this {@link DirectionalVector}.
|
||||
* It correspond to the Z (north to south) axis in a Minecraft world.
|
||||
*/
|
||||
public final double z;
|
||||
|
||||
/**
|
||||
* The azimuthal angle φ (phi) of this {@link DirectionalVector}, in radian.
|
||||
* It correspond with Minecraft world as follow :
|
||||
* <pre>Yaw :
|
||||
* North (-z) = -PI/2
|
||||
* East (+x) = 0
|
||||
* South (+z) = PI/2
|
||||
* West (-x) = ±PI</pre>
|
||||
*/
|
||||
public final double yaw;
|
||||
|
||||
/**
|
||||
* The polar angle θ (theta) of this {@link DirectionalVector}, in radian.
|
||||
* It correspond with Minecraft world as follow :
|
||||
* <pre>Pitch :
|
||||
* Down (-y) = -PI/2
|
||||
* Up (+y) = PI/2</pre>
|
||||
*/
|
||||
public final double pitch;
|
||||
|
||||
/**
|
||||
* Initialize this {@link DirectionalVector} with the yaw and pitch
|
||||
* contained in the provided {@link Location}.
|
||||
* {@link Location#getYaw()} and {@link Location#getPitch()} values are automatically
|
||||
* converted to conform {@link #yaw} and {@link #pitch} specification.
|
||||
*/
|
||||
public DirectionalVector(Location l) {
|
||||
this(
|
||||
Math.toRadians(((l.getYaw()+90)%360) > 180 ? ((l.getYaw()+90)%360)-360 : ((l.getYaw()+90)%360)),
|
||||
-Math.toRadians(l.getPitch())
|
||||
);
|
||||
/* MC : +90 : %360 : >180 -> -360
|
||||
* South (+z) = 0, 360 : 90-450 : 90 : 90 : PI/2
|
||||
* West (-x) = 90 : 180 : 180 : ±180 : ±PI
|
||||
* North (-z) = 180 : 270 : 270 : -90 : -PI/2
|
||||
* East (+x) = 270 : 360 : 0-360 : 0 : 0
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param v the vector representing the direction. If v.getX() && v.getZ() are 0,
|
||||
* the yaw will be 0. This may have inconsistence if the vector is calculated
|
||||
* from a {@link Location}'s yaw and pitch. In this case, prefer using
|
||||
* {@link #DirectionalVector(Location)}. The {@link Vector} is
|
||||
* normalized if necessary (does not modify provided {@link Vector}).
|
||||
*/
|
||||
public DirectionalVector(Vector v) {
|
||||
this(v.getX(), v.getY(), v.getZ());
|
||||
// this((v = v.clone().normalize()).getX(), v.getY(), v.getZ());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private DirectionalVector(double x, double y, double z) {
|
||||
double vectSize = Math.sqrt(x*x + y*y + z*z);
|
||||
this.x = x/vectSize;
|
||||
this.y = y/vectSize;
|
||||
this.z = z/vectSize;
|
||||
|
||||
if (x == 0.0 && z == 0.0) {
|
||||
pitch = y > 0.0 ? PId2 : -PId2;
|
||||
yaw = 0;
|
||||
}
|
||||
else {
|
||||
yaw = Math.atan2(z, x);
|
||||
pitch = Math.atan(y / Math.sqrt(x*x + z*z));
|
||||
}
|
||||
}
|
||||
|
||||
private DirectionalVector(double x, double y, double z, double yaw, double pitch) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
private DirectionalVector(double yaw, double pitch) {
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
|
||||
y = Math.sin(pitch);
|
||||
|
||||
double cosPitch = Math.cos(pitch);
|
||||
x = cosPitch * Math.cos(yaw);
|
||||
z = cosPitch * Math.sin(yaw);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Vector toVector() {
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the yaw and the pitch of the provided {@link Location}
|
||||
* with the values inside the current {@link DirectionalVector}
|
||||
* after conversion of these values
|
||||
*/
|
||||
public void putIntoLocation(Location l) {
|
||||
/* std : -PI/2 : <0 ? +2PI : MC
|
||||
* South (+z) = PI/2 : 0 : 0 : 0, 360
|
||||
* West (-x) = ±PI : -3PI/2 - PI/2 : PI/2 : 90
|
||||
* North (-z) = -PI/2 : -PI : PI : 180
|
||||
* East (+x) = 0 : -PI/2 : 3PI/2 : 270
|
||||
*/
|
||||
l.setYaw((float)Math.toDegrees(yaw < PId2 ? yaw + PIx2 - PId2 : yaw - PId2));
|
||||
l.setPitch((float)Math.toDegrees(-pitch));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public DirectionalVector getOpposite() {
|
||||
return new DirectionalVector(
|
||||
-x,
|
||||
-y,
|
||||
-z,
|
||||
(yaw > 0 ? (yaw - PI) : (yaw + PI)),
|
||||
-pitch
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current direction is the player face direction,
|
||||
* this method return the direction of the back of the head.
|
||||
* This is an alias of {@link #getOpposite()}
|
||||
*/
|
||||
public DirectionalVector getBackDirection() {
|
||||
return getOpposite();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current direction is the player face direction,
|
||||
* this method return the direction of the bottom of the head.
|
||||
*/
|
||||
public DirectionalVector getBottomDirection() {
|
||||
return new DirectionalVector(
|
||||
(pitch > 0 ? yaw : (yaw > 0 ? (yaw - PI) : (yaw + PI))),
|
||||
(pitch > 0 ? (pitch - PId2) : (-PId2 - pitch))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current direction is the player face direction,
|
||||
* this method return the direction of the top of the head.
|
||||
*/
|
||||
public DirectionalVector getTopDirection() {
|
||||
return new DirectionalVector(
|
||||
(pitch < 0 ? yaw : (yaw > 0 ? (yaw - PI) : (yaw + PI))),
|
||||
(pitch < 0 ? (pitch + PId2) : (PId2 - pitch))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If the current direction is the player face direction,
|
||||
* this method return the direction of the left of the head.
|
||||
*/
|
||||
public DirectionalVector getLeftDirection() {
|
||||
return new DirectionalVector(
|
||||
yaw > -PId2 ? (yaw - PId2) : (yaw - PId2 + PIx2),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If the current direction is the player face direction,
|
||||
* this method return the direction of the right of the head.
|
||||
*/
|
||||
public DirectionalVector getRightDirection() {
|
||||
return new DirectionalVector(
|
||||
yaw < PId2 ? (yaw + PId2) : (yaw + PId2 - PIx2),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,192 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import fr.pandacube.lib.chat.Chat.FormatableChat;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.text.format.TextDecoration.State;
|
||||
|
||||
public class ItemStackBuilder {
|
||||
|
||||
/**
|
||||
* Create a builder with a clone of the provided ItemStack.
|
||||
*
|
||||
* The returned builder will not alter the provided ItemStack.
|
||||
* IF you want to modify the ItemStack with the builder, please use {@link #wrap(ItemStack)}.
|
||||
*
|
||||
* @param base the original ItemStack.
|
||||
* @return the builder
|
||||
*/
|
||||
public static ItemStackBuilder of(ItemStack base) {
|
||||
return wrap(base.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder of a new ItemStack with the specified Material.
|
||||
*
|
||||
* @param mat the material of the new builded ItemStack
|
||||
* @return the builder
|
||||
*/
|
||||
public static ItemStackBuilder of(Material mat) {
|
||||
return wrap(new ItemStack(mat));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder that will alter the data of the provided ItemStack.
|
||||
*
|
||||
* The {@link #build()} method of thez returned builder will return the same instance
|
||||
* of ItemStack as the parameter of this method.
|
||||
*
|
||||
* To create a builder that doesn’t modify the provided ItemStack, use {@link #of(ItemStack)}.
|
||||
* @return the builder
|
||||
*/
|
||||
public static ItemStackBuilder wrap(ItemStack stack) {
|
||||
return new ItemStackBuilder(stack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private final ItemStack stack;
|
||||
private ItemMeta cachedMeta;
|
||||
|
||||
private ItemStackBuilder(ItemStack base) {
|
||||
stack = base;
|
||||
}
|
||||
|
||||
private ItemMeta getOrInitMeta() {
|
||||
return (cachedMeta != null) ? cachedMeta : (cachedMeta = stack.getItemMeta());
|
||||
}
|
||||
|
||||
private void updateMeta() {
|
||||
stack.setItemMeta(cachedMeta);
|
||||
}
|
||||
|
||||
public ItemStackBuilder amount(int a) {
|
||||
stack.setAmount(a);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder rawDisplayName(Component displayName) {
|
||||
getOrInitMeta().displayName(displayName);
|
||||
updateMeta();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder displayName(Chat displayName) {
|
||||
if (displayName != null) {
|
||||
if (displayName.getAdv().style().decoration(TextDecoration.ITALIC) == State.NOT_SET)
|
||||
((FormatableChat)displayName).italic(false);
|
||||
return rawDisplayName(displayName.getAdv());
|
||||
}
|
||||
else
|
||||
return rawDisplayName(null);
|
||||
}
|
||||
|
||||
public ItemStackBuilder rawLore(List<Component> lore) {
|
||||
getOrInitMeta().lore(lore);
|
||||
updateMeta();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder lore(List<Chat> lore) {
|
||||
if (lore != null) {
|
||||
return rawLore(lore.stream()
|
||||
.map(line -> Chat.italicFalseIfNotSet(line).getAdv())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
else
|
||||
return rawLore(Collections.emptyList());
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLoreAfter(List<Chat> lores) {
|
||||
if (lores != null) {
|
||||
List<Component> baseLore = getOrInitMeta().lore();
|
||||
if (baseLore == null) baseLore = Collections.emptyList();
|
||||
return rawLore(
|
||||
Streams.concat(
|
||||
baseLore.stream(),
|
||||
lores.stream()
|
||||
.map(line -> Chat.italicFalseIfNotSet(line).getAdv())
|
||||
)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLoreAfter(Chat... lores) {
|
||||
if (lores == null || lores.length == 0)
|
||||
return this;
|
||||
return addLoreAfter(Arrays.asList(lores));
|
||||
}
|
||||
|
||||
public ItemStackBuilder enchant(Enchantment ench, int level) {
|
||||
getOrInitMeta().addEnchant(ench, level, true);
|
||||
updateMeta();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder flags(ItemFlag... flags) {
|
||||
getOrInitMeta().addItemFlags(flags);
|
||||
updateMeta();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder hideEnchants() {
|
||||
return flags(ItemFlag.HIDE_ENCHANTS);
|
||||
}
|
||||
|
||||
public ItemStackBuilder hideAttributes() {
|
||||
return flags(ItemFlag.HIDE_ATTRIBUTES);
|
||||
}
|
||||
|
||||
public ItemStackBuilder fakeEnchant() {
|
||||
enchant(Enchantment.DURABILITY, 1);
|
||||
return hideEnchants();
|
||||
}
|
||||
|
||||
public ItemStackBuilder damage(int d) {
|
||||
ItemMeta m = getOrInitMeta();
|
||||
if (m instanceof Damageable)
|
||||
((Damageable)m).setDamage(d);
|
||||
updateMeta();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public ItemStack build() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,177 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldBorder;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import fr.pandacube.lib.util.RandomUtil;
|
||||
import fr.pandacube.lib.paper.PandaLibPaper;
|
||||
|
||||
public class LocationUtil {
|
||||
|
||||
public static String conciseToString(Location loc) {
|
||||
String world = loc.getWorld() == null ? "null" : loc.getWorld().getName();
|
||||
return "(" + world + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ() + ")";
|
||||
}
|
||||
/**
|
||||
* Return a random secure location in the provided world, inside the current
|
||||
* WorldBorder. Will be on the surface, for non-nether world, or below the roof of the nether world
|
||||
* @param w the world in which to pick a location
|
||||
* @param extraSecureCheck provides extra checks to determine location security
|
||||
*/
|
||||
public static CompletableFuture<Location> getRandomSecureLocation(World w, Predicate<Location> extraSecureCheck) {
|
||||
|
||||
WorldBorder wb = w.getWorldBorder();
|
||||
|
||||
Location minWorld = wb.getCenter().clone().add(-wb.getSize()/2, 0, -wb.getSize()/2);
|
||||
Location maxWorld = wb.getCenter().clone().add(wb.getSize()/2, 0, wb.getSize()/2);
|
||||
|
||||
return getRandomSecureLocation(w, minWorld, maxWorld, extraSecureCheck);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static final int maxTryBeforeCancelRandomLocation = 75;
|
||||
public static CompletableFuture<Location> getRandomSecureLocation(World w, Location min, Location max, Predicate<Location> extraSecureCheck) {
|
||||
|
||||
CompletableFuture<Location> future = new CompletableFuture<>();
|
||||
|
||||
AtomicReference<BukkitTask> t = new AtomicReference<>();
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
t.set(Bukkit.getScheduler().runTaskTimer(PandaLibPaper.getPlugin(), () -> {
|
||||
|
||||
count.incrementAndGet();
|
||||
if (count.get() > maxTryBeforeCancelRandomLocation) {
|
||||
future.complete(null);
|
||||
t.get().cancel();
|
||||
}
|
||||
|
||||
// generate a random (x,z) coordinate
|
||||
Location ret = new Location(w,
|
||||
RandomUtil.nextIntBetween(min.getBlockX(), max.getBlockX()) + 0.5,
|
||||
w.getMaxHeight() - 1,
|
||||
RandomUtil.nextIntBetween(min.getBlockZ(), max.getBlockZ()) + 0.5);
|
||||
|
||||
// find a secure y value
|
||||
ret = getSecureLocationOrNull(ret);
|
||||
|
||||
if (ret == null)
|
||||
// there is no secure y position for the provided (x,z) values
|
||||
return;
|
||||
|
||||
if (extraSecureCheck != null && !extraSecureCheck.test(ret))
|
||||
return; // extra checks didn’t validate the location
|
||||
|
||||
//if (checkCubo && PandacubePaper.getPlugin().cuboManager != null)
|
||||
// if (PandacubePaper.getPlugin().cuboManager.getCuboFromLocation(ret) != null)
|
||||
// return; // il y a un cubo à l'endroit aléatoire sélectionnée
|
||||
|
||||
// tout est bon
|
||||
future.complete(ret);
|
||||
t.get().cancel();
|
||||
|
||||
}, 1, 1));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param l the source location
|
||||
* @return a secure location with the same X and Z coordinate as the
|
||||
* provided location, but Y modified to ensure security for player
|
||||
* who will be teleported to this location.
|
||||
* May return null if it is impossible to securize find a secure location.
|
||||
*/
|
||||
public static Location getSecureLocationOrNull(Location l) {
|
||||
l = l.clone();
|
||||
l.setY(l.getWorld().getEnvironment() == Environment.NETHER ? 126 : 256);
|
||||
Block b = l.getBlock();
|
||||
|
||||
while (b.getY() >= 0 && !currPosSafe(b))
|
||||
b = b.getRelative(BlockFace.DOWN);
|
||||
|
||||
return currPosSafe(b) ? b.getLocation().add(0.5, 0, 0.5) : null;
|
||||
|
||||
}
|
||||
|
||||
public static boolean currPosSafe(Block b) {
|
||||
return b.getY() >= b.getWorld().getMinHeight() + 1 && b.getY() <= b.getWorld().getMaxHeight()
|
||||
&& isSecureFloor(b.getRelative(BlockFace.DOWN))
|
||||
&& isAir(b)
|
||||
&& isAir(b.getRelative(BlockFace.UP));
|
||||
}
|
||||
|
||||
public static boolean isAir(Block b) { return b.getType() == Material.AIR; }
|
||||
public static boolean isSecureFloor(Block b) { return !isAir(b) && !dangerousBlocks.contains(b.getType()); }
|
||||
|
||||
public static final Set<Material> dangerousBlocks = EnumSet.of(
|
||||
Material.LAVA,
|
||||
Material.WATER,
|
||||
Material.COBWEB,
|
||||
Material.MAGMA_BLOCK,
|
||||
Material.CAMPFIRE,
|
||||
Material.SOUL_CAMPFIRE,
|
||||
Material.FIRE,
|
||||
Material.SOUL_FIRE,
|
||||
Material.WITHER_ROSE,
|
||||
Material.END_PORTAL,
|
||||
Material.NETHER_PORTAL,
|
||||
Material.END_GATEWAY
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the {@link Location} l is inside the cuboïd formed by the 2 others
|
||||
* Locations min and max.
|
||||
* @return true if l is inside the cuboid min-max
|
||||
*/
|
||||
public static boolean isIn(Location l, Location min, Location max) {
|
||||
return (l.getWorld().equals(min.getWorld()) && l.getWorld().equals(max.getWorld()) && l.getX() >= min.getX()
|
||||
&& l.getX() <= max.getX() && l.getY() >= min.getY() && l.getY() <= max.getY() && l.getZ() >= min.getZ()
|
||||
&& l.getZ() <= max.getZ());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a new location based on the linear interpolation between p0 and p1, according to the value c.
|
||||
* @param c between 0 and 1. If 0, it returns p0 and if 1, returns p1. Other finite numbers are allowed, but the returned location wont be part of the {@code [p0;p1]} segment.
|
||||
* @return The location, linearly interpolated between p0 and p1 with the value c. The yaw and pitch in the returned location are those of p0.
|
||||
* @throws IllegalArgumentException if the provided locations are not in the same world.
|
||||
*/
|
||||
public static Location lerp(Location p0, Location p1, float c) {
|
||||
return p0.clone().add(p1.clone().subtract(p0).multiply(c));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.type.Sign;
|
||||
import org.bukkit.block.data.type.WallSign;
|
||||
|
||||
public class MaterialUtil {
|
||||
|
||||
public static boolean isSign(Material m) {
|
||||
return WallSign.class.equals(m.data) || Sign.class.equals(m.data);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ScoreboardUtil {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Component title, Component[] lines) {
|
||||
|
||||
Objective obj = scBrd.getObjective("sidebar_autogen");
|
||||
if (obj != null && !obj.getCriteria().equalsIgnoreCase("dummy")) {
|
||||
// objective present but with wrong criteria, removing it
|
||||
obj.unregister();
|
||||
obj = null;
|
||||
}
|
||||
|
||||
|
||||
if (obj == null) {
|
||||
obj = scBrd.registerNewObjective("sidebar_autogen", "dummy", title);
|
||||
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
}
|
||||
else {
|
||||
// only update title if needed
|
||||
if (!title.equals(obj.displayName())) {
|
||||
obj.displayName(title);
|
||||
}
|
||||
// fix display slot if someone else changed it
|
||||
if (DisplaySlot.SIDEBAR != obj.getDisplaySlot()) {
|
||||
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
}
|
||||
}
|
||||
|
||||
ChatColor[] colors = ChatColor.values();
|
||||
|
||||
/*
|
||||
* Scanning lines from last to first, keeping only the 15 first lines
|
||||
*/
|
||||
int score = 1, i = 0;
|
||||
for (int lineIndex = Math.min(lines.length, 15) - 1; lineIndex >= 0; i++, score++, lineIndex--) {
|
||||
String teamId = "sidebar_team" + score;
|
||||
String sbEntry = colors[i].toString();
|
||||
Team tLine = scBrd.getTeam(teamId);
|
||||
if (tLine == null) {
|
||||
tLine = scBrd.registerNewTeam(teamId);
|
||||
}
|
||||
if (!tLine.hasEntry(sbEntry)) {
|
||||
tLine.addEntry(sbEntry);
|
||||
}
|
||||
|
||||
if (!tLine.prefix().equals(lines[lineIndex])) {
|
||||
tLine.prefix(lines[lineIndex]);
|
||||
}
|
||||
|
||||
Score scoreEntry = obj.getScore(sbEntry);
|
||||
if (scoreEntry.getScore() != score) {
|
||||
scoreEntry.setScore(score);
|
||||
}
|
||||
}
|
||||
|
||||
// clean older data when we are reducing the number of line displayed
|
||||
for (; i < colors.length; i++, score++) {
|
||||
String teamId = "sidebar_team" + score;
|
||||
String sbEntry = colors[i].toString();
|
||||
|
||||
if (obj.getScore(sbEntry).isScoreSet()) {
|
||||
scBrd.resetScores(sbEntry);
|
||||
}
|
||||
|
||||
Team tLine = scBrd.getTeam(teamId);
|
||||
if (tLine != null && !tLine.prefix().equals(Component.empty())) {
|
||||
tLine.prefix(Component.empty());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Chat title, Chat[] lines) {
|
||||
Component[] cmpLines = new Component[lines.length];
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
cmpLines[i] = lines[i].getAdv();
|
||||
}
|
||||
updateScoreboardSidebar(scBrd, title.getAdv(), cmpLines);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Chat title, List<Chat> lines) {
|
||||
Component[] cmpLines = new Component[lines.size()];
|
||||
for (int i = 0; i < cmpLines.length; i++) {
|
||||
cmpLines[i] = lines.get(i).getAdv();
|
||||
}
|
||||
updateScoreboardSidebar(scBrd, title.getAdv(), cmpLines);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,191 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
|
||||
/**
|
||||
* Represents some special mob heads, also support creating player skulls and custom skulls.
|
||||
*
|
||||
* @author xigsag, SBPrime
|
||||
*
|
||||
* @see <a href="https://github.com/TigerHix/Hex-Utils/blob/9954159a323d12733b29c287a56980991cee2948/hex/util/Skull.java">github.com/TigerHix/Hex-Utils/hex/util/Skull.java</a>
|
||||
*/
|
||||
public enum Skull {
|
||||
|
||||
ARROW_LEFT("MHF_ArrowLeft"),
|
||||
ARROW_RIGHT("MHF_ArrowRight"),
|
||||
ARROW_UP("MHF_ArrowUp"),
|
||||
ARROW_DOWN("MHF_ArrowDown"),
|
||||
QUESTION("MHF_Question"),
|
||||
EXCLAMATION("MHF_Exclamation"),
|
||||
CAMERA("FHG_Cam"),
|
||||
|
||||
ZOMBIE_PIGMAN("MHF_PigZombie"),
|
||||
PIG("MHF_Pig"),
|
||||
SHEEP("MHF_Sheep"),
|
||||
BLAZE("MHF_Blaze"),
|
||||
CHICKEN("MHF_Chicken"),
|
||||
COW("MHF_Cow"),
|
||||
SLIME("MHF_Slime"),
|
||||
SPIDER("MHF_Spider"),
|
||||
SQUID("MHF_Squid"),
|
||||
VILLAGER("MHF_Villager"),
|
||||
OCELOT("MHF_Ocelot"),
|
||||
HEROBRINE("MHF_Herobrine"),
|
||||
LAVA_SLIME("MHF_LavaSlime"),
|
||||
MOOSHROOM("MHF_MushroomCow"),
|
||||
GOLEM("MHF_Golem"),
|
||||
GHAST("MHF_Ghast"),
|
||||
ENDERMAN("MHF_Enderman"),
|
||||
CAVE_SPIDER("MHF_CaveSpider"),
|
||||
|
||||
CACTUS("MHF_Cactus"),
|
||||
CAKE("MHF_Cake"),
|
||||
CHEST("MHF_Chest"),
|
||||
MELON("MHF_Melon"),
|
||||
LOG("MHF_OakLog"),
|
||||
PUMPKIN("MHF_Pumpkin"),
|
||||
TNT("MHF_TNT"),
|
||||
DYNAMITE("MHF_TNT2");
|
||||
|
||||
private final String name;
|
||||
|
||||
Skull(String mcName) {
|
||||
name = mcName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the item based on this Skull enum.
|
||||
*
|
||||
* @return itemstack
|
||||
*/
|
||||
public ItemStack get() {
|
||||
return get(null, null);
|
||||
}
|
||||
/**
|
||||
* Return the item based on this Skull enum, with the provided display name and lore.
|
||||
*
|
||||
* @return itemstack
|
||||
*/
|
||||
public ItemStack get(Chat dispName, List<Chat> lore) {
|
||||
return getFromPlayerName(name, dispName, lore);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull of a player based on his name.
|
||||
*
|
||||
* @param name player's name
|
||||
* @return itemstack
|
||||
*/
|
||||
public static ItemStack getFromPlayerName(String name, Chat dispName, List<Chat> lore) {
|
||||
ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
||||
|
||||
@SuppressWarnings({ "deprecation", "unused" })
|
||||
boolean b = meta.setOwner(name);
|
||||
|
||||
if (dispName != null)
|
||||
meta.displayName(dispName.getAdv());
|
||||
|
||||
if (lore != null)
|
||||
meta.lore(lore.stream().map(Chat::getAdv).collect(Collectors.toList()));
|
||||
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by url.
|
||||
*
|
||||
* @param url skin url
|
||||
* @return itemstack
|
||||
*/
|
||||
public static ItemStack getFromSkinURL(String url) {
|
||||
return getFromSkinURL(url, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by url.
|
||||
*
|
||||
* @param url skin url
|
||||
* @return itemstack
|
||||
*/
|
||||
public static ItemStack getFromSkinURL(String url, Chat name, List<Chat> lore) {
|
||||
return getFromBase64String(Base64.getEncoder().encodeToString(String.format("{textures:{SKIN:{url:\"%s\"}}}", url).getBytes()), name, lore);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by a base64 String.
|
||||
*
|
||||
* @param str the base64 string from gameprofile informations
|
||||
* @return itemstack
|
||||
*/
|
||||
public static ItemStack getFromBase64String(String str) {
|
||||
return getFromBase64String(str, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by a base64 String.
|
||||
*
|
||||
* @param str the base64 string from gameprofile informations
|
||||
* @return itemstack
|
||||
*/
|
||||
public static ItemStack getFromBase64String(String str, Chat dispName, List<Chat> lore) {
|
||||
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
|
||||
SkullMeta headMeta = (SkullMeta) head.getItemMeta();
|
||||
|
||||
PlayerProfile profile = Bukkit.createProfile(UUID.randomUUID());
|
||||
profile.setProperty(new ProfileProperty("textures", str));
|
||||
headMeta.setPlayerProfile(profile);
|
||||
|
||||
if (dispName != null)
|
||||
headMeta.displayName(dispName.getAdv());
|
||||
|
||||
if (lore != null)
|
||||
headMeta.lore(lore.stream().map(Chat::getAdv).collect(Collectors.toList()));
|
||||
|
||||
head.setItemMeta(headMeta);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user