-
Notifications
You must be signed in to change notification settings - Fork 3
How To Proxy
Creating NMS proxy classes is very simple, its just a matter of creating an interface with the right annotations and NMSPoxy will handle the rest. NMSProxy supports any class but is especially good at NMS & CraftBukkit/Spigot classes.
To start you will need an interface that extends NMSProxy
and is annotated with @NMSClass
. This is the marker to a
valid proxy class and tells the api the class type we will be proxying. When proxying NMS (NMSClass.Type.NMS
) and
CraftBukkit/Spigot (NMSClass.Type.CRAFTBUKKIT
) classes the api will automatically prefix the correct versioned package
to the provided class name to save you time. If implimenting something outside these bounds, you can insert %version%
into the class name and it will be replaced with the NMS version identifier used in many places in the bukkit ecosystem.
Next up is specifying methods and fields. For every method and field you want to access on the proxy instance you need
to add a method onto the interface with either a @NMSMethod
or @NMSField
on it. The return type can either be another
proxy class, the actual class type itself (useful for netty/game profile classes) or Object
for anything else and the
arguments can be proxy class instances or actual objects. This allows for the highest compatibility between real objects
and proxy class instances.
For any static methods/fields you must add a @NMSStatic
annotation. You can also add default methods which
will run as you expect.
@NMSClass(type = NMSClass.Type.CRAFTBUKKIT, className = "entity.CraftPlayer")
public interface NMSCraftPlayer implements NMSProxy {
default GameProfile getProfile() {
return getHandle().getProfile();
}
@NMSMethod
NMSEntityPlayer getHandle();
}
@NMSClass(type = NMSClass.Type.NMS, className = "EntityPlayer")
public interface NMSEntityPlayer implements NMSProxy {
@NMSField(type = NMSField.Type.GETTER)
NMSPlayerConnection playerConnection();
@NMSMethod
GameProfile getProfile();
}
Now that you have created your proxy classes, you can start to use them inside your plugin. First, get your plugins
instance of the NMSProxyProvider
using NMSProxyProvider.get(JavaPlugin plugin)
.
From there you have a 2 options to get a proxy instance. The first is to wrap a current object that you have on hand. To
do this you need to call NMSProxyProvider#getNMSObject(Class<? extends NMSProxy> proxyClass, Object object)
. This will
type check the object to the proxy class and hand you back a proxy class instance of the object. From there you can use
the object as normal.
The other option you have is to construct a NMS object from scratch. For this you need to call
NMSProxyProvider#constructNMSObject(Class<? extends NMSProxy> proxyClass, Object... args)
. This will call the
constructor on the proxied class type with the arguments you give it. You can use proxy instances as arguments and they
will be converted back to their original types when used in the constructor. From there everything works as normal.
If at anytime you need to get the original object back from the proxy instance, you can call NMSProxy#getProxyHandle()
on the proxy instance.
If you need to get a static instance of a class (you wont be able to use any methods/fields that arn't marked with
@NMSStatic
) you can call NMSProxyProvider#getStaticNMSObject(Class<? extends NMSProxy> proxyClass)
or
NMSProxy#getStaticProxyObject()
on a proxy instance of the same type. Static proxy instances will return null for
NMSProxy#getProxyHandle()
calls.
public class MyPlugin extends JavaPlugin implements Listener {
private NMSProxyProvider proxyProvider;
public void onEnable() {
proxyProvider = NMSProxyProvider.get(this);
this.getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
NMSCraftPlayer craftPlayer = proxyProvider.getNMSObject(NMSCraftPlayer.class, event.getPlayer());
GameProfile gameProfile = craftPlayer.getProfile();
// Use game profile/craft player proxy as needed.
}
}