I'm having some trouble with getting event handlers to run only on the client. My mod has a number of them that but here I'll just give code for one of them as an example.
For example, I would like to print a chat message when a certain entity spawns. To do this I am subscribing to a Forge event like so:
// register the event listener
MinecraftForge.EVENT_BUS.register(this);
@ForgeSubscribe
@SideOnly(Side.CLIENT) // <-- shouldn't this prevent Forge from calling this on the server side?
public void onEntitySpawn(EntityJoinWorldEvent event) {
// check for specific entity, print chat message here
}
What I expect to happen is to see exactly one chat message printed when the entity spawns. However, what actually happens is I see two messages printed. From examining the callstack, I can see that one call comes from net.minecraft.server.* and the other call comes from net.minecraft.client.*. (This is on a singleplayer world. If I join a server then code works fine and the message prints just once.)
So, my first question is: Does @SideOnly(Side.CLIENT) not work here? Shouldn't it make my method only be called on the client side?
I did some more research and read that I might need to use a "Proxy" to separate client/server behavior. I changed my code to the below:
@SidedProxy(clientSide = "com.example.MyMod$ClientEventProxy", serverSide = "com.example.MyMod$BaseEventProxy")
public static BaseEventProxy proxy;
public static class BaseEventProxy {
public void registerForEvents() {}
}
public static class ClientEventProxy extends BaseEventProxy {
public void registerForEvents() {
MinecraftForge.EVENT_BUS.register(this);
}
@ForgeSubscribe
@SideOnly(Side.CLIENT) // This probably does nothing, but I left it here anyways
public void onEntitySpawn(EntityJoinWorldEvent event) {
// check for specific entity, print chat message here
}
}
However, this doesn't make any difference. I still see the message being printed twice. (And, having read this, that makes sense. Basically, it says that the client/server proxy is for mods that can run on both the dedicated server and the client with integrated server.)
So, my second question is: Given that @SidedProxy doesn't do what I require, how can I make Forge only call my event listener once, on the client side only? (I did do some more research into this and it looks like I can check either FMLCommonHandler.instance().getEffectiveSide() or World.isRemote but is that the best practice?)