Войти или зарегистрироваться

[resolved]KCauldron reflection

  • Автор темы Автор темы MOR_IV
  • Дата начала Дата начала
Статус
Закрыто для дальнейших ответов.

MOR_IV

Активный участник
Пользователь
Баллы
88
Имя в Minecraft
MOR_IV
Значит имеем следующее:
Java:
public class ReflectionAPI {
    private boolean error;
    private String server = "net.minecraft.server.";
    private String craftbukkit = "org.bukkit.craftbukkit.";
    private Class<?> CraftWorld;
    private Class<?> CraftItemStack;
 
    private Class<?> ItemStack;
    private Class<?> NBTTagCompound;
    private Class<?> TileEntity;
    private boolean forge = false;
 
    public ReflectionAPI() {
        error = false;
        load();
    }
 
    private void load() {
        String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3] + ".";
        ggg();
        loadClass();
        loadMethods();
    }

    private void ggg() {
        if(Bukkit.getServer()!=null) {
            if(Bukkit.getVersion().contains("MCPC")||Bukkit.getVersion().contains("Forge")) forge = true;
            Server server = Bukkit.getServer();
            Class<?> bukkitServerClass = server.getClass();
            String[] pas = bukkitServerClass.getName().split("\\.");
            if (pas.length == 5) {
                String verB = pas[3];
                craftbukkit += verB;
            }
            try {
                Method getHandle = bukkitServerClass.getDeclaredMethod("getHandle");
                Object handle = getHandle.invoke(server);
                Class<? extends Object> handleServerClass = handle.getClass();
                pas = handleServerClass.getName().split("\\.");
                if (pas.length == 5) {
                    String verM = pas[3];
                    this.server += verM;
                }
                Bukkit.getLogger().info(this.server);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void loadClass() {
        String name;
        name = craftbukkit + ".CraftWorld";
        CraftWorld = getNMSClass(name);
        name = craftbukkit + ".inventory.CraftItemStack";
        CraftItemStack = getNMSClass(name);
       
        name = server + ".ItemStack";
        ItemStack = getNMSClass(name);
        name = server + ".NBTTagCompound";
        NBTTagCompound = getNMSClass(name);
        name = server + ".TileEntity";
        TileEntity = getNMSClass(name);
    }
    private Class<?> getNMSClass(String name){
        Bukkit.getLogger().info("-------------------------   " + name);
        Class<?> nmsClass = null;
        try {
            nmsClass = Class.forName(name);
        } catch (ClassNotFoundException e) {
            Bukkit.getLogger().info("+++++++++++++++++++++++   " + name);
            e.printStackTrace();
            error = true;
        }
        if(nmsClass != null)
            Bukkit.getLogger().info(nmsClass.getName());
        return nmsClass;
    }
}

Это тестовый код, поэтому не судить строго.
Так вот прикол в том, что на spigot все работает отлично.
а вот на KCaudron у меня дебаг пишет что срабатывает getNMSClass(String name) со значением name = net.minecraft.server.dedicated.ItemSrack
далее NullPointerExceprion и даже трасировку не дает. Могу предположить что
catch (ClassNotFoundException e) {
Bukkit.getLogger().info("+++++++++++++++++++++++ " + name);
e.printStackTrace();
не выполняется...
Помогите разобраться
 
Последнее редактирование:
Написал Это. Опять же на спиготе робит нормально.
На KCauldron говорит java.lang.NoSuchMethodException: net.minecraft.item.ItemStack.getTag()
То есть CraftItemStack.asNMSCopy(org.*********ventory.ItemStack) возвращает экземпляр класса net.minecraft.item.ItemStack, в котором отсутствует метод getTag();
Почему так - не понятно.
Java:
public String getTags(org.*********ventory.ItemStack item){
        if(item == null | item.getType().equals(Material.AIR)) return Strings.NULL_NBT;
        String s = Strings.NULL_NBT;
        try {
            Object craftStack = asNMSCopy.invoke(CraftItemStack, new Object[] {item});
            Object tag = getMethod(craftStack.getClass(), "getTag", new Class[] {}).invoke(craftStack, new Object[] {});
            if(tag == null) return Strings.NULL_NBT;
            Bukkit.getLogger().info(tag.getClass().getName());
            Method toString = getMethod(tag.getClass(), "toString", new Class[] {});
        
            s = (String) toString.invoke(tag,  new Object[] {});
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return s;
    }
 
Последнее редактирование:
Приведи полный stack trace из консоли во время ошибки.
И да, пользуйся, пожалуйста, тегов CODE=Java для корректной подсветки синтаксиса блока с кодом. Спасибо :)
 
Последнее редактирование:
Приведи полный stack trace из консоли во время ошибки.
И да, пользуйся, пожалуйста, тегов CODE=Java для корректной подсветки синтаксиса блока с кодом.
Ок, но через сутки. Я на работе
Так вот как обещал:
Java:
package ru.mor.iv.mineblocker.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;

import ru.mor.iv.mineblocker.utils.Strings;

public class ReflectionAPI {
    private boolean error;
    private String server = "net.minecraft.server.";
    private String craftbukkit = "org.bukkit.craftbukkit.";

    public ReflectionAPI() {
        error = false;
        load();
    }

    private void load() {
        if(Bukkit.getServer()!=null) {
            Server server = Bukkit.getServer();
            Class<?> bukkitServerClass = server.getClass();
            String[] pas = bukkitServerClass.getName().split("\\.");
            if (pas.length == 5) {
                String verB = pas[3];
                craftbukkit += verB;
            }
            try {
                Method getHandle = bukkitServerClass.getDeclaredMethod("getHandle");
                Object handle = getHandle.invoke(server);
                Class<? extends Object> handleServerClass = handle.getClass();
                pas = handleServerClass.getName().split("\\.");
                if (pas.length == 5) {
                    String verM = pas[3];
                    this.server += verM;
                }
                Bukkit.getLogger().info(this.server);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public String getTags(org.*********ventory.ItemStack item){
        if(item == null | item.getType().equals(Material.AIR)) return Strings.NULL_NBT;
        String s = Strings.NULL_NBT;
        /**/    log(org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.class.getName());
        net.minecraft.server.v1_7_R4.ItemStack is = org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack.asNMSCopy(item);
   
        /**/    log(is.getClass().getName());
        net.minecraft.server.v1_7_R4.NBTTagCompound nbt = is.getTag();
        /**/        log(nbt.getClass().getName());
        if(nbt !=null){
            /**/    log(nbt.toString());
        }
        try {
            String name = craftbukkit + ".inventory.CraftItemStack";
            Class<?> craftItemStack = Class.forName(name);
            /**/    log("ref " + craftItemStack.getName());
            Class[] paramTypes = new Class[] { org.*********ventory.ItemStack.class };
       
            Object craftStack = craftItemStack.getMethod("asNMSCopy",  paramTypes).invoke(craftItemStack, new Object[] {item});
            /**/    log("ref " + craftStack.getClass().getName());
            Object tag = craftStack.getClass().getMethod("getTag", new Class[] {}).invoke(craftStack, new Object[] {});
            if(tag == null) return Strings.NULL_NBT;
            /**/    log("ref " + tag.getClass().getName());
            Method toString = tag.getClass().getMethod("toString", new Class[] {});
            s = (String) toString.invoke(tag,  new Object[] {});
        } catch (NoSuchMethodException | SecurityException | ClassNotFoundException |
                IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
   
   
   
        return "ref " + s;
    }
Код:
[10:06:26] [Server thread/INFO]: org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack
[10:06:26] [Server thread/INFO]: net.minecraft.server.v1_7_R4.ItemStack
[10:06:26] [Server thread/INFO]: net.minecraft.server.v1_7_R4.NBTTagCompound
[10:06:26] [Server thread/INFO]: {ench:[0:{lvl:1s,id:32s,},],}
[10:06:26] [Server thread/INFO]: ref org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack
[10:06:26] [Server thread/INFO]: ref net.minecraft.server.v1_7_R4.ItemStack
[10:06:26] [Server thread/INFO]: ref net.minecraft.server.v1_7_R4.NBTTagCompound
Код:
[09:47:31] [Server thread/INFO]: org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack
[09:47:31] [Server thread/INFO]: net.minecraft.item.ItemStack
[09:47:31] [Server thread/INFO]: net.minecraft.nbt.NBTTagCompound
[09:47:31] [Server thread/INFO]: {laserSetting:1,charge:294000.0d}
[09:47:31] [Server thread/INFO]: ref org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack
[09:47:31] [Server thread/INFO]: ref net.minecraft.item.ItemStack
[09:47:31] [Server thread/WARN]: java.lang.NoSuchMethodException: net.minecraft.item.ItemStack.getTag()
[09:47:31] [Server thread/WARN]:     at java.lang.Class.getMethod(Unknown Source)
[09:47:31] [Server thread/WARN]:     at ru.mor.iv.mineblocker.reflection.ReflectionAPI.getTags(ReflectionAPI.java:67)
[09:47:31] [Server thread/WARN]:     at ru.mor.iv.mineblocker.command.CommandMB.onCommand(CommandMB.java:44)
[09:47:31] [Server thread/WARN]:     at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
[09:47:31] [Server thread/WARN]:     at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:181)
[09:47:31] [Server thread/WARN]:     at org.bukkit.craftbukkit.v1_7_R4.CraftServer.dispatchCommand(CraftServer.java:717)
[09:47:31] [Server thread/WARN]:     at net.minecraft.network.NetHandlerPlayServer.func_147361_d(NetHandlerPlayServer.java:1317)
[09:47:31] [Server thread/WARN]:     at net.minecraft.network.NetHandlerPlayServer.func_147354_a(NetHandlerPlayServer.java:1099)
[09:47:31] [Server thread/WARN]:     at net.minecraft.network.play.client.C01PacketChatMessage.func_148833_a(C01PacketChatMessage.java:38)
[09:47:31] [Server thread/WARN]:     at net.minecraft.network.play.client.C01PacketChatMessage.func_148833_a(C01PacketChatMessage.java:53)
[09:47:31] [Server thread/WARN]:     at net.minecraft.network.NetworkManager.func_74428_b(NetworkManager.java:245)
[09:47:31] [Server thread/WARN]:     at net.minecraft.network.NetworkSystem.func_151269_c(NetworkSystem.java:173)
[09:47:31] [Server thread/WARN]:     at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:991)
[09:47:31] [Server thread/WARN]:     at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:431)
[09:47:31] [Server thread/WARN]:     at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:809)
[09:47:31] [Server thread/WARN]:     at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:669)
[09:47:31] [Server thread/WARN]:     at java.lang.Thread.run(Unknown Source)

Так вот забава - если внимательно вчитаться в коде я сначала вызываю прямую ссылку на net.minecraft.server.v1_7_R4, а калдрон говорит это классы net.minecraft, причем по прямой ссылке он отлично выполняет getTag() у net.minecraft.item.ItemStack, а через ref говорит такого нет.
Я пробежался по методам, сделал toString к каждому. Так вот смотрим:
Spigot:
Java:
net.minecraft.server.v1_7_R4.ItemStack
public net.minecraft.server.v1_7_R4.NBTTagCompound net.minecraft.server.v1_7_R4.ItemStack.getTag()
То есть метод getTag() возвращает NBTTagCompound. Все ок.

KCauldron:
Java:
net.minecraft.item.ItemStack
public net.minecraft.nbt.NBTTagCompound net.minecraft.item.ItemStack.func_77978_p()
То есть единственный(проверил внимательно) метод аналог, который возвращает NBTTagCompound - это func_77978_p().
Как так?
 
А вот так, основа nms kcauldron - forge, соответственно названия Nms классов и методов mcpшные. В котле есть какой-никакой ремаппер обращения к спайготовскому nms, но работает он только для прямого обращения, не через рефлексию.
 
не через рефлексию.
Как быть в моем случае? Есть идеи? Ручками писать проверку путей на наличие класса для каждой версии?
Я выкрутился частично из ситуации.
Берем одну известную, а именно класс CraftItemStack по имени. Потом при вызове метода getTags(ItemStack item) исследуем все классы, методы, возвращаемые значения по пути следования, сохраняя все в переменные значения классов и методов.
Ну вопрос еще решен не полностью. Мне еще много работать.
Вопрос решен. Я осилил рефлекцию для NBT block & stack
Спасибо.
 
Статус
Закрыто для дальнейших ответов.
Назад
Верх