Amazon Ad

Saturday, June 3, 2017

Entities Part 1: Setting Up

At long last, we are going to start learning how to create an entity. So let's get into defining what an entity is in minecraft.

There are two different kinds of entities: Entities and Mobs

Entities are anything that exist in the world that are not in the inventory and are not blocks. Some entities are spawned in the world to hurt other entities while some only occur in the world as items, which are EntityItems. Entities have a world, x, y, z, and some have acceleration depending on what kind of entity it is. There are also ThrowableEntities which, as examples, are like splash potions and ender pearls.

Now Mobs are another story. Mobs are anything that aren't items or blocks and have an AI. Mobs have many different fields that go with it by default including posX, posY, posZ, motionX, motionY, and motionZ, just to name a few. You can register and render a mob using the EntityRegistry in the Forge API.

So what kind of activity can we do to practice with entities. I thought of an entity that we can make. It's a lion-like creature that fires a ball of lightning and will stun the player upon contact (a mob that fires an entity). The way we are going to do this is we will do the basic entity setup in this tutorial and in the next tutorial we will do the AI. After that, we will set up the entity for the stun bolt, then we will put it all together. This will all occur over a span of about ~1-1/2 months as I have my own mods to do as well as school to stay on task with.

So let's start with creating a directory for our entities and create a class for our mob and call it EntityKao. We will extend it to EntityMob which is the class we will inherit from for all of our mob's properties. We will need to inherit a few methods from EntityMob including,


  • initEntityAI
  • applyEntityAttributes
The initEntityAI method is how we set what AI we want for the mob. There is a whole list of AI and there is a rule of thumb for the execution of the AI. Certain AI cannot be executed at once as others while some can be executed with others. Here's the list of AI and the categories that they belong in:

Category 1
  • EntityAIAvoidEntity
  • EntityAICreeperSwell
  • EntityAIDefendVillage 
  • EntityAIFleeSun 
  • EntityAIHurtByTarget 
  • EntityAIMoveIndoors 
  • EntityAIMoveThroughVillage  
  • EntityAIMoveTowardsRestriction 
  • EnttiyAIMoveTowardsTarget 
  • EntityAINearestAttackableTarget 
  • EntityAIOwnerHurtByTarget 
  • EntityAIOwnerHurtTarget 
  • EntityAIPanic 
  • EntityAIPlay 
  • EntityAIRunAroundLikeCrazy 
  • EntityAIWander 
  • EntityAIWanderAvoidWater 

Category 2
  • EntityAIBeg 
  • EntityAIWatchClosest 
  • EntityAIWatchClosest2 

Category 3
  • EntityAIAttackMelee 
  • EntityAIAttackRanged 
  • EntityAIAttackRangedBow 
  • EntityAIFollowGolem 
  • EntityAIFollowOwner 
  • EntityAILookAtVillager 
  • EntityAILookIdle 
  • EntityAIMate 
  • EntityAIOcelotAttack 
  • EntityAITempt 
  • EntityAIVillagerMate 
  • EntityAIZombieAttack 


Category 4
  • EntityAISwimming 

Category 5
  • EntityAILeapAtTarget 
  • EntityAILlamaFollowCaravan 
  • EntityAIMoveToBlock 
  • EntityAISit 
  • EntityAITradePlayer 


Category 7
  • EntityAIEatGrass 

Unknown Category
  • EntityAIDoorInteract 
  • EntityAIFindNearest 
  • EntityAIFindNearestPlayer 
  • EntityAIFollowParent 
  • EntityAIHarvestFarmland 
  • EntityAILookAtTradePlayer 
  • EntityAIOcelotSit 
  • EntityAIOpenDoor 
  • EntityAIRestrictOpenDoor 
  • EntityAIRestrictSun 
  • EntityAISkeletonRiders 
  • EntityAITarget 
  • EntityAITargetNonTamed 
  • EntityAIVillagerInteract 

When you want to add an AI to your mob, you have to add it to a task. Some have to be added to a targetTask, because they search for targets. A few examples would be EntityAIAttackMelee, EntityAIAttackRanged, EntityAIFindNearestAttackableTarget, etc.

So let's add some AI to our mob. We will add three AI for now, which will be EntityAILookIdle, EntityAIWander, and EntityAIAttackMelee. We have to give them a priority of when we want them to fire. This is how they should look like in our class (I know, at long last enough of me babbling)

Next, we want to set the entity attributes, which are stuff like health and speed. So we can add in lines just like you see below. There's really not much. If you wanna explore then by all means, go on ahead, but this is as much as I am going to show.


Well, this concludes this part of the entities tutorials. I hope this at least gets you started in creating a mob.

Wednesday, May 24, 2017

Custom Commands

I decided to do a tutorial on commands since there aren't really any tutorials on commands these days. So without further-a-do, let's get to it.

Remember at part two of setting up with IntelliJ while we were creating the proxies, we created two extra methods called "serverStarting(event)" and "serverStopping(event)"? Well, it's now time to utilize them...well...one of them at least! We are going to need to use the "serverStarting(event)" method to register a command to the logical server. So we need to create that same method in our main mod class, annotate it with "@Mod.EventHandler" and pass in "FMLServerStartingEvent" into it. It's going to contain a method we need in order to register our command. (Doing this for "serverStopping(event)" is optional since we are currently not using it).


Now we need to go into our CommonProxy class and register our yet to be created command.


Now we need to create a new class called CommandTutorial and we will put it in a new package called "command". This class needs to inherit from CommandBase, which is a base template for all commands in Minecraft. You will be prompted to override a few methods: "getName()", "getUsage(sender)", and "execute(server, sender, args[]) throws CommandException". For the "getName()" we are going to return the name of our command, which is going to give our command the "/<name_here> <args_1> [args_2] ... [args_8]" look, and the args[] is everything typed after the name of the command separated by spaces. So for the tutorial we should give our command the name "tut", for simplicity and consistency. The "getUsage(sender)" method is returned to us when we try to get the usage for that command. The "execute(server, sender, args[]) throws CommandException" is what we want to happen after the player presses enter with our command entered in. So we are going to specify that.in our "execute()" comand.

First, we need to get the world of the command sender. The command sender is whomever is sending it, the player practically, and get's the entity world out of it. Then we need to check if we are on the client side or on server side. Again, using world.isRemote to check that means that returning true is on the client logical side and returning false means server logical side. We should also print depending on which side we are on just in case we missed something.



Now we need to specify what we want to happen if we are processing on the server logical side. We are going to make a test command that will give us our custom blocks and items specifically. So we will need to get the player that is sending the command. Luckily, we don't need to do any witchcraft to pull that off, cause CommandBase has a method for getting the player; two methods, in fact. We are going to need to use one of them. There is "getPlayer(server, player, name)" and there is "getCommandSenderAsPlayer(sender)" which returns the player that is sending the command. We need that one. So let's create a new EntityPlayerMP object called "player" and initialize it to "getCommandSenderAsPlayer(sender)" and pass in "sender" as an argument. Now let's move on to the part of deciding what block or item to give to the player.

In order to tell Minecraft what block or item to give to the player, we need to test if the command looks like this:

/tut get <item:block>

So we need to see if the command sender has typed in "get" as the first argument.


Now if this is true, then we need to see if the command argument after that matches with any of our items/blocks unlocalized names.



Now we need to give the player the items or blocks requested. We need to create a new ItemStack with each of these items/blocks in it. There are two methods that we can use called "getBlockFromText(sender, name)" and "getItemFromText(sender, name)". We can use these when creating the itemstacks of the blocks/items. We give it a string and it matches the string with an unlocalized name of an item or block (depending on the method specified) and returns the item or block that it finds. Then, we can put it in the player's inventory by using a method in the "player.inventory" called "addStackToInventory(stack)". We need to do this for each item and block.


Let's print something to the screen whenever the command is successful!


Now we can test the mod and type in the command and see what it gives us!


It works for the item, and it also works for the blocks. Congrats! You just created a working command!

Multi-Textured Blocks

I know that this is a popular topic to learn so here it is!

Starting off, we need to review how the blocks are rendered in the game. Blocks are rendered using JSON files, or JavaScript Object Notation. When the model JSON is loaded it checks for various variants. These variants are used to determine how the block is then rendered onto the screen. (More information here). The only variant that we want to worry about today is the "textures" variant. This variant is responsible for reporting back to Minecraft which textures in what domain to render on what object. In this case, we want to render on our tutorial block custom textures that I will provide (or you can make your own if you want to). We are going to create grass and dirt blocks. First we are going to rename our tutorial block to dirt and create a second block and name it grass and create a second blockstates and model JSON files. We will call it "tut_grass" and "tut_dirt". Make sure you change the material to ground for the dirt and grass for, well, you know, grass. And also, change the harvest tool to "shovel" so that we can harvest it properly.

We need to make the blocks drop the proper drops. In the grass class, press CTRL+O and type in getItemDropped and press Enter. We need this method to return Item.getItemFromBlock(Blocks.tutDirt). This is going to make the block drop the dirt block instead of itself. If we add this exactly to the dirt class, but replace Blocks.tutDirt with this keyword, then we can ensure that the same thing happens for the dirt. Now we need to add this to the registry so that we can render it and test it. We need to go into the JSON files that we created earlier for the dirt and grass and rename everything, except the grass model file, leave everything there.

The grass model class is going to be different. You may have noticed the there is the variant "textures" and after that there is the child tag "all", which tell Minecraft to apply the following texture to all sides. What we want to do is tell Minecraft to apply certain textures to certain sides, and there are certain keywords to allow that to happen.

If we tell Minecraft to have the parent model be "cube" rather than "cube_all" then we can have a plethora of different faces for our textures. We can tell Minecraft to render a specific texture on a specific face. A face is defined as a side of a block that is facing a certain direction. There are currently, in vanilla,
  • "north"
  • "south"
  • "east"
  • "west"
  • "up"
  • "down"
We can specify a texture on any of these sides as long as we have the parent model of "cube" rather than the traditional "cube_all".

So now in our JSON file, if we specify the parent to be "cube" then change "all" to be various faces, we can achieve what we want easily.


We are telling it on the "up" face, we want to apply the "tut_grass_top" texture, and then the same texture for the "north", "south", "east", "west" faces because these are the sides of the cube. Then the "down" is the bottom of the cube.

We should also tell minecraft to render a particle when we walk or mine it by adding the "particle" variant in after "textures" which is going to give the texture for when we break the block and particles spawn.



Now if we put the following textures into our assets and run the game then we get the following result! Hopefully you do too! You can apply this concept to any block whatsoever.



Tuesday, May 23, 2017

Blocks, Items, Creative tabs, and all review

In the last tutorial, we created a util class that handles the registry and rendering of all of our blocks and items. Now we need to create our blocks and items. First we need to create a package in our main com.[your_domain].tut package and call it init and put two classes in there and called them Blocks and Items. Let's create a block and an item.

First the block in our Blocks class:


Now we create BlockTutBlock in a package called com.[your_domain].tut.blocks.


As I have said before, you do not have to format your code the way you see it here.

Now we have to make a class called BlockBase and put all of our templates.



Now you can create a block and initialize it all in it's constructor, whether you want to give it a light level, a harvest level, or make it just a basic block. Lastly, we now need to register and render it in our RegisterUtil class.


Now we need to create an item.


Then we create the item class and inherit from ItemBase



But wait, what if we don't wanna put our blocks and items into the vanilla creative tabs? Well, we should create a class called CreativeTabsHandler in our com.[your_domain].tut.handlers and put our new creative tab in their.


This creates a new creative tab with an unlocalized name of "tutTab" and we are setting the tab icon to be our newly created tut item.

Now we need to do the JSON's for our block and item. We can just copy from coal_ore and coal JSON's.

The way that IntelliJ creates directories is kinda weird so we will have to go into the actual folder and create the assets.tut.blockstates and assets.tut.models.item, assets.tut.models.block directories. If we go into the external libraries and open the forgeSrc and locate the assets then we can find the JSON files of coal_ore and coal. You can reference earlier tutorials for creating JSON files for blocks and items, nothing have changed. I will provide images for you if you do not know how to make images. I actually have a small Paint.NET tutorial here if you would like to learn how to make basic textures for items and blocks. You'd have to research or find ways into making higher quality textures though. Here is the link to a couple of textures, one of the block, and one of the item. Once you place them in the right directories, and run the mod, then it should work. I have already tested it.

If you have any questions, please feel free to ask in the comments!

Registry and Rendering Utils

Now we need to register and render our blocks and items properly. The last time we did that, we did it in a not so favorable fashion. The way that we did it was like this:

Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, meta, ModelResourceLocation)

This is becoming outdated and is now becoming taken over by a new method of rendering. We are going to create a class that will handle our rendering and registering. So let's create a class called RegisterUtil in a package dubbed util with the following contents.


We create a static void method that we will pass in the preinitialization event into (and I will show you why in a bit) and we create two private static void methods with the events needed as arguments as well as Block and Item as varargs. If you don't know what a vararg is, allow me to explain it to you briefly.

A vararg is simply an array of arguments that are dynamic, so you can have as many passed in as you want. You can either have none passed in, or you can have 100 passed in, as long as the variable that is passed in is of the same type. We can utilize this feature of Java to implement DRY (Don't Repeat Yourself).

First we are going to create the block registry and rendering  method before the item method, because we should do the more complicated one just to get it out of the way.

First, we have to create a foreach loop, which is a for loop that creates a new instance of an object and initializes it to an index of an array of the same type.



Now we need to create an ItemBlock for this new block instance. This new ItemBlock must be a constant so that it doesn't get changed in some way (just to be safe).




Now we need to register the block and itemblock. When we initialize the block before registering it (later on) we give it a registry name. That same registry name is going to be passed onto our itemblock. The itemblock is simply the block as an item in the inventory, using the item json model. Before we register these two, we need to make sure that we are not registering it on the server side, and only on the client side. This is why the FMLPreInitializationEvent argument was given as a parameter so that we can check for the client side. If we are on the client side, and not the server side then we can proceed with registering the block and item block.


So what is the "client side" and "server side" you may ask? Well, to put it simply, there is two different clients and two different servers. There's the physical and logical client and server. The physical client is the actual game that you actually play from the launcher. The physical server is the server you connect to when you wanna play with your friends. So running the minecraft_server.jar is known as the dedicated server, or the physical server. Then there is the logical server and the logical client. The logical client is what processes input and sends that input to the logical server. The logical server is what serves the game's logic, such as mob AI, world generation, weather, health, and other game mechanics. When we test for the client, we are testing for the logical sides. We are registering everything on the logical client and rendering on the logical server.

Now that we got that out of the way, we can definitely start rendering. Within this conditional, after the block and itemblock registry, we add our model registry. (Thanks to draco18s for fixing this! This would have caused some issued one the dedicated server!)



You don't have to format it the way that I did, you can put it all on one line, I had to do it this way in order to make the image fit. It's the same method as before, essentially, just called differently. No need to explain anything here. You can go to my previous tutorial on items if you want to view the explanation on it. Now we can move onto items, which is the same process but a bit shorter, but with items instead, and without itemblocks.



For testing purposes, we can added a logger at every step of this "util".



We are logging the unlocalized names of the blocks that are being registered to the console so that we can easily debug where we went wrong with something. And it's nice to know that our code is working well. Now it's time to make some blocks and items.

We are going to want to make a couple of classes in a packages dubbed init and called them Blocks and Items. In there, we will initialize our blocks and items. Then, in our RegistryUtil, we will register and render our blocks and items.

Before we continue, we need to call our registerAll(event) method in our CommonProxy#preInit(event) method, and pass in the event argument as the parameter, and we are good to go to the next tutorial.

Moderate Minecraft Modding Tutorial Part 2: Setting Up with IntelliJ Part 2

Before we start programming, we gotta fix a few things first! We have to set our language level and target level to be Java 8 and setup our run configurations to use the correct modules. First let's go into our settings by opening File > Settings... and then navigate our way to Build, Execution, Deployment > Compiler > Java Compiler. There we should see three modules.


We need to change the Target bytecode version to 1.8. After we change it, apply the settings and return to the main screen. Next we need to change our JDK to Java 8 by going to File > Project Structure > Project. We need to make sure that Project SDK is set to 1.8 and Project Language Level is set to 8. Next we need to go to Modules and go to tutorial > tutorial_main, which is the module we will use for building our mod. This is needs to have the language level set to 8 as well. If you didn't have to change anything then just close out and you're good, otherwise apply changes and return to the main screen.

Now we can finally start on programming!! Hooray! The fun part! Oh but wait! We still need to set everything up! Damn! Well, this time around it'll go smoother than last time!

First we will need to create the main mod class just like last time with the @Mod annotation and the three main event handlers, in a package with the same naming convention as last time (see my first modding tutorial for more details).


Ref is throwing an error at us so we need to create it and put our static constants in it.


Now we need to set up our proxies. We need to create the common and the client proxy. We need to get an instance of the common proxy which we will be accessing the proxy methods through.



Now we gotta create the necessary methods for the common and client proxies. There are two extra methods that I will get into some other time (such as commands). You should make two classes (CommonProxy and Client Proxy, Client Proxy inheriting from CommonProxy) and they should look like these two images:



In our main class, we need to call our proxies in our even handlers and pass the parameters as arguments so we can use them later whenever we need to.


Now we should probably get, for future reference, the instance of our mod.


Next we need to create a logger so that we can log to the console for debugging purposes.


Now we can use this logger in our main methods to signal to us that our mod initialization has began.


If we run our mod, we shouldn't have any problems and we should find our logs in the console during the pre-init, init, and the post-init phases of modloading.

We are now done with setting up! We can finally begin coding our blocks and items!

Moderate Minecraft Modding Tutorial Part 1: Setting Up with IntelliJ Part 1

Hello, everyone! I know I've been gone for a while, and I am sorry about that, but I am back with even better tutorials! I am going to show you how you can make even better mods with even better code! I will start with showing you how to set up your environment with JetBrains IDEA IntelliJ (which is now my new favorite IDE!) Let's start by obviously downloading and installing IntelliJ from here. Once you have gotten that installed, you are gonna want to go and get forge for 1.11.2 into a new separate folder somewhere on your computer. I will be using mappings for Minecraft Forge 1.11.2-13.20.0.2304. We are going to open IntelliJ and click on "Import Project..." (As shown below).


Navigate to your new project folder that you put your forge files in and double click build.gradle. Click Ok and it should open up a new window. (If your window is not dark theme you can configure it by doing some googling *wink wink*).

You're gonna want to navigate your mouse to the bottom left corner of IntelliJ and a list should pop up, including Gradle.



Click on Gradle and a new window should open on the right. Wait for the tasks to load and that might take a little while so give a bit. You should now see something like this,


Open up tasks and you should be able to view a bunch of different tasks. These tasks are performed through Gradle is how Forge organizes itself for obfuscation and compiling, and even releasing (which we will get to in a later post). Gradle is very useful for fetching code from remote locations and even executing tasks for a program. What we want to do is execute two different tasks, setupDecompWorkspace, and genIntellijRuns.

setupDecompWorkspace is going to setup our workspace so that we can view the minecraft source code along with the forge API. genIntellijRuns is going to setup our workspace to work with IntelliJ. When you run genIntelliJRuns, it will ask you to restart IntelliJ, which you will need to agree to do so in order for everything to work properly

To find these tasks you gotta go into tasks and go into forgegradle, and execute setupDecompWorkspace followed by genIntellijRuns. When these two tasks have completed and you have restarted your IDE, then you are going to need to set up your configurations. Before that, we need to refresh our workspace by clicking the refresh button at the top of our Gradle window. Now if you look in your External Libraries you should see forgeSrc-1.11.2-13.20.0.2304. We are now ready to start programming!

Sunday, February 12, 2017

Bonus Material: Raytrace and onItemRightClick event

Hello, my name is Alex and I am going to show you how to create a mod for minecraft forge 1.11.2. There's not a lot of tutorials on 1.11 so I am creating one for those that want to get started.

WARNING: IF YOU DO NOT KNOW BASIC JAVA, THIS MAY NOT BE RIGHT FOR YOU!!!

I'm gonna show you some bonus material for your minecraft mod. It was asked that I cover item properties, such as a specific ability when you right click with the item in your hand. Let's get started, shall we?

Let's start by creating an item that spawns lightning right where the player is looking. Create the texture for it first. I'm gonna use this texture:


You can use the texture too, you can download it from here.

Let's create an item and a class for this item.

1
public static Item lightningSpawner;

initialize it with our new ItemLightningSpawner class that we will create momentarily. Give it the parameters of name, and creative tab. But this time we are gonna give it a third parameter of maxStackSize, we will make it NOT stack. This is done by putting 1 as our third parameter.

Let's create the class and it's constructor just like our last item, extending to ModItem.

1
2
3
4
5
public class ItemLightningSpawner extends ModItem {
 public ItemLightningSpawner(String name, CreativeTabs tab, int size) {
  super(name, tab, size);
 }
}

Now we need to override the super's method onItemRightClick. This is one of the super methods inherited from the Item class that is activated when you hold an item in your hand and right click with it. There is this and onItemUse which the difference between the two is that the latter is only called when the cursor is on a block and you right click. We need to override the former and tell it to get the raytrace of the cursor, get the block position that it is on, and then spawn a lightning bolt right where it is.

1
2
3
@Override
public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) {
}

Let's start by testing if the side is a server or not by calling world.isRemote. This just specifies whether it is a client or not.

1
2
if(!worldIn.isRemote){
}

So we are testing if the world is on the client side or the server side because we want to spawn the lightning bolt as an entity in the world and we want it to show up for both the client and the server. Within this we need to create an object that stores the raytrace information of the player.

1
RayTraceResult pos = playerIn.rayTrace(100, 20);

The raytrace is the current position of the cursor in the world. It stores information like what block the player is looking at, what direction in the world the player is facing, what kind of block the player is looking at, etc. What we want is the block position of the cursor. We are setting the first value to 100 so that it gets the block position within 100 blocks. I don't know what the second position is but I believe it's the timespan the vector looks back in and whatever blockpos you were looking at during that time. So this example does 20 ticks, so whatever block pos you were looking at 20 ticks ago, it gets that information. I could be wrong though, so please correct me if I am wrong.

Next, we need to get the x, y, and z coordinates of the raytrace block position.

1
2
3
double x = pos.getBlockPos().getX();
double y = pos.getBlockPos().getY();
double z = pos.getBlockPos().getZ();

This does exactly what we want. It gets the x, y, and z coordinates of the current look vector of the player. Next we need to add the weather effect, and return the ActionResult as a success.


1
worldIn.addWeatherEffect(new EntityLightningBolt(worldIn, x, y, z, true));

This line of code just spawns in a new weather effect as an entity in the world. We create a new instance of EntityLightningBolt and we give it the parameters of world, x, y, z, true. It needs the world and the position it's spawning in. The true parameter, I honestly don't know what it does, but I'll look into it and update when I find out.


1
return new ActionResult(EnumActionResult.SUCCESS, new ItemStack(this));

This returns a successful action result event. I don't know much about it except that it is necessary. We pass in our class as the item for the item stack.

We need to complete the check we did earlier but including an else statement to our if.


1
2
3
else{
    return new ActionResult(EnumActionResult.FAIL, new ItemStack(this));
}

This ensures that whether the world is on client side, it doesn't fire for only the player, but for the entire server world.

Now we need models. Create the models for the item and texture and fire up the game. Get the item out of the creative tab and right click with it in your hand. Play with the lightning. It's fun!

Thursday, February 9, 2017

Armor

Hello, my name is Alex and I am going to show you how to create a mod for minecraft forge 1.11.2. There's not a lot of tutorials on 1.11 so I am creating one for those that want to get started.

WARNING: IF YOU DO NOT KNOW ANYTHING ABOUT JAVA, PLEASE LEARN THE BASICS BEFORE ATTEMPTING TO FOLLOW ANY MODDING TUTORIALS!!!!!


Let's start by creating our Armor's Items. Create a class called ArmorHandler in your Handler package. Within this we need to create our init, register, registerRenders, and registerRender(Item item) methods. Next wee need to create the items for our Armor.


1
2
3
4
public static Item tutHelmet;
public static Item tutChest;
public static Item tutLegs;
public static Item tutBoots;

We need to initialize them using a class we will create called ItemTutArmor. We are going to give it the parameters of NAME, CREATIVE TAB, ARMOR MATERIAL (we will create our own), and RENDER INDEX, EQUIPMENTSLOT.

The name and creative tab are pretty much self explanatory. The armor material is what will be our armor's durability, armor texture, strength, etc. The render index is what armor model it will use. Legs use a different model than the others. EquipmentSlot is what slot the armor is gonna go into, helmet goes into HEAD, chest goes into CHEST, etc.

1
2
3
4
tutHelmet = new ItemTutArmor("tut_helmet", CreativeTabHandler.tabCombat, MaterialHandler.TUTORIAL_ARMOR, 0, EntityEquipmentSlot.HEAD);
tutChest = new ItemTutArmor("tut_chest", CreativeTabHandler.tabCombat, MaterialHandler.TUTORIAL_ARMOR, 0, EntityEquipmentSlot.CHEST);
tutLegs = new ItemTutArmor("tut_legs", CreativeTabHandler.tabCombat, MaterialHandler.TUTORIAL_ARMOR, 1, EntityEquipmentSlot.LEGS);
tutBoots = new ItemTutArmor("tut_boots", CreativeTabHandler.tabCombat, MaterialHandler.TUTORIAL_ARMOR, 0, EntityEquipmentSlot.FEET);

Now we need to create the ItemTutArmor class. We need to set it up so that it utilizes our name and creative tab.


1
2
3
4
5
6
 public ItemTutArmor(String name, CreativeTabs tab, ArmorMaterial materialIn, int renderIndexIn, EntityEquipmentSlot equipmentSlotIn) {
  super(materialIn, renderIndexIn, equipmentSlotIn);
  setUnlocalizedName(name);
  setRegistryName(name);
  setCreativeTab(tab);
 }

We also need to extend our class to ItemArmor. Once you have done that, let's go ahead and create our ArmorMaterial. Our Armor Material is going to go into our MaterialHandler. We need to create a constant that will hold our armor material for us.


1
public static final ArmorMaterial NAME_OF_MATERIAL = EnumHelper.addArmorMaterial("<materialName>", "<textureName>", <durability>, new int[]{<headArmorPiecesAmount>, <chestArmorPiecesAmount>, <legsArmorPiecesAmount>, <feetArmorPiecesAmount>}, <enchantability>, <sound>, <toughtness>);

This is the format that we will go by for our material. Replace the corresponding name with whatever values that you want there. For me I am gonna go with the following:


1
public static final ArmorMaterial TUTORIAL_ARMOR = EnumHelper.addArmorMaterial("tutorial_armor", "tut:tutorial_armor", 1500, new int[]{3, 5, 4, 2}, 10, SoundEvents.ITEM_ARMOR_EQUIP_DIAMOND, 8F);

The name is the registry name, I have already went over this. The texture name is the name of the armor model texture. It is in the format of texture_name_layer_0 or texture_name_layer_1. As mentioned earlier, there is two different models. layer_0 is the layer that includes the helmet, chest, and boots. layer_1 is the layer with the pants. Next, the durability is how many times the armor can be hit before breaking. The integer array with the 4 different integers is how many halves of armor will be filled in the GUI, at the armor bar. The enchantability is the same as the tool enchantability. The sound is the sound that is played when you put on the armor. Lastly, the toughness is how tough it is, obviously. I don't know much about this but when I do, I will be sure to update.

Next is to create the armor textures. Make the textures. I will be borrowing from my mod, Mara: The Ultimate Nightmare (be sure to check it out. Link at the end of the tutorial!). We need to put the armor model textures in the folder textures/models/armor. Save your textures in the correct locations (the item textures in the item texture location). Register the armor and it's rendering and you finally have armor.

MAKE SURE YOU PUT YOUR ARMORHANDLER INIT, REGISTER, AND REGISTERRENDERS IN YOUR PROXIES!!!

The following is my result:



=====================================Armor Properties=====================================

If you would like to add potion effects to your armor, then here is how to:

Go into your Armor class and put in the onArmorTick method.


1
2
3
4
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) {
  
}

Within this we need to call on the player method addPotionEffect and pass in a new instance of PotionEffect. We then need to pass in an argument that is the potion effect (you can get the effect from MobEffects class). We also need to pass in the duration (in ticks) and the amplifier (whether it is I, II, III, etc).


1
player.addPotionEffect(new PotionEffect(MobEffects.HEALTH_BOOST, 100, 2));

I am adding a health boost when the armor is worn.


Congratulations, you just successfully made armor.

Saturday, February 4, 2017

Paint.NET Textures

I said I would do it, and here I am doing it now: Paint.NET Textures Tutorial!

What we need are two things: the vanilla minecraft assets folder, and Paint.NET (obviously). So let's go and get the assets folder first. We need to go to our ".gradle" folder in our User Directory. If you go to your User Directory > .gradle > caches > minecraft > net > minecraft > minecraft > 1.11.2 then there should be a JAR there with the appropriate name of minecraft-1.11.2.jar. If we right click that and go to 7-Zip > Open Archive then there should be a bunch of files and folders there waiting for us to extract them. Now, don't click extract because what we want is the assets folder. Open up your workspace directory, being the main mod folder, and drag and drop the assets folder into your main mod folder. Now close out of your 7-Zip.

Next, we gotta go to getpaint.net. There you should see the download on the top right-hand side of the page. Down a little ways should be a download button, in the form of an image. Once clicked, you should see a download link at the top right-hand section of the page. Click, download, run, and follow the on screen prompts. Once it is done installing (may take a few minutes), then open up Paint.NET.

Now once in Paint.NET, you're gonna want to click Open and navigate to the assets folder in your main mod class, and navigate to textures > blocks > find your texture. Let's use the diamond_ore.png texture.

Let's play with the hue and saturation. Go to Adjustments > Hue / Saturation.... Change the hue until it fits your liking.

TIP: YOU MIGHT WANT TO ZOOM IN ON THE IMAGE BY HOLDING CONTROL AND SCROLL UP BEFORE ADJUSTING ANYTHING

I'm gonna make my texture a reddish color. Mine are at 180 for hue, and 139 for saturation, but it is your texture so make it however you wish to make it.

Let's do CTRL+SHIFT+S and save it to our mod folder > src > main > resources > assets > tut > textures > blocks.

If you don't have textures.blocks created, then create it.

We need to save it with the name that we specified in our JSON file, back in the Blocks tutorial. Ours is tut_block, so let's save it as tut_block.png.

Here is my finished result:


Let's make an item texture. Go back into Paint.NET and open up a texture from assets > minecraft > textures > items. Let's use the diamond.png texture.

Go to adjustments > Hue / Saturation... and play with the settings until it fits your likings. I'm going to keep mine where it is from the block texture settings, giving it, too, a reddish color. CONTROL + SHIFT + S and save it to src > main > resources > assets > tut > textures > items. If you don't have an items folder then create one. We also have to save this with the name that we specified in our JSON file that we created for our item, created back in the Items tutorial Here is my finished product for the item texture:


Now go back to the project and run the game and you should have the textures loaded in.

Thursday, February 2, 2017

Ore Gen

Hello, my name is Alex and I am going to show you how to create a mod for minecraft forge 1.11.2. There's not a lot of tutorials on 1.11 so I am creating one for those that want to get started.

WARNING: IF YOU DO NOT KNOW ANYTHING ABOUT JAVA, PLEASE LEARN THE BASICS BEFORE ATTEMPTING TO FOLLOW ANY MODDING TUTORIALS!!!!!


In this tutorial, we will be looking at how ore generation works. We will be generating our block/ore that we created back in the blocks tutorial. Let's start by creating a package called "com.<yourname>.tut.world". In here we will create a class called "WorldGenOre". We will implement IWorldGenerator and add the unimplemented method, generate. In this method we will have a switch method, that switches through the different dimensions.


1
2
3
4
5
 public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) {
  switch(world.provider.getDimension()){
  
  }
 }

We get the dimension type through world.provider.getDimension(). This is an integer that is given to each dimension as a unique ID. Nether is -1, Overworld is 0, and End is 1. So we need to specify what happens in each of these cases.

We want to create a method for each of these dimensions, genSurface, genNether, and genEnd.

Within each of these, let's start with genSurface, we want to call a method, that we will make, called addOreSpawn.


1
2
3
private void genSurface(World world, Random random, int chunkX, int chunkZ){
 addOreSpawn(BlockHandler.tutBlock.getDefaultState(), world, random, chunkX, chunkZ, 16, 16, 50, 20, 10, 100, BlockMatcher.forBlock(Blocks.STONE));
}

It takes in 12 arguments: block to spawn, the world, random, chunkX, chunkZ, maxX, maxZ, the chance of it spawning, minimum Y spawn, max Y spawn, and block to generate in.

Block to spawn is the block that we are generating, obviously.

The World is self explanatory, and so is random.

ChunkX is the chunk on the X axis that is being generated. It is often a 16 X 256 X 16 cube of cubes. 256 is the highest Y value a block can be placed in the world. 16 is the max size of the chunk on the X and Z axis.

MaxX and MaxZ are the max size of the chunk that the ore can be generated in. The maths goes like this:

16 + rand.nextInt(16)

So technically, the max X spawn can be generated anywhere along the X axis in a chunk between 16 and 32. The same goes for the Z spawn.

MaxVeinSize is the max number of blocks that will be spawned in a vein.

Chance is the chance that the block will be spawned. It iterates through a for loop and the lower the number, the rarer, because it goes through the entire chunk and generates that many times in the chunk. If you put 1, it will only generate 1 vein in a chunk.

MinY and MaxY are are the Y spawn coords for the vein. We work out a random number between the two parameters.

BlocksToSpawnIn is the block that the ore will be found in. We will choose STONE for this.

Let's create the addOreSpawn method and implement our for loop and generate our ores.

1
2
3
4
5
6
7
8
9
 private void addOreSpawn(IBlockState block, World world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ, int maxVeinSize, int chance, int minY, int maxY, Predicate<IBlockState> blockToSpawnIn){
  int diffMinMaxY = maxY - minY;
  for(int x = 0; x < chance; x++){
   int posX = blockXPos + random.nextInt(maxX);
   int posY = minY + random.nextInt(diffMinMaxY);
   int posZ = blockZPos + random.nextInt(maxZ);
   (new WorldGenMinable(block, maxVeinSize, blockToSpawnIn)).generate(world, random, new BlockPos(posX, posY, posZ));
  }
 }

First, we get the range of the min and max Y values. Then we iterate through our chance, and iterate through it. Next we created a posX, posY, and posZ. The posX is a random number between the chunk boundary and a random number of the other chunk boundary, being 16 + rand(16). The same applies for the Z axis. The posY is a random number between the min Y and a random number of the difference of the min and max Y. Then we instantiate a new WorldGenMinable which is how we generate our ore in the world. We give it the arguments of the block state, max vein size, and the block to spawn in. We then call the WorldGenMinable.generate method, and give it the arguments world, random, and a new BlockPos, given the posX, posY, and posZ values.

Our blockToSpawnIn is a predicate of a block state. I don't know too much about it, so I can't discuss it too much.

We get the block state of the block we want to generate because some blocks have different state. For example: redstone. It has lit and unlit blockstates It generates the default blockstate, being unlit, so that it can change between lit and unlit within the world.

Now we need to register our world generator. Go into your CommonProxy and register the World Generator we created.


1
GameRegistry.registerWorldGenerator(new WorldGenOre(), 0);

The 0 is the weight of the generator. We will make it 0 for simplicity, so it is loaded first every time, after the vanilla generator.

Once you have gotten it registered, go ahead and run the game and CREATE A NEW WORLD EVERY TIME YOU MAKE A CHANGE TO WORLD GENERATION!!!!!!