Skip to content
Aki edited this page Jul 11, 2018 · 1 revision

Plugins use CraftBukkit by casting instances of Bukkit API interfaces to concrete CraftBukkit implementations. A plugin would for instance cast a Player to a CraftPlayer but that does not work on Glowstone. If you've got a Player instance on Glowstone, then it will not be implemented by CraftPlayer. It's implemented by GlowPlayer.

Linkstone provides NMS/OBC classes that are wrappers/boxes around Glowstone classes. These wrappers are annotation with a @LBox annotation. When ever a value is casted to one of these annotated classes, the cast gets replaced against wrapping the object into that box.

Here's an example box class:

// The annotation tell the Linkstone framework,
// that this class is a box that wraps GlowPlayers.
@LBox(GlowPlayer.class)
public class CraftPlayer {
    // The @LBoxed annotation must be attached to the field that contains the wrapped value.
    // The toString, hashCode and equals method are delegated to that field.
    @LBoxed
    private final GlowPlayer glow;

    public CraftPlayer(GlowPlayer glow) {
        this.glow = glow;
    }
}

If a plugin contains a cast to the CraftPlayer class, it will get replaced against wrapping the object into the CraftBukkit box.

Initializing a box

Boxes should not be initialized by using the new keyword since all box instances are stored in a global cache. Use the Linkstone.<TypeToBox>box(objectToBox) instead.

Here's an exemplary implementation for the getHandle method in CraftPlayer.
It wraps the GlowPlayer in an EntityPlayer box.

public EntityPlayer getHandle() {
    // We could drop the type parameter since the
    // java compiler is able to interfere it.
    return Linkstone.<EntityPlayer>box(glow);
}