Saturday, 1 February 2020

Minecraft Distributions (Client vs Dedicated Server) [1.14.4+]

Minecraft Distributions 
Historically, Minecraft actually shipped with two completely separate programs -
  • Dedicated Client - contained all the "client-side" code
  • Dedicated Server - contained all the "server-side" code
But then they figured out that it was pretty user-unfriendly for you to have to run the DedicatedServer if you wanted to play LAN multiplayer with your buddies, so they added an "Integrated Server" into the Client (the "open to LAN" feature) and made what I like to call the "CombinedClient".  (For some reason everyone else just calls it the "Client", which is a bit confusing I think).




This integrated server is used even when you're playing in single player mode.


The Dedicated Server is still available as a standalone program

So the two different Minecraft distributions are now:
  • CombinedClient (which has both client-side code and server-side code in it)
  • Dedicated Server (which has only server-side code).

The Forge authors wanted to make it easy to use the same Mod code in both the "Combined" Client and the Dedicated Server.  (This is not trivial because the Dedicated Server is missing the client-side code, and if your Mod attempts to call any of the client-side code when it's installed in the DedicatedServer, it will crash.)  Roughly half of the minecraft classes are in the client distribution only.

The way they do this is to call different events during startup.
  • The FMLCommonSetupEvent is called during startup for both the CombinedClient and DedicatedServer.
  • The FMLClientSetupEvent is called during startup of the CombinedClient only.


You just need to make sure that parts of your code which might run on the dedicated server never call any of the Client-code-only classes or methods.  These objects are marked with the @OnlyIn(Dist.CLIENT) annotation, eg

@OnlyIn(Dist.CLIENT)
public class Minecraft {

}

or

@OnlyIn(Dist.CLIENT)
public boolean hasCustomBreakingProgress(BlockState state) {
   return true;
}

A comment about @OnlyIn(Dist.CLIENT) objects - because of the way that Java loads classes, your server-side classes should not have any mention of @OnlyIn(Dist.CLIENT) vanilla objects whatsoever.  It doesn't matter whether the code is ever executed- simply having a Dist.CLIENT definition somewhere in your class is often enough to cause a crash on a DedicatedServer.  Create a dedicated client-side-only class to hold references to Dist.CLIENT class instances, and only instantiate your client-side-only class after checking whether you're on the server side or not.  You can do this with inheritance if you prefer; similar to the way that Block classes refer to World, and not directly to ClientWorld or ServerWorld.  The FMLClientSetupEvent (and FMLServerSetupEvent) can help to initialise these correctly.

No comments:

Post a Comment