Jump to content

[1.12.x] Any Guides for Newbies?


Splashsky

Recommended Posts

I'm brand new to the modding scene. I know PHP, I've got some C++ experience, and I'm aware of Java. I can figure things out, more or less... but really only when I have examples I can first learn from. What I'm getting at is are there any clean, fully working example mods using all the best practices for 1.12.x? Like, registering and rendering items, how I should set up the proxies, etc? I did look at Choonster's test mod, and it had a pretty neat idea with how he registers items... however, I need a guide or an example mod that steps me through the basics of setting up a registry for items and blocks, and how I should set up my proxies to work with that.

 

This is basically just what I pulled from Choonster...

public static ModIngot ObsidianIngot = new ModIngot("obsidian_ingot");


    public static void init()
    {

    }

    @Mod.EventBusSubscriber(modid = Reference.MODID)
    public static class RegistrationHandler
    {
        public static final Set<Item> ITEMS = new HashSet<>();

        @SubscribeEvent
        public static void registerItems(final RegistryEvent.Register<Item> event)
        {
            final Item[] items = {
                    ObsidianIngot
            };

            final IForgeRegistry<Item> registry = event.getRegistry();

            for (final Item item : items) {
                registry.register(item);
                ITEMS.add(item);
            }

            init();
        }
    }

 

But I don't know where to go from here.

Link to comment
Share on other sites

Blocks work the same, except:

  • You use the RegistryEvent.Register<Block> event.
  • You have to create an ItemBlock instance of your block and register it during the Item registration event if you want the block to appear in the player's inventory at all.

Models need to be registered during the ModelRegistryEvent and you call ModelLoader.setCustomModelResourceLocation(...) there. This is client-side-only.

 

Proxies are how to distinguish between the physical client and physical server (the client, running single player, has an integrated logical server). You need two classes, a ClientProxy and a ServerProxy that both can be assigned to the same field in your main class, annotated with @SidedProxy It is recommended that you use an IProxy interface as the common type.

  • Like 1

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

Would it matter too terribly much where I were to put the Registry event? Choonster's puts the class into the ModItems class, and another tutorial puts the class directly into the main mod file. Is there a way I can make a separate Registry class and call the registration somewhere in the main mod class?

Link to comment
Share on other sites

2 minutes ago, Splashsky said:

Is there a way I can make a separate Registry class and call the registration somewhere in the main mod class?

Yes. Create the class and register it as an event handler. Job done.

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

So... 

@Mod.EventHandler

... and I just assign that class to a variable in the main mod file? Or do I use that above the registration function after using 

@SubscribeEvent / @Mod.EventBusSubscriber

above the Registry class declaration?

 

Java's metadata is like alienese to me.

Link to comment
Share on other sites

The annotation on the class is for static method event handler. Otherwise you have to register an instance manually.

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

18 minutes ago, Splashsky said:

So, gauging from what I read, the EasyRegistry classes could just as easily be the ClientProxy and ServerProxy I have. Just set it up in the same way... okay. Well, thanks, Draco! :D

I have them set up that way because of what the EasyRegistry is supposed to do: register stuff in a way that doesn't require I, the modder, to have to do much work in my main class: its flexible, its powerful, it makes distinctions.

 

The interface-and-separate-classes makes more sense for a traditional proxy system because anything that would be in a "common" proxy should be in your main mod class.

  • Like 1

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

56 minutes ago, Splashsky said:

So, effectively - and pardon for being such a newb - I could just write a ServerRegistry class with the same base functionality as your EasyRegistry and register that to the EVENT_BUS separate from the ServerProxy I have?

Oh, sure. Absolutely.

You could even register it as a static class and bypass the static -> instance redirection methods.

9 minutes ago, Splashsky said:

Additionally, is there any particular reason you make two methods for most actions? Such as registerItem and _registerItem, that is.

The first one is static so I can reference it as EasyRegistry.registerItem, that method then calls Hardlib.proxy._registerItem

  • Like 1

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

Okay, so from what I've extrapolated, I came up with a plan in my head. I can use my common.items package, create a ModItem class to act as a base class and set the Unlocalized and Registry names. When that item is created, I can, from the ModItem class, call ServerRegistry.registerItem(), add it to that list, and simply have the ServerRegistry use registerAll on that list. When I get it all hooked up, I use kind of a ItemHub with a method for instantiating all these items, which ultimately adds them to the list in the ServerRegistry. I then just add the ServerRegistry to the EVENT_BUS and call it a day.

 

Is that more or less correct? :o

Link to comment
Share on other sites

13 minutes ago, Splashsky said:

Okay, so from what I've extrapolated, I came up with a plan in my head. I can use my common.items package, create a ModItem class to act as a base class and set the Unlocalized and Registry names. When that item is created, I can, from the ModItem class, call ServerRegistry.registerItem(), add it to that list, and simply have the ServerRegistry use registerAll on that list. When I get it all hooked up, I use kind of a ItemHub with a method for instantiating all these items, which ultimately adds them to the list in the ServerRegistry. I then just add the ServerRegistry to the EVENT_BUS and call it a day.

 

Is that more or less correct? :o

That is a valid approach. There are a lot of different approaches. Some people combine some registration code in each item class, I just list it out directly in my event handler.

 

One philosophy I have is that although I like the idea of putting things in lists and iterating, it is also no effort at all to cut and paste in an IDE and you have to create the list anyway so it doesn't save you that much to put it in a list rather than just have a line to register each item.

 

For me, iterating through a list is more efficient when you're doing several lines of processing. If you're doing a single line then you don't save much.

 

Cut and paste can of course introduce errors sometimes, but when all the lines are one after another that is easy to catch.

 

My basic approach is to create all my instances in a ModItems class, and then have a registerItems() method in that class that I call from my proxy (in older versions) and from my registry event handler in more recent versions. I sometimes make my ModItems class also the event subscriber.

 

In programming there are a lot of ways to achieve the same thing and a lot is just personal preference. I rarely do mods with more than a half dozen items so I don't get too fancy with organizing it. If you're doing a major item overhaul mod then of course you need to architect things for greater convenience.

Edited by jabelar
  • Like 1

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

I see! In this, then, I have another question. Given Draco's EasyRegistry class, it looks like he annotates it with SidedProxy... would this work as I expect it to?

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class Venture
{
    @Mod.Instance
    public static Venture instance;

    @SidedProxy(clientSide = Reference.CLIENTPROXY, serverSide = Reference.SERVERPROXY)
    public static CommonProxy proxy;

    public static ServerRegistry registry;

    public static Logger logger;

    @Mod.EventHandler
    public static void preInit(FMLPreInitializationEvent event)
    {
        logger = event.getModLog();
        MinecraftForge.EVENT_BUS.register(registry);
        proxy.preInit();
    }

    @Mod.EventHandler
    public static void init(FMLInitializationEvent event)
    {
        proxy.init();
    }

    @Mod.EventHandler
    public static void postInit(FMLPostInitializationEvent event)
    {
        proxy.postInit();
    }
}
public class ServerRegistry
{
    private List<Block> blocksToRegister = new ArrayList<Block>();
    private List<Item>  itemsToRegister  = new ArrayList<Item>();
    private List<IForgeRegistryEntry> otherItems = new ArrayList<IForgeRegistryEntry>();

    public static void registerItem(Item item)
    {
        Venture.registry._registerItem(item);
    }

    public void _registerItem(Item item)
    {
        itemsToRegister.add(item);
    }

    @SubscribeEvent
    public void registerItems(RegistryEvent.Register<Item> event)
    {
        event.getRegistry().registerAll(itemsToRegister.toArray(new Item[itemsToRegister.size()]));
    }
}
public class ModItem extends Item
{
    protected String name;

    public ModItem(String name)
    {
        this.name = name;
        setUnlocalizedName(name);
        setRegistryName(name);
        Venture.registry.registerItem(this);
    }

    @Override
    public ModItem setCreativeTab(CreativeTabs tab)
    {
        super.setCreativeTab(tab);
        return this;
    }
}

 

Edited by Splashsky
Link to comment
Share on other sites

38 minutes ago, Splashsky said:

Couldn't you just make _registerItem static instead? O.o

No, because of the need for both a common side and a client side (how would I register the item models only on the client when all the methods are static?)

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

IYour getting close but there are a couple things that are suspicious to me. I'm assuming that youre Reference.CLIENTPROXY and Reference.SERVERPROXY are strings with full package and class names, but after that:

 

1) I usually register my event listener to the bus in the init() rather than the preinit() handling method. I'm not sure where I learned that, but it has always worked for me and you might run into trouble (or maybe not) at that point.

 

The registry method in 1.12.1 actually doesn't need you to register the handler class directly to the bus. Instead you use an @ObjectHolder annotation and another type of subscription. In other words, you don't register the registry rather it registers itself based on annotation. I'm sure Draco's examples are good so look at them more closely.

Edited by jabelar

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

20 minutes ago, jabelar said:

The registry method in 1.12.1 actually doesn't need you to register the handler class directly to the bus. Instead you use an @ObjectHolder annotation and another type of subscription. In other words, you don't register the registry rather it registers itself based on annotation. I'm sure Draco's examples are good so look at them more closely.

I had actually seen some of that from Choonster's test mod repo. It had some init things in there where he used @ObjectHolder to manage items...

@GameRegistry.ObjectHolder(Reference.MODID)
public class ModItems {
    public static ModIngot ObsidianIngot = new ModIngot("obsidian_ingot");
    // ... more items go here

    @Mod.EventBusSubscriber(modid = Reference.MODID)
    public static class RegistrationHandler
    {
        public static final Set<Item> ITEMS = new HashSet<>();

        @SubscribeEvent
        public static void registerItems(final RegistryEvent.Register<Item> event)
        {
            final Item[] items = {
                    ObsidianIngot
            };

            final IForgeRegistry<Item> registry = event.getRegistry();

            for (final Item item : items) {
                registry.register(item);
                ITEMS.add(item);
            }
        }
    }
}

but the one thing I couldn't ever figure out is how to make it work, or if things like this worked on their own without having to instantiate the class in the main mod file or something else along those lines.

Link to comment
Share on other sites

1 hour ago, jabelar said:

1) I usually register my event listener to the bus in the init() rather than the preinit() handling method. I'm not sure where I learned that, but it has always worked for me and you might run into trouble (or maybe not) at that point.

Registry events specifically fire between preInit and Init, so you would have to register your event handler during preInit.

 

Registering Things

The recommended way to register things is through the RegistryEvents. These events are fired right after preinitialization

 

http://mcforge.readthedocs.io/en/latest/concepts/registries/#registering-things


 

Quote

 

I had actually seen some of that from Choonster's test mod repo. It had some init things in there where he used @ObjectHolder to manage items...

 

but the one thing I couldn't ever figure out is how to make it work, or if things like this worked on their own without having to instantiate the class in the main mod file or something else along those lines.

 

The @ObjectHolder annotation is what handles that. Specifically.

If the @ObjectHolder points to an item that is not part of your mod (e.g. another mod's item) it will be filled without you having to create a JVM-class-load-based dependency on that other mod (i.e. get its source code into your dev environment).

Edited by Draco18s

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

5 minutes ago, Draco18s said:

Registry events specifically fire between preInit and Init, so you would have to register your event handler during preInit.

 

I meant regular event handler registration. He was treating it like a regular registration. I seem to remember that problems could arise if you registered those at preInit time, although I can't remember and it may not matter or perhaps doesn't matter any more. I've never had trouble registering regular event handler on init.

 

As mentioned the registry events don't need explicit registration since the annotation takes care of that, so shouldn't be in preInit or init. I suppose technically they're also on the same bus, but they're now handled somewhat separately.

Edited by jabelar

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

5 minutes ago, jabelar said:

As mentioned the registry events don't need explicit registration since the annotation takes care of that, so shouldn't be in preInit or init. I suppose technically they're also on the same bus, but they're now handled somewhat separately.

It doesn't matter when you register an event handler.

As for the annotation, that's only true for static event handler methods.

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.

×
×
  • Create New...

Important Information

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