Jump to content

Are utility classes mandatory?


Pentasis
 Share

Recommended Posts

I'm learning both Java and minecraft modding at the same time. And one of the things I notice when looking at tutorials and source code of existing mods, is that utility classes are (always?) used for the setup code for Registries, Config, Eventhandlers, etc. 

Is this how Forge needs it to be? Is there any reason why I shouldn't use an object over static fields/methods in a utility class?

NOTE: I am not asking for a discussion over whether utility classes are "evil"; I just want to know the reason behind this.

Link to comment
Share on other sites

No you don't need a utility class, it's a matter of preference only.  You can create an object and register it on the event bus, or you can register a utility class instead (for its static methods), Forge supports both methods, eg both of these work:

ServerLifeCycleEvents serverLifeCycleEvents = new ServerLifeCycleEvents();
 MOD_EVENT_BUS.register(serverLifeCycleEvents);


 public class ServerLifecycleEvents {
   @SubscribeEvent
      public void onServerStartingEvent(FMLServerStartingEvent event) { }
}

///------- or ------------

MOD_EVENT_BUS.register(ServerLifeCycleEvents.class);  
public class ServerLifecycleEvents {  
    @SubscribeEvent  
     public static void onServerStartingEvent(FMLServerStartingEvent event) {  }    //static here
}

 

I personally prefer the utility class for setup code because I only ever need a singleton and they are so simple I never need to write a test harness for it, so creating an object just adds a bit of extra overhead.  I also like the imperative style of explicitly adding to registries. 

 

Or do you mean- can you just add registration methods to the objects themselves?  (eg create a new Block and have it register itself?, or perhaps using a static initialiser inside the Block class)  In that case - the answer is "no" because the objects must be registered with vanilla at the correct time, which is not guaranteed unless you use the forge initialisation events.

 

Many folks like to eliminate utility classes as much as possible by using static initialiser assignment of a DeferredRegister, eg

 

*   private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);
*
*   public static final RegistryObject<Block> ROCK_BLOCK = BLOCKS.register("rock", () -> new Block(Block.Properties.create(Material.ROCK)));
*
*   public ExampleMod() {
*       BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());
*   }
Again I think that's a matter of personal preference although some people do hold strong opinions about the right way to do it (TM).
Link to comment
Share on other sites

Utility classes can often help reduce the amount of code you need to write. For example, back on 1.12 (when we no longer had the Game Registry and had to register item models ourselves) I wrote this class:
https://github.com/Draco18s/ReasonableRealism/blob/1.14.4/src/main/java/com/draco18s/hardlib/EasyRegistry.java 

That's the 1.14 version, but the switch was pretty straight forward.

It meant I could have my "1.7-like" register-a-block one or two line clean system:
https://github.com/Draco18s/ReasonableRealism/blob/1.14.4/src/main/java/com/draco18s/harderores/HarderOres.java#L119-L131

 

Instead of this utter nonsense people were doing where they'd create a block, set its registry name, set its translation key, add it to a BLOCKS list, then add the blocks list to the registry, then over in the item event loop over their entire BLOCKS list, create an item (set its registry and translation keys), set a creative tab, and add it to an ITEMS list. And then realize "herp a derp, I created this giant loop that does all my blocks, how does I do more than one creative tab where some blocks are in one and others are in another? What if my block has variants that need different items?" and then end up needing nine lines per block (plus a couple lines for registering a model in the client proxy!).

 

The deferred registry system is what I'll be using on 1.16 because it solves the problem I was solving.

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

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
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.

 Share



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I used multiple biomes by setting the type to minecraft:multi_noise. The dimension is working fine now, but I was wondering if there is a way to supress this warning when creating a new world: Warning! These settings are using experimental features. These settings are experimental and could one day stop working. Do you wish to proceed?
    • Hi. Please help. Forge keep crashing on my pc (error code 1). This happened after i updated my PC to the latest windows 11 update. I have tried updating my GPU driver, reinstall java and reinstall minecraft, but i still got this error code 1. Any help is appreciated. Thanks.  
    • here are the logs https://gist.github.com/Myrious/13e16642c4afe9c0286691571bd136f0
    • I Start Up the game get a crash before forge even starts to load Crash Log-https://gist.github.com/keepinitreal247/c1024110beca289019a0177ddecfc910
    • The game crashed whilst initializing game. Error: net.minecraftforge.fml.ModLoadingExceptionForge encountered an error during the sided_setup event phase . Got crash exit code -1 for minecraft forge 1.19.3 It works before i instal my mods the list of mods i got are: Macaw's: paintings, paths, lights, roofs, windows, trapdoors, fences, doors + optifine 1.19.3  +  Shaders: BSL, Sildurs-high,extreme, extreme VL + Resource packs: SFT_FREE, HelHeim R29, SkylineArt free, Clear_Glass_Pack, Unity, Round trees, Fresh animations, Better-Leaves  ---- Minecraft Crash Report ---- // Hi. I'm Minecraft, and I'm a crashaholic. Time: 2023-01-29 01:34:45 Description: Rendering overlay java.lang.NoClassDefFoundError: net/minecraftforge/common/extensions/IForgeModelBaker     at java.lang.ClassLoader.defineClass1(Native Method) ~[?:?] {}     at java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[?:?] {}     at cpw.mods.cl.ModuleClassLoader.readerToClass(ModuleClassLoader.java:119) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.lambda$findClass$15(ModuleClassLoader.java:219) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.loadFromModule(ModuleClassLoader.java:229) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.findClass(ModuleClassLoader.java:219) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.loadClass(ModuleClassLoader.java:135) ~[securejarhandler-2.1.4.jar:?] {}     at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?] {}     at java.lang.ClassLoader.defineClass1(Native Method) ~[?:?] {}     at java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[?:?] {}     at cpw.mods.cl.ModuleClassLoader.readerToClass(ModuleClassLoader.java:119) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.lambda$findClass$15(ModuleClassLoader.java:219) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.loadFromModule(ModuleClassLoader.java:229) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.findClass(ModuleClassLoader.java:219) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.loadClass(ModuleClassLoader.java:135) ~[securejarhandler-2.1.4.jar:?] {}     at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?] {}     at net.minecraft.client.resources.model.ModelBakery.lambda$bakeModels$9(ModelBakery.java:209) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:classloading,pl:accesstransformer:B,xf:OptiFine:default}     at java.util.HashMap$KeySet.forEach(HashMap.java:1008) ~[?:?] {}     at net.minecraft.client.resources.model.ModelBakery.m_245909_(ModelBakery.java:204) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:classloading,pl:accesstransformer:B,xf:OptiFine:default}     at net.minecraft.client.resources.model.ModelManager.m_245476_(ModelManager.java:166) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:classloading,pl:runtimedistcleaner:A}     at net.minecraft.client.resources.model.ModelManager.m_246937_(ModelManager.java:89) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:classloading,pl:runtimedistcleaner:A}     at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:646) ~[?:?] {}     at java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:483) ~[?:?] {}     at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[?:?] {}     at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[?:?] {}     at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[?:?] {re:computing_frames}     at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[?:?] {re:computing_frames}     at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[?:?] {} Caused by: java.lang.ClassNotFoundException: net.minecraftforge.common.extensions.IForgeModelBaker     at cpw.mods.cl.ModuleClassLoader.loadClass(ModuleClassLoader.java:141) ~[securejarhandler-2.1.4.jar:?] {}     at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?] {}     ... 28 more A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Thread: Render thread Stacktrace:     at java.lang.ClassLoader.defineClass1(Native Method) ~[?:?] {}     at java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[?:?] {}     at cpw.mods.cl.ModuleClassLoader.readerToClass(ModuleClassLoader.java:119) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.lambda$findClass$15(ModuleClassLoader.java:219) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.loadFromModule(ModuleClassLoader.java:229) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.findClass(ModuleClassLoader.java:219) ~[securejarhandler-2.1.4.jar:?] {}     at cpw.mods.cl.ModuleClassLoader.loadClass(ModuleClassLoader.java:135) ~[securejarhandler-2.1.4.jar:?] {}     at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?] {}     at java.lang.ClassLoader.defineClass1(Native Method) ~[?:?] {}     at java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[?:?] {} -- Overlay render details -- Details:     Overlay name: net.minecraft.client.gui.screens.LoadingOverlay Stacktrace:     at net.minecraft.client.renderer.GameRenderer.m_109093_(GameRenderer.java:1337) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:mixin,pl:accesstransformer:B,xf:OptiFine:default,re:classloading,pl:accesstransformer:B,xf:OptiFine:default,pl:mixin:APP:mtr.mixins.json:GameRendererMixin,pl:mixin:A}     at net.minecraft.client.Minecraft.m_91383_(Minecraft.java:1135) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.Minecraft.m_91374_(Minecraft.java:713) ~[client-1.19.3-20221207.122022-srg.jar%23168!/:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.main.Main.m_239872_(Main.java:212) ~[1.19.3-forge-44.1.0.jar:?] {re:classloading,pl:runtimedistcleaner:A}     at net.minecraft.client.main.Main.main(Main.java:51) ~[1.19.3-forge-44.1.0.jar:?] {re:classloading,pl:runtimedistcleaner:A}     at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] {}     at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?] {}     at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] {}     at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?] {}     at net.minecraftforge.fml.loading.targets.CommonClientLaunchHandler.lambda$launchService$0(CommonClientLaunchHandler.java:27) ~[fmlloader-1.19.3-44.1.0.jar:?] {}     at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:30) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:53) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:71) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.modlauncher.Launcher.run(Launcher.java:106) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.modlauncher.Launcher.main(Launcher.java:77) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.modlauncher.BootstrapLaunchConsumer.accept(BootstrapLaunchConsumer.java:26) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.modlauncher.BootstrapLaunchConsumer.accept(BootstrapLaunchConsumer.java:23) ~[modlauncher-10.0.8.jar:?] {}     at cpw.mods.bootstraplauncher.BootstrapLauncher.main(BootstrapLauncher.java:141) ~[bootstraplauncher-1.1.2.jar:?] {} -- Last reload -- Details:     Reload number: 1     Reload reason: initial     Finished: No     Packs: vanilla
  • Topics

×
×
  • Create New...

Important Information

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