Jump to content

[1.12.2] Stuck getting started; need simple example


JoeStrout

Recommended Posts

My son and I are trying to get started making MC mods.  We're using Forge 1.12.2 and gradle, and following the Forge docs.  We've got as far as successfully printing to stdout in the pre-init, init, and post-init events.  But everything else we've attempted (including copying & pasting the snippets in the docs) has so far failed.  This is not because we don't understand Java; it's because we don't understand the Forge API.

 

So I have two related questions:

 

  1. Does anyone have a simple full example of doing something more?  Adding a simple new block or item type (of the sort that doesn't require a custom subclass), perhaps.  Or responding to a chat event by chatting back.  Or something similarly trivial.
  2. Where is the API reference documentation?  For example, all the events that can be registered for, and all the methods we can call to affect things in the game?  Or do we just trawl the Forge source code for that?

 

Many thanks,

- Joe

Link to comment
Share on other sites

OK, thanks all.  We were trying to code with just a text editor, but it seems that Eclipse (or similar) is pretty much required for this work.

 

Incidentally, we managed to get a simple example put together that responds to chat events.  We put this in a separate class from the main entry class (the one identified with @Mod), like so:

 

package net.strout.mod1;

import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

@Mod.EventBusSubscriber
public class MyForgeEventHandler {
 	
 	@SubscribeEvent
 	public static void onChat(ClientChatEvent event) {
 		String msg = event.getMessage();
 		System.out.println("ClientChatEvent: " + msg);
 		if (msg.contains("Hello")) {
 			Minecraft.getMinecraft().player.sendChatMessage("Hi Yourself!");
 		} else if (msg.contains("Bye")) {
 			Minecraft.getMinecraft().player.sendChatMessage("Later!");
 		}
 	}
 	
}

 

The only funny thing about this is that the responses appear before your own input in the chat log (since the chat event is not fully processed at this point).  If we were making a more serious chat mod, we'd have to solve that... but for the sake of a "hello world" level example to get started, I think this is good enough.

 

The key bit is importing the correct stuff at the top to avoid the dreaded "cannot find symbol" errors.  Eclipse will more or less automatically fill those in for you, or you can look in MinecraftByExample and discover the necessary imports from there.

 

Hopefully this will be helpful to the next poor soul who comes along!

Link to comment
Share on other sites

Append to the message rather than displaying a new message.

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

10 hours ago, Draco18s said:

Append to the message rather than displaying a new message.

That appends the new text on the same line (even when I insert a "\n" or a System.getProperty("line.separator")).  To get the effect I was after, I had to go to more extreme measures, like so:

	@SubscribeEvent
	public static void onChatReceived(ClientChatReceivedEvent event) {
		ITextComponent msg = event.getMessage();
		String formattedText = msg.getFormattedText();
		System.out.println("Chat type " + event.getType() + " received: " + formattedText);
		String plaintext = msg.getUnformattedText().toLowerCase();
		if (plaintext.contains("hello")) {
			// Cancel the event, so the player doesn't see the given message AFTER our response.
			event.setCanceled(true);
			// Display the given message immediately.
			Minecraft.getMinecraft().player.sendStatusMessage(msg, false);
			// Then, display our response.
			Minecraft.getMinecraft().player.sendStatusMessage(new TextComponentString(
					"<§rVoice In Your Head§r> §rHi yourself.§r"), false);
		}
	}

 

I don't know if all those §r (reset) formatting codes are actually necessary, but that's how the player messages are formatted, so I'm doing the same thing in the response.

Link to comment
Share on other sites

Also, here's the main entry class that illustrates adding a simple item type.  Posting here for posterity in case somebody else finds it useful, and also so I can dig it up later if I decide to write my own beginner modding tutorial.  ;)

package net.strout.mod1;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;

@Mod(modid = StroutMod1.MODID, version = StroutMod1.VERSION)
@Mod.EventBusSubscriber
public class StroutMod1
{
    public static final String MODID = "stroutmod1";
    public static final String VERSION = "0.1";
    
    public static Item testItem;
    
    @EventHandler
    public void preinit(FMLPreInitializationEvent event) {
    		System.out.println("PRE-INITIALIZATION");
    		testItem = (Item)(new Item());
    		testItem.setRegistryName("stroutmod1_testitem1");
    		testItem.setUnlocalizedName(testItem.getRegistryName().toString());
    		testItem.setCreativeTab(CreativeTabs.MISC);
    		System.out.println("Created item: " + testItem.getRegistryName());
	}
    
	@SubscribeEvent
	public static void registerBlocks(RegistryEvent.Register<Item> event) {
	    event.getRegistry().registerAll(testItem);
		System.out.println("Registered item: " + testItem.getRegistryName());	    
	}
    
    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        System.out.println("INITIALIZATION");
        // Just some sample code showing how to get info on common blocks:
        System.out.println("DIRT BLOCK >> " + Blocks.DIRT.getUnlocalizedName());

        // Register the model for our custom item type.
        // Assumes a properly named and located JSON file, in this case:
        // models/item/stroutmod1_testitem1.json
		ModelResourceLocation res = new ModelResourceLocation(testItem.getRegistryName(), "inventory");
		Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(testItem, 0, res);
    }

    @EventHandler
    public void postinit(FMLPostInitializationEvent event) {
    		System.out.println("POST-INITIALIZATION");
    }

}

 

And of course, if anybody spots anything I'm doing wrong, please do educate me!

 

 

Link to comment
Share on other sites

3 hours ago, diesieben07 said:

One thing, Problematic code, issue 2.

OK, thanks for that.  I see that I should use ModelLoader.setCustomModelResourceLocation in ModelRegistryEvent to register your item models, rather than ItemModelMesher.  But I've been learning mostly from the MinecraftByExample project, which does not do it this way, and I'm having trouble getting it to work.  Here's what I've got:

 

   @EventHandler
    public void registerModels(ModelRegistryEvent event) {
		ModelResourceLocation res = new ModelResourceLocation(testItem.getRegistryName(), "inventory");
    		ModelLoader.setCustomModelResourceLocation(testItem, 0, res);
    		System.out.println("Set model for " + testItem.getRegistryName() + " to " + res);
    }

 

This is in my main class (shown a couple posts up), which is marked with @Mod and @Mod.EventBusSubscriber, and successfully gets other events (for example RegistryEvent.Register<Item>).  But this ModelRegistryEvent doesn't appear to get invoked; I never see the console output from this method.  And as a result, my beautiful frog texture has reverted to the purple checkerboard no-texture texture.

 

What am I doing wrong?

 

Link to comment
Share on other sites

20 hours ago, JoeStrout said:

Does anyone have a simple full example of doing something more?

You can Google for "github" at site:http://www.minecraftforge.net/forum/topic

You can go to github and then search for Forge projects.

 

Stick to mods using the same version of Minecraft (1.12.2). After looking at a few, you'll quickly distinguish between matters of style versus matters of necessity. You'll also quickly get a sense for who knows what he's doing (and who knows even less than you do).

 

Once you've settled on one or two worthy examples, emulate them (don't cut and paste). You learn by assimilating and doing.

 

Finally, when you are getting ready to run something, run it in debug mode (with some break points set within your own code). Step through and into the various methods, examining some of the changing fields as you go. More than any static examination of vanilla code can ever teach you, a ride-through will illuminate how the program functions. Try to scan each operation at least once so you have some idea how it hangs together. No need to sit through 500 cycles of a loop, but try a few at least once.

 

And have fun.

  • Like 1

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

1 hour ago, diesieben07 said:

@EventHandler is only used for the FML lifecycle events (subtypes of FMLEvent). You need to use @SubscribeEvent to subscribe to the modern forge-style events (subtypes of Event).

 

Ah, OK, I should have known that.

 

Unfortunately, I've changed it to @SubscribeEvent and it's still not getting called.  :(

 

EDIT: I had also failed to make it a static method.  Oops!  All good now.  Thanks everyone for the help!

Edited by JoeStrout
figured it out
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

    • WINNING303 DAFTAR SITUS JUDI SLOT RESMI TERPERCAYA 2024 Temukan situs judi slot resmi dan terpercaya untuk tahun 2024 di Winning303! Daftar sekarang untuk mengakses pengalaman berjudi slot yang aman dan terjamin. Dengan layanan terbaik dan reputasi yang kokoh, Winning303 adalah pilihan terbaik bagi para penggemar judi slot. Jelajahi berbagai pilihan permainan dan raih kesempatan besar untuk meraih kemenangan di tahun ini dengan Winning303 [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]] [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]]
    • SLOT PULSA TANPA POTONGAN : SLOT PULSA 5000 VIA INDOSAT IM3 TANPA POTONGAN - SLOT PULSA XL TELKOMSEL TANPA POTONGAN  KLIK DISINI DAFTAR DISINI SLOT VVIP << KLIK DISINI DAFTAR DISINI SLOT VVIP << KLIK DISINI DAFTAR DISINI SLOT VVIP << KLIK DISINI DAFTAR DISINI SLOT VVIP << SITUS SLOT GACOR 88 MAXWIN X500 HARI INI TERBAIK DAN TERPERCAYA GAMPANG MENANG Dunia Game gacor terus bertambah besar seiring berjalannya waktu, dan sudah tentu dunia itu terus berkembang serta merta bersamaan dengan berkembangnya SLOT GACOR sebagai website number #1 yang pernah ada dan tidak pernah mengecewakan sekalipun. Dengan banyaknya member yang sudah mempercayakan untuk terus menghasilkan uang bersama dengan SLOT GACOR pastinya mereka sudah percaya untuk bermain Game online bersama dengan kami dengan banyaknya testimoni yang sudah membuktikan betapa seringnya member mendapatkan jackpot besar yang bisa mencapai ratusan juta rupiah. Best online Game website that give you more money everyday, itu lah slogan yang tepat untuk bermain bersama SLOT GACOR yang sudah pasti menang setiap harinya dan bisa menjadikan bandar ini sebagai patokan untuk mendapatkan penghasilan tambahan yang efisien dan juga sesuatu hal yang fix setiap hari nya. Kami juga mendapatkan julukan sebagai Number #1 website bocor yang berarti terus memberikan member uang asli dan jackpot setiap hari nya, tidak lupa bocor itu juga bisa diartikan dalam bentuk berbagi promosi untuk para official member yang terus setia bermain bersama dengan kami. Berbagai provider Game terus bertambah banyak setiap harinya dan terus melakukan support untuk membuat para official member terus bisa menang dan terus maxwin dalam bentuk apapun maka itu langsung untuk feel free to try yourself, play with SLOT GACOR now or never !
    • BRI4D adalah pilihan tepat bagi Anda yang menginginkan pengalaman bermain slot dengan RTP tinggi dan transaksi yang akurat melalui Bank BRI. Berikut adalah beberapa alasan mengapa Anda harus memilih BRI4D: Tingkat Pengembalian (RTP) Tertinggi Kami bangga menjadi salah satu agen situs slot dengan RTP tertinggi, mencapai 99%! Ini berarti Anda memiliki peluang lebih besar untuk meraih kemenangan dalam setiap putaran permainan. Transaksi Melalui Bank BRI yang Akurat Proses deposit dan penarikan dana di BRI4D cepat, mudah, dan akurat. Kami menyediakan layanan transaksi melalui Bank BRI untuk kenyamanan Anda. Dengan begitu, Anda dapat melakukan transaksi dengan lancar dan tanpa khawatir. Beragam Pilihan Permainan BRI4D menyajikan koleksi permainan slot yang beragam dan menarik dari berbagai provider terkemuka. Mulai dari tema klasik hingga yang paling modern, Anda akan menemukan banyak pilihan permainan yang sesuai dengan selera dan preferensi Anda.  
    • SPARTA88 adalah pilihan tepat bagi Anda yang menginginkan agen situs slot terbaik dengan RTP tinggi dan transaksi yang mudah melalui Bank BNI. Berikut adalah beberapa alasan mengapa Anda harus memilih SPARTA88: Tingkat Pengembalian (RTP) Tinggi Kami bangga menjadi salah satu agen situs slot dengan RTP tertinggi, mencapai 98%! Ini berarti Anda memiliki peluang lebih besar untuk meraih kemenangan dalam setiap putaran permainan. Beragam Pilihan Permainan SPARTA88 menyajikan koleksi permainan slot yang beragam dan menarik dari berbagai provider terkemuka. Mulai dari tema klasik hingga yang paling modern, Anda akan menemukan banyak pilihan permainan yang sesuai dengan selera dan preferensi Anda. Kemudahan Bertransaksi Melalui Bank BNI Proses deposit dan penarikan dana di SPARTA88 cepat, mudah, dan aman. Kami menyediakan layanan transaksi melalui Bank BNI untuk kenyamanan Anda. Dengan begitu, Anda dapat melakukan transaksi dengan lancar tanpa perlu khawatir.
    • Slot Bank ALADIN atau Daftar slot Bank ALADIN bisa anda lakukan pada situs WINNING303 kapanpun dan dimanapun, Bermodalkan Hp saja anda bisa mengakses chat ke agen kami selama 24 jam full. keuntungan bergabung bersama kami di WINNING303 adalah anda akan mendapatkan bonus 100% khusus member baru yang bergabung dan deposit. Tidak perlu banyak, 5 ribu rupiah saja anda sudah bisa bermain bersama kami di WINNING303 . Tunggu apa lagi ? Segera Klik DAFTAR dan anda akan jadi Jutawan dalam semalam.
  • Topics

×
×
  • Create New...

Important Information

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