Jump to content

[1.8.9] Catching all events for new Event system.


yoshiquest

Recommended Posts

I've been writing a mod to integrate the Clojure programming language into Minecraft, and would like to add a better event system. This would involve shoving events into core.async channels, which would then distribute them across the mod. As such, I need a way to catch most, if not all, events in order to process them.

 

So does subscribing to a parent class event catch the child events as well? Such that if I subscribe to just the Event class, I'll catch all events? Or on the other hand, is there a way to plug into the event bus, and handle events that way?

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

Yes, you can subscribe to just

Event

and you will receive all events. Should you? Hell no. Forge's

EventBus

is highly optimized.

Posting an event is no more than one virtual method dispatch and array lookup and then a for-loop through an array (the array of listeners). Every listener is an instance of a special interface (so a virtual dispatch per listener, which is not avoidable) and then a direct invocation of the target method, no reflection, nothing.

I highly suggest you stick to this system, since there are probably hundreds of events (at least) fired every tick on a busy server (every entity fires

LivingUpdateEvent

just for a start).

 

So yeah, please don't.

 

Hm, would there possibly be a way to directly feed it a Method? Clojure can pass functions around like data, so I could probably make a way to register a function with the event handler. It would still directly call it as a method, but 1.) Wouldn't require a class at all (or an instance of one, it would function as a static method) and 2.) It wouldn't require method annotations (very annoying in Clojure). If you could just register an event from anywhere, it would open up a lot of possibilities, such as auto-subscribing to certain events (such as when syncing entities, or registering extended properties, for example). This is the main issue I'm facing that makes me want such a feature.

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

Hm, forge has a transforming classloader that it uses, right? Would it be possible to add subscribed methods to the event class using that, then re-registering the class, in order to allow for dynamic event registration?

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

I am not sure what you are saying but it already sounds horrible :P

 

Yeah, I think it's impossible. Minecraft Forge's event system is retarded. By that I mean it's very... static. But I suppose that perhaps instead of trying to keep everything in a single event class that gets modified over time, maybe I should just add event methods to the classes themselves.

 

On a side note, I actually tried the global Event subscription idea I had. The game actually didn't lag for the most part. HOWEVER, core.async was trying to push too many events to the central channel. In other words, more events were coming in than could be sorted and subsequently dropped, causing a backlog of events that caused noticeable lag and constant complaints from core.async that it had too many events.

 

TL;DR: You were probably right lol.

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

Actually, why DO we have to provide an object? Why not a class with static methods?

 

For example, I wanna try putting an event subscription in my entity class, but I don't wanna have to have it registered every single time the entity is constructed, when just a static method will do (as the entity object gets provided by the event anyways).

 

In fact, wouldn't calling static methods technically be faster anyways? So then why do we have to provide an instance?

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

Forge's
EventBus

is highly optimized.

Posting an event is no more than one virtual method dispatch and array lookup and then a for-loop through an array (the array of listeners). Every listener is an instance of a special interface (so a virtual dispatch per listener, which is not avoidable) and then a direct invocation of the target method, no reflection, nothing.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Forge's
EventBus

is highly optimized.

Posting an event is no more than one virtual method dispatch and array lookup and then a for-loop through an array (the array of listeners). Every listener is an instance of a special interface (so a virtual dispatch per listener, which is not avoidable) and then a direct invocation of the target method, no reflection, nothing.

 

I don't understand how this answers my question. Shouldn't the same be possible with or without an instance?

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

In theory: Yes. In practice: not really, since forge emits a new class for every handler method so the call will most likely be just inlined or at the very least there will be some kind of prediction there (whether it's the JIT or the CPU doing branch prediction). Virtual dispatch is not expensive anymore unless you actually have a megamorphic call site.

 

So yes, one could pass in a Class<> instead, but we are in OOP here, objects rule, not classes.

 

Ah, I understand.

 

Side note: OOP is somewhat irrelevent, as the language I'm writing for is Clojure, which is FP (Functional Programming) instead. It is why wrapping around Minecraft Forge is quite a bit more monumental for Clojure than a language like Scala: I'm not only bridging the gap between languages, I'm also bridging the gap between mindsets.

 

Anyways, I think I'm done with this, thanks again for all of the help.

Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.

Link to comment
Share on other sites

First off, writing a Clojure adapter is a fun academic experiment but its not worth the effort to make a real mod in. Trying to do anything in the real world with it is inadvisable.

And calling a system retarded because you have no idea what the hell you're doing is NOT a way to make friends.

The EventBus in Forge is HIGHLY optimized in a way that lets us run whatever the hell we want without any performance impact of the rest of the system.

 

At the end of the day, the Event bus is just an array of IEventListeners.

Whatever the implementation of that IEventListener is we dont give a shit.

If you want to do your static method crap you could easily just write a IEventListener that calls a static method.

 

This shouldnt have to be explained as its obvious if you take 10 seconds to look at the system.

 

But ya, have fun with your Clojure toy, i'd advise you drop it, or put in a modicum of effort before calling shit retarded.

 

On top of that you're developing or 1.8.9, we're on 1.10, get with the times.

 

That being said, you do bring up ONE good point, There is no technical reason we don't allow static methods as event handlers.

It's mainly a legacy from when we originally moved from Guava's EventBus {Which doesnt support it} to our own.

I've got a proof of concept edit already, only like 4 lines of code changed. I'll push it up if cpw cares enough about it.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I have done this now but have got the error:   'food(net.minecraft.world.food.FoodProperties)' in 'net.minecraft.world.item.Item.Properties' cannot be applied to                '(net.minecraftforge.registries.RegistryObject<net.minecraft.world.item.Item>)' public static final RegistryObject<Item> LEMON_JUICE = ITEMS.register( "lemon_juice", () -> new Item( new HoneyBottleItem.Properties().stacksTo(1).food( (new FoodProperties.Builder()) .nutrition(3) .saturationMod(0.25F) .effect(() -> new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 1500), 0.01f ) .build() ) )); The code above is from the ModFoods class, the one below from the ModItems class. public static final RegistryObject<Item> LEMON_JUICE = ITEMS.register("lemon_juice", () -> new Item(new Item.Properties().food(ModFoods.LEMON_JUICE)));   I shall keep going between them to try and figure out the cause. I am sorry if this is too much for you to help with, though I thank you greatly for your patience and all the effort you have put in to help me.
    • I have been following these exact tutorials for quite a while, I must agree that they are amazing and easy to follow. I have registered the item in the ModFoods class, I tried to do it in ModItems (Where all the items should be registered) but got errors, I think I may need to revert this and figure it out from there. Once again, thank you for your help! 👍 Just looking back, I have noticed in your code you added ITEMS.register, which I am guessing means that they are being registered in ModFoods, I shall go through the process of trial and error to figure this out.
    • ♈+2349027025197ஜ Are you a pastor, business man or woman, politician, civil engineer, civil servant, security officer, entrepreneur, Job seeker, poor or rich Seeking how to join a brotherhood for protection and wealth here’s is your opportunity, but you should know there’s no ritual without repercussions but with the right guidance and support from this great temple your destiny is certain to be changed for the better and equally protected depending if you’re destined for greatness Call now for enquiry +2349027025197☎+2349027025197₩™ I want to join ILLUMINATI occult without human sacrificeGREATORLDRADO BROTHERHOOD OCCULT , Is The Club of the Riches and Famous; is the world oldest and largest fraternity made up of 3 Millions Members. We are one Family under one father who is the Supreme Being. In Greatorldrado BROTHERHOOD we believe that we were born in paradise and no member should struggle in this world. Hence all our new members are given Money Rewards once they join in order to upgrade their lifestyle.; interested viewers should contact us; on. +2349027025197 ۝ஐℰ+2349027025197 ₩Greatorldrado BROTHERHOOD OCCULT IS A SACRED FRATERNITY WITH A GRAND LODGE TEMPLE SITUATED IN G.R.A PHASE 1 PORT HARCOURT NIGERIA, OUR NUMBER ONE OBLIGATION IS TO MAKE EVERY INITIATE MEMBER HERE RICH AND FAMOUS IN OTHER RISE THE POWERS OF GUARDIANS OF AGE+. +2349027025197   SEARCHING ON HOW TO JOIN THE Greatorldrado BROTHERHOOD MONEY RITUAL OCCULT IS NOT THE PROBLEM BUT MAKE SURE YOU'VE THOUGHT ABOUT IT VERY WELL BEFORE REACHING US HERE BECAUSE NOT EVERYONE HAS THE HEART TO DO WHAT IT TAKES TO BECOME ONE OF US HERE, BUT IF YOU THINK YOU'RE SERIOUS MINDED AND READY TO RUN THE SPIRITUAL RACE OF LIFE IN OTHER TO ACQUIRE ALL YOU NEED HERE ON EARTH CONTACT SPIRITUAL GRANDMASTER NOW FOR INQUIRY +2349027025197   +2349027025197 Are you a pastor, business man or woman, politician, civil engineer, civil servant, security officer, entrepreneur, Job seeker, poor or rich Seeking how to join
    • Hi, I'm trying to use datagen to create json files in my own mod. This is my ModRecipeProvider class. public class ModRecipeProvider extends RecipeProvider implements IConditionBuilder { public ModRecipeProvider(PackOutput pOutput) { super(pOutput); } @Override protected void buildRecipes(Consumer<FinishedRecipe> pWriter) { ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.COMPRESSED_DIAMOND_BLOCK.get()) .pattern("SSS") .pattern("SSS") .pattern("SSS") .define('S', ModItems.COMPRESSED_DIAMOND.get()) .unlockedBy(getHasName(ModItems.COMPRESSED_DIAMOND.get()), has(ModItems.COMPRESSED_DIAMOND.get())) .save(pWriter); ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.COMPRESSED_DIAMOND.get(),9) .requires(ModBlocks.COMPRESSED_DIAMOND_BLOCK.get()) .unlockedBy(getHasName(ModBlocks.COMPRESSED_DIAMOND_BLOCK.get()), has(ModBlocks.COMPRESSED_DIAMOND_BLOCK.get())) .save(pWriter); ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModItems.COMPRESSED_DIAMOND.get()) .pattern("SSS") .pattern("SSS") .pattern("SSS") .define('S', Blocks.DIAMOND_BLOCK) .unlockedBy(getHasName(ModItems.COMPRESSED_DIAMOND.get()), has(ModItems.COMPRESSED_DIAMOND.get())) .save(pWriter); } } When I try to run the runData client, it shows an error:  Caused by: java.lang.IllegalStateException: Duplicate recipe compressed:compressed_diamond I know that it's caused by the fact that there are two recipes for the ModItems.COMPRESSED_DIAMOND. But I need both of these recipes, because I need a way to craft ModItems.COMPRESSED_DIAMOND_BLOCK and restore 9 diamond blocks from ModItems.COMPRESSED_DIAMOND. Is there a way to solve this?
  • Topics

×
×
  • Create New...

Important Information

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