Jump to content

Using a dedicated EventSubscriber vs multiple


Cratthorax

Recommended Posts

Good morning,

I'm almost all way through my current mod port, and while I'm on it, I'd thought to improve code were due. In the past my focus wasn't necessarily on making things working for multiplayer, since I would never play MC online anyways, but now I wanna change that, since I really don't want to crash other users games. I also want to make things a bit more "efficient", if that is even what I'm trying to do?

So, per title, I have a multitude of different event subscribers to intercept recipe/advancements code, which all run on server start(on a Forge bus), and are currently running inside my main file, mixed up with a couple of client related eventSubs to cancel player related render stuff. So my first question would be: is it a good idea to mix client/server events up in one .class, or am I supposed to give them dedicated .classes's? I should mention that my main file is registering for modEventBus as well as forgeEventBus.

Is it even worth worrying to lump them up in one file, or does the game not bother at all, as long as I keep it structured?

Edit: oh, and is multithreading with multiple .classes housing evtSubs even a thing in MC, given how low the used up resources by this game are?

Edited by Cratthorax
Link to comment
Share on other sites

2 hours ago, Cratthorax said:

is it a good idea to mix client/server events up in one .class, or am I supposed to give them dedicated .classes's?

no it´s not since you can only subscribe a class to one Dist server or client if you don't enter a dist it will run on both (common)

2 hours ago, Cratthorax said:

Is it even worth worrying to lump them up in one file, or does the game not bother at all, as long as I keep it structured?

the events are called, no matter what class they are in
if you combine several events (which are registered on the same Dist) in one class you may save some RAM in the extreme case 1-2MB (depends on the class size)

I would recommend that you sort the Events/summarize them in classes, that you can handle the code

  • Like 1
Link to comment
Share on other sites

6 hours ago, Luis_ST said:

no it´s not since you can only subscribe a class to one Dist server or client if you don't enter a dist it will run on both (common)

the events are called, no matter what class they are in
if you combine several events (which are registered on the same Dist) in one class you may save some RAM in the extreme case 1-2MB (depends on the class size)

I would recommend that you sort the Events/summarize them in classes, that you can handle the code

Well, you can run a class inside a class dedicated to client. But I take it that's not a good practice. I just wanted to rule out if it's something to worry about or not.

I do practice to sort event .classes into three categories: client, server, and registry. But from a performance pov I couldn't say there really is any notable improvement, no matter how you structure the files. The only golden rule here seems to be, applying a clear distinction between client(render, sound, ui, model etc.) and server side.

Edited by Cratthorax
Link to comment
Share on other sites

Quote

It doesn't matter for performance if you have one class registered to the event bus or multiple. What matters it he amount of event subscribing methods.

Oh, so it does make sense, if I'm using multiple events to check for "similar" conditions, I should make sure I'm trying to achieve it with only one?

Because I would often use multiple events(in one, or across multiple files/.classes) as backup.

Quote

You should use @EventBusSubscriber with the Dist parameter for dist-only subscribers (e.g. FMLClientSetupEvent or EntityRenderersEvent.RegisterRenderers). This has nothing to do with performance, but it is necessary to avoid crashing the dedicated server.

Which leads me to the question, is there a way to list definitive methods/fields/constructors/types, that are only supposed to be used by client vs server? I mean, I do know you are supposed to keep render, sound, ui stuff etc. dedicated to client, but a comprehensive list would ease up things, and stop wasting time with browsing through examples(in Google, and the forge snapshot). 

Quote

You should not register the same event handler to multiple event buses. Separate your mod event bus and forge event bus methods into separate classes if you use the class/object based registration.

Hmmm, I might be wrong. But the source main .class from example mod actually exactly does that. So I had the impression that's not a problem.

 
	@Mod(blabla.MODID)
public class blablaMain{
	    public blablaMain() {
        
        IEventBus modEvtBus = FMLJavaModLoadingContext.get().getModEventBus();
        
        modEvtBus.addListener(this::setup);
        modEvtBus.addListener(this::enqueueIMC);
        modEvtBus.addListener(this::processIMC);
        modEvtBus.addListener(this::doClientStuff);
	        MinecraftForge.EVENT_BUS.register(this);  
    }
	    private void setup(final FMLCommonSetupEvent evt)
    {
        // some preinit code
    }
    
    private void doClientStuff(final FMLClientSetupEvent evt) {
        // do something that can only be done on the client
    }
	    private void enqueueIMC(final InterModEnqueueEvent evt)
    {
        // some example code to dispatch IMC to another mod
    }
	    private void processIMC(final InterModProcessEvent evt)
    {
        // some example code to receive and process InterModComms from other mods
    }
    
    @SubscribeEvent
    public void onServerStarting(FMLServerStartingEvent evt) {
        // do something when the server starts
    }
    
    @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
    public static class RegistryEvents {
        @SubscribeEvent
        public static void onBlocksRegistry(final RegistryEvent.Register<Block> blockRegEvt) {
            // register a new block here
        }
    } 
  
}

 

Edited by Cratthorax
Link to comment
Share on other sites

Quote

A good start is the @OnlyIn annotation. If it is present on a class/method/field then that element is only present on that distribution. For example the Minecraft class. This means that from common code you cannot use it - or you will crash servers and cause strange bugs on single player.

By distribution you mean "the mod you've distributed", or is that java language related? Also, how exactly one defines "common" code, because I'd see that(folder/package) a lot on other mod examples. Is it mend like the German word "gewöhnlich", or more like "common" for anyone to use(server) vs "closed" not for anyone to use(client).

I think I start to comprehend this a bit more. Utilizing this annotation I would crash test my mod on a LAN server world, and if any of my code crashes the server, I would annotate with @Onlyln to prevent that crash(on server), or make my code server compatible. At least that's how I understand your feedback.

If that is the case, why isn't the example mod source distributed with a simple comment, like this:

//use this class/method/field annotation to make sure you aren't crashing the server, if mod is present: @OnlyIn

 

Edited by Cratthorax
Link to comment
Share on other sites

No, do not use @OnlyIn, ever. @OnlyIn is a marker annotation that Forge puts in vanilla code. When Forge sets up the development environment it takes the server jar and the client jar and merges them together. Code that is present only in either one of them gets annotated with @OnlyIn. This tells you that you cannot use said code from common code (i.e. code that runs on server and client), because then you'll run into crashes on the side that does not have the class/method/field available. Refer to the documentation above for how to safely interact with this code (Mainly DistExecutor and @EventBusSubscriber with the Dist parameter).

Oh, so you marked any of critical classes/events etc., or is it for just some that can't be used?

Is there any "codeable" way of "stress" testing the /minecraftforge source for crash prone code? Like something that clearly debugs for me which code to not use commonly?

Link to comment
Share on other sites

Quote

Not that I know of, but I am not 100% sure what your question is.

Well, something like an "idiot" break. Something that allows me using debugging code, that, for example, scans the (any)source for client only annotations etc., and/or tells me: "Hello, you right now utilize client code commonly. Please stop doing that!", as in:

if ((client only)annotation found on class/method/field || any other method to determine client code) {
	                     system.out.println("Hello, you right now utilize client code commonly. Please stop doing that!)
	}
Edited by Cratthorax
Link to comment
Share on other sites

Good morning,

one thing kept me busy thinking though, when you said:"What matters it he(is the?) amount of event subscribing methods.". Is there something like a recommended quantity of subscribed events for any range of PC specs? Something like an absolute "upper limit"?

My mod is quite huge, and it's hard to unite some of its events under one event method.

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.