Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.8] My First Modding Experience


statphantom
 Share

Recommended Posts

Hello, amateur coder, complete novice minecrafter here. I am doing some home projects to understand all the events, how they interact etc etc.

 

 

I decided to change the Topic / Title of this thread since it has kind of become my HUB for help / progression on my Mod(s). I will post any ideas / problems / progressions I have and people can help me out develop my mod, I am using 1.8 as a pure learning curve, get something done that is playable to me and then come 1.9 I will adapt everything into 1.9 and then release it to the public :)

 

My Idea is create a 'leveling from scratch mod' where you start from nothing but everything is harder to get and realistic (well as realistic as it can be), and also have to level up a various number of skills. e.g. you wake up, you gain the perception skill. you take your first step you gain the strength and agility skills ETC. Please post ANYTHING you like here, any ideas, any problems you can foresee, or any advice / help :)

 

Remember I am very new to minecraft modding so this will take a while and I will need a lot of help also, Thanks!

 

~ Statphantom

 

NEW VIDEO: 18/10/15

 

To Do:

Add some fibrous plans (Jute Cotton etc.) to world gen.

Get some good textures

Add panning for metals

Add camp fires

Add bark building blocks for homes

Create skills / levels GUI

 

Done:

Added string / rope from tensile weeds

tall grass drops tensile weeds on occation

Saved skills variables through death

Created 3 skills for testing

Crafting table

New wood axe mechanics

Add bark from trees

Sticks can only be gathered from grass that has leaves above it

Language file

Learned texture placement

Remove tree punching

Add sticks from grass

Link to comment
Share on other sites

  • Replies 71
  • Created
  • Last Reply

Top Posters In This Topic

PlayerInteractEvent is for interaction, it would be useful if you would need to perform one-time task when clicking on block.

 

In this case - mining in MC is a continuous task. It is being called every tick when you are mining. Also - breakSpeed is player-related (calculated during task) so using this event you could make one player not be able to mine wool, and ther would do that easily.

 

Oh and if you don't know: -1.0F comes from Block#setIndestructible (or something like that), lookup bedrock.

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Thanks! the API changes a lot so I find a lot of outdated information, I do know coding (C and C++ mostly) and am very interested in coding / gaming so learning minecraft is a perfect middle ground, At RMIT university to learn code. But anywho I won't go to the extreme of bothering you via skype calls and I just need pushes in the right direction, I have this so far...

 

@SubscribeEvent
public void onPlayerClickEvent(PlayerInteractEvent event) {
if (event.action == Action.RIGHT_CLICK_BLOCK) {

	if (event.entityPlayer.getCurrentEquippedItem() == null) {

		if (event.world.getBlockState(event.pos).getBlock() == Block.getBlockById(2)) {


		}
	}
}
}

 

seems to be happy, now lets learn about item and block replacements :P

 

Thanks a lot for your help, it is not going unnoticed :)

Link to comment
Share on other sites

All code that SETs data should be ran on server side:

http://www.minecraftforge.net/forum/index.php/topic,33918.msg178740.html#msg178740

 

Apply this to your code (!world.isRemote) - this is one of most important things about MC code design.

 

Block.getBlockById(2)

 

As of 1.7+ - NEVER refere to blocks on per-ID besis.

IDs are being assigned on WORLD creation, not on game startup. Each world has its own dictionary, in one world 500 can be something and in other  - something else.

You should never, ever, in any case, use Item/Block IDs, always instances (e.g.: Blocks.apple).

 

Note that while vanilla IDs are actually static - so no harm here, it's still bad practice (and slower).

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Thanks, I got confused between the Block and Blocks classes so have fixed this (if (event.world.getBlockState(event.pos).getBlock() == Blocks.grass)) :P

 

also how do I make the code server side only? do I create a new method called 'swapGrassForDirt'? or can I add @sideonly(side.SERVER) just before the manipulation.

 

	@SubscribeEvent
        @SideOnly(side.SERVER) <------- here?
public void onPlayerMineEvent(PlayerEvent.BreakSpeed event) {

	if (event.state.getBlock() == Blocks.log) {

                        @SideOnly(side.SERVER) <------- or here?
		event.newSpeed = -1;

	} else {

	}
}

 

 

also, sadly the ONE thing I never learnt in java was thread handling so while I can read and understand that link, don't entirely know how to implement them :P

on a VERY related topic, where would I add the !world.isRemote check?

Link to comment
Share on other sites

Yes, most of events are called on both logical sides, isRemote decides which logical side can pass the test. All of data manipulation should happen on server.

 

true = client

false = server

 

I am pretty sure I gave good explanation in link provided. (Might take some questions to get it tho :P)

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Got it working :) right-clicking on grass with an empty hand replaces it with dirt :) please let me know if something is wrong either way.

 

 

 

@SubscribeEvent
public void onPlayerClickEvent(PlayerInteractEvent event) {
if (event.action == Action.RIGHT_CLICK_BLOCK) {

	if (event.entityPlayer.getCurrentEquippedItem() == null) {

		if (event.world.getBlockState(event.pos).getBlock() == Blocks.grass) {

			if (!event.world.isRemote) {
				event.world.setBlockState(event.pos, Blocks.dirt.getDefaultState());
			}
		}
	}
}
}

 

now I will focus on item drops, and so only facing the top of the grass blocks works :)

Link to comment
Share on other sites

Yes, most of events are called on both logical sides, isRemote decides which logical side can pass the test. All of data manipulation should happen on server.

 

true = client

false = server

 

I am pretty sure I gave good explanation in link provided. (Might take some questions to get it tho :P)

 

Yep that worked perfectly, i got a bit confused with the @SideOnly annotation, I think I am understanding it correctly that it basically does the same thing as the isRemote check however it is for a full method, so you don't need both of them.

Link to comment
Share on other sites

Not quite. 'isRemote' is logical check, @SideOnly is, let's call it "code-check".

 

Anything annotated with @SideOnly will ONLY exist on provided .jar.

 

Minecraft.class is @SideOnly(Side.CLIENT) - that means that Forge will NOT LOAD whole Minecraft.class into Java VM if it somehow appear in Dedicated.jar file (known as minecraft_server.jar).

 

Same goes other way around. If you run a Client.jar - anything marked with Side.SERVER will NOT be present in your environment.

 

Generally - don't use it... like at all (almost no point).

 

Example of when there is a point in doing it: Say you want server to use external SQL database. Why would client do it? In this case you could proxify access - make client use @SideOnly(Side.CLIENT) method that would return data from e.g local .json and server use Side.SERVER methods/classes that would setup SQL database interaction (for dedicated server only). Whole @SideOnly is not needed, but will save you some pointless class-loading.

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Since you mentioned:

 

Main data types in minecraft are:

 

Singletons:

Item - description of what you hold in hand, Items DON'T hold data, they just "act" on data provided.

Block - similar to Items - those just act on data based on their instance, BlockState and TileEntity.

 

"Per-instance":

ItemStack - object that is actually being in your hand. ItemStack hold info about what Item it is, along with internal NBT data. internal NBT data consists of stackSize, metadata and CustomNBTData. CustomNBTData is something you can put your stuff into.

BlockState - 4 bits of data assigned to position in world. BlockState, often called metadata, can be used to e.g add facing sides to block (like furnace).

TileEntity - non-mobile object in world. TileEntity can exist in some BlockPos - you could call it "a layer over position". E.g when you place block you can also make it place TileEntity in its position. TileEntity can hold any data you want.

Entity - quite like TileEntity but moving-living.

 

Basically, that's all you need to know. Then there are more events, more packets and extended data (WorldSaveData, IExtendedEntityProperties).

 

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

The important difference between @SideOnly and isRemote is:

 

- SideOnly checks the jar file. Meaning: a method with @SideOnly(Side.SERVER) will NOT exist in the integrated server (!), because that is part of the client jar file.

 

- @SideOnly is never needed (unless you override vanilla method that has it). You can always achieve the same result (cleaner, most of the time) with @SidedProxy. The problem with a @SideOnly method is that you cannot easily call it, unless you are already in a @SideOnly method yourself. That is not the case with @SidedProxy.

Link to comment
Share on other sites

I can force an item to spawn at my feet, however how do I spawn this item at the event.world.loc? also this only worlds for vanilla items, how do I spawn in a custom made item? lets call it 'sharpStick'

 

current code is:

 

	@SubscribeEvent
public void onPlayerClickEvent(PlayerInteractEvent event) {
	if (event.action == Action.RIGHT_CLICK_BLOCK) {

		if (event.entityPlayer.getCurrentEquippedItem() == null) {

			if (event.world.getBlockState(event.pos).getBlock() == Blocks.grass && event.face == event.face.UP) {

				if (!event.world.isRemote) {
					event.world.setBlockState(event.pos, Blocks.dirt.getDefaultState());

					event.entity.dropItem(Items.stick, 1);
				}						
			}
		}
	}
}

 

I would like to replace event.entity.dropItem(Items.stick, 1); with a line that can drop my custom item on top of the block I right clicked on.

 

my Item class just incase you want to see it.

 

public class SharpStick extends Item {

private final String name = "sharpStick";

public SharpStick() {

	GameRegistry.registerItem(this, name);
	setCreativeTab(CreativeTabs.tabMisc);
	setUnlocalizedName(name);
}

public String getName() {
	return name;
}
}

 

Link to comment
Share on other sites

Thanks! the API changes a lot so I find a lot of outdated information, I do know coding (C and C++ mostly) and am very interested in coding / gaming so learning minecraft is a perfect middle ground, At RMIT university to learn code.

 

That's great!  I also knew mostly c and c++ before going into this.

 

One thing to note is that some actions that you want to happen would probably be better inside the blocks themselves.

 

Example from within a block that can be created

public class testBlock extends Block{

private IBlockState state;

public testBlock(Material material, IBlockState state){
super(material);
this.state = state; //This could be the block you want it to be changed to when it is right Clicked
}

//When the block is right clicked, basically.
@Override
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ){

//This will be called when the block is right clicked.  So it's changed to the state you passed in the constructor.
//Also, only make changes with blocks on the server.  To check, do this.
if(!worldIn.isRemote){
worldIn.setBlockState(pos, this.state);

//You could also have the player drop items from here, but I'll let you figure that out (You already did in the event handler!)

}

 

I have not tested the above code, but I am pretty sure it would work!

 

I know you're messing around with events for the most part, but I thought that this would help you some how.

 

Events are definitely good when working with vanilla blocks, but if you do end up creating new items, know that this is an option!:)

 

Either way, good luck with everything!  I hope this helps you.

Link to comment
Share on other sites

This works fine for any Items. Your Items are not any different than vanilla Items.

So, you want to spawn an Item when a Block is right-clicked?

You can simulate a Block drop easily using Block.spawnAsEntity(world, pos, itemStack).

 

What do I use to get the itemStack of a custom item? Items class only contains vanilla items, do I need to do a search for name?

Link to comment
Share on other sites

Thanks! the API changes a lot so I find a lot of outdated information, I do know coding (C and C++ mostly) and am very interested in coding / gaming so learning minecraft is a perfect middle ground, At RMIT university to learn code.

 

That's great!  I also knew mostly c and c++ before going into this.

 

One thing to note is that some actions that you want to happen would probably be better inside the blocks themselves.

 

Example from within a block that can be created

public class testBlock extends Block{

private IBlockState state;

public testBlock(Material material, IBlockState state){
super(material);
this.state = state; //This could be the block you want it to be changed to when it is right Clicked
}

//When the block is right clicked, basically.
@Override
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ){

//This will be called when the block is right clicked.  So it's changed to the state you passed in the constructor.
//Also, only make changes with blocks on the server.  To check, do this.
if(!worldIn.isRemote){
worldIn.setBlockState(pos, this.state);

//You could also have the player drop items from here, but I'll let you figure that out (You already did in the event handler!)

}

 

I have not tested the above code, but I am pretty sure it would work!

 

I know you're messing around with events for the most part, but I thought that this would help you some how.

 

Events are definitely good when working with vanilla blocks, but if you do end up creating new items, know that this is an option!:)

 

Either way, good luck with everything!  I hope this helps you.

 

Thanks! any information is helpful since I'm starting out, I am messing with vanilla blocks right now but when I do custom blocks I will DEFINITELY come back here and re-read this :)

Link to comment
Share on other sites

Finally got it working! the problem was is anouther coder told me to add the registry add inside of the constructor for my item so when I created a new item it was registering the item twice.... or am I supposed to do this in a way that I dont create a new SharkStick() object? I will post all 3 of my classes so anyone can tell me if anything is wrong, thanks :)

 

Main Mod Class

 

package tutorial.generic;

import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;

@Mod(modid = Level.MODID, name = Level.MODNAME, version = Level.VERSION)
public class Level {
    public static final String MODID = "StatsLevelMod";
    public static final String MODNAME = "Level";
    public static final String VERSION = "1.0.1";
    
    public static Item sharpstick;
    
    
    @EventHandler
    public void preInit (FMLPreInitializationEvent event) {
    	
    	System.out.println("Loading " + MODNAME + "!");
    	System.out.println("Version " + VERSION + "!");
    	
    	sharpstick = new SharpStick();
    	GameRegistry.registerItem(sharpstick, ((SharpStick) sharpstick).getName());
    	
    	MinecraftForge.EVENT_BUS.register(new LevelEventHandler());
    	
    	GameRegistry.addRecipe(new ItemStack(sharpstick),
    	"A ",
    	" A",
    	'A', Items.stick);
    }
    
    @EventHandler
    public void init(FMLInitializationEvent event) {
    	
    	
    }
    
    @EventHandler
    public void postInt (FMLPostInitializationEvent event) {
    	
    	System.out.println(MODID + " loaded successfuly!");
    }
}

 

 

Event Handler Class

 

package tutorial.generic;

import net.minecraft.block.Block;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class LevelEventHandler {

@SubscribeEvent
public void onPlayerMineEvent(PlayerEvent.BreakSpeed event) {

	if (event.state.getBlock() == Blocks.log) {

		event.newSpeed = -1;

	} else {

		event.newSpeed = -1;
	}
}

@SubscribeEvent
public void onPlayerClickEvent(PlayerInteractEvent event) {
	if (event.action == Action.RIGHT_CLICK_BLOCK) {

		if (event.entityPlayer.getCurrentEquippedItem() == null) {

			if (event.world.getBlockState(event.pos).getBlock() == Blocks.grass && event.face == event.face.UP) {

				if (!event.world.isRemote) {
					event.world.setBlockState(event.pos, Blocks.dirt.getDefaultState());

					Item drop = new SharpStick();

					Block.spawnAsEntity(event.world, event.pos, new ItemStack(drop));
				}						
			}
		}
	}
}
}

 

 

My Item Class

 

package tutorial.generic;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraftforge.fml.common.registry.GameRegistry;

public class SharpStick extends Item {

private final String name = "sharpStick";

public SharpStick() {

	setCreativeTab(CreativeTabs.tabMisc);
	setUnlocalizedName(name);
}

public String getName() {
	return name;
}
}

 

 

Thanks again for all your help guys!

 

 

PS: also need to make the item stackable :)

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




×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.