Jump to content

How to debug dedicated server problems.


Jontom Xire

Recommended Posts

I have finally got around to setting up a dedicated Minecraft server and my mod crashes.

 

The first crash was easy. It complained about trying to instantiate a Screen. A quick search of my code showed that my client event handler class was "static final" initialising my screen. I changed it to dynamic initialisation, moved client tick event registration into the FMLClientSetupEvent handler and all was well...or so I hoped.

I now get this error:

[17:03:22] [main/ERROR] [minecraft/Main]: Failed to start the minecraft server
net.minecraftforge.fml.LoadingFailedException: Loading errors encountered: [
	Stats and Skills (stats_and_skills) has failed to load correctly
§7java.lang.RuntimeException: Attempted to load class net/minecraft/client/player/LocalPlayer for invalid dist DEDICATED_SERVER

So, I did a search of my code for LocalPlayer...and found nothing. I am not importing that class, not instantiating it, not (apparently) referencing it, anywhere.

 

I am not asking you to solve this problem. There will, I am sure, be others after this. I am asking for tips on how to find the root cause of such problems and would also appreciate tips on avoiding them in the first place.

 

Link to comment
Share on other sites

I've tracked down this specific issue to this code, and now I am confused because I am sure I am handling this as per the documentation:

 

    public static void handler(SyncMsg msg, Supplier<NetworkEvent.Context> ctx)
    {
        ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> safe_handler(msg)));
        ctx.get().setPacketHandled(true);
    }

    public static void safe_handler(SyncMsg msg)
    {
        Player      player = (Player)(Minecraft.getInstance().player);
        PlayerData  data   = PlayerData.get(player);

        ...

 

The crash occurs when loading the mod, long before any of this code is executed. Minecraft.getInstance() is a static function, but surely this won't get executed until a message is received by the client.

Link to comment
Share on other sites

And to answer my own question...the documentation, if you read the "Common mistakes" section REALLY closely, holds all the answers, including a hint about race conditions when using static members in a normal client installation. The bit I really needed to read was about: ...@OnlyIn(Dist) annotation....

 

Now all I need to do is figure out which import that is in.

 

HOWEVER:

The documentation also says:

 

    There is NO reason for using this annotation directly. Use DistExecutor or a check on FMLEnvironment#dist instead.

 

I am. It doesn't work! Yes my supplied method is in the same class, but I tried putting it in a different class and it didn't work either.

 

Edited by Jontom Xire
Link to comment
Share on other sites

I changed "DistExecutor.unsafeRunWhenOn" to "DistExecutor.safeRunWhenOn". No change. However, I also at the same time made "DistExecutor.safeRunWhenOn" call an empty function in another class. Completely empty. However I did not remove/comment out my original safe_handler() function which is no longer being called AT ALL from ANYWHERE! Still got a crash. Code that is simply not being called at all.

 

I renamed the function to NOT_CALLED() to be really really sure it isn't being called at all somehow. Still crashed. Commented out the body of the NOT_CALLED() function and it works just fine.

Looks like @OnlyIn is my only option, as long as I can find the import...

Link to comment
Share on other sites

  • 3 weeks later...
On 2/19/2023 at 5:14 PM, Jontom Xire said:
Attempted to load class net/minecraft/client/player/LocalPlayer for invalid dist DEDICATED_SERVER

Classes in the client package don't exist on the server.

On 2/19/2023 at 5:56 PM, Jontom Xire said:

public static void handler(SyncMsg msg, Supplier<NetworkEvent.Context> ctx)
    {
        ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> safe_handler(msg)));
        ctx.get().setPacketHandled(true);
    }

    public static void safe_handler(SyncMsg msg)
    {
        Player      player = (Player)(Minecraft.getInstance().player);
        PlayerData  data   = PlayerData.get(player);

        ...

Are those methods in the same class? Any code that interacts with client only code should be in a seperate class.

Minecraft#player is an instance of LocalPlayer, so the game tries to load that class in order to cast it.

Please provide a complete stacktrace and git repo.

Edited by Alpvax
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.