Jump to content

Are utility classes mandatory?


Pentasis

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
    • It is an issue with quark - update it to this build: https://www.curseforge.com/minecraft/mc-mods/quark/files/3642325
    • Remove Instant Massive Structures Mod from your server     Add new crash-reports with sites like https://paste.ee/  
  • Topics

×
×
  • Create New...

Important Information

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