Posted September 24, 20159 yr 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
September 24, 20159 yr @SubscribeEvent public void onPlayerBreakSpeed(PlayerEvent.BreakSpeed event) { if (event.state.getBlock() == Blocks.wool) { event.newSpeed = -1.0F; } } // Wool is now +/- like bedrock. 1.7.10 is no longer supported by forge, you are on your own.
September 24, 20159 yr Author Thanks! May I ask why this needs PlayerEvent instead of PlayerInteractEvent? has the latter been depreciated?
September 24, 20159 yr 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.
September 24, 20159 yr Author How would you do this for PlayerInteractionEvent? as another example, right click a grass block and it will replace it with a dirt block? so far I have this... @SubscribeEvent public void onPlayerClickEvent(PlayerInteractEvent event) { if (event.action == Action.RIGHT_CLICK_BLOCK) { } }
September 24, 20159 yr event.player.worldObj.setBlockState(state) // figure it out. All code that SETs data should be ran on server side: http://www.minecraftforge.net/forum/index.php/topic,33918.msg178740.html#msg178740 Note: Point 5 applies ONLY if you know java. 1.7.10 is no longer supported by forge, you are on your own.
September 24, 20159 yr Author 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 Thanks a lot for your help, it is not going unnoticed
September 24, 20159 yr 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.
September 24, 20159 yr Author Thanks, I got confused between the Block and Blocks classes so have fixed this (if (event.world.getBlockState(event.pos).getBlock() == Blocks.grass)) 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 on a VERY related topic, where would I add the !world.isRemote check?
September 24, 20159 yr never use sideonly if u have no idea what u are doing. if(event.world.isRemote) doStuff();
September 24, 20159 yr Author never use sideonly if u have no idea what u are doing. if(event.world.isRemote) doStuff(); does this mean that both client and server will read this but only the client will pass the test?
September 24, 20159 yr 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 ) 1.7.10 is no longer supported by forge, you are on your own.
September 24, 20159 yr Author 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
September 24, 20159 yr Author 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 ) 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.
September 24, 20159 yr 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.
September 24, 20159 yr Author understood, so basically anything @SideOnly(side.SERVER) wouldn't even compile in the clients code? PS: got 'face' checking working really well really quickly, getting the hang of this but ItemStacks will be a bit harder I think.
September 24, 20159 yr 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.
September 24, 20159 yr Author another snag now I created an Item fine, added to the registry, can craft the item fine, but how do I spawn it without adding it to a block break drop? e.g. right clicking grass at the top with change the grass into dirt and then spawn a stick (mimics searching through the grass for a branch)?
September 24, 20159 yr Author 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; } }
September 24, 20159 yr 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.
September 25, 20159 yr Author 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?
September 25, 20159 yr Author 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
September 25, 20159 yr Author 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
September 25, 20159 yr From within the constructor inside your item class, type "this." And it should give you a list of things that you can mess around with. I believe stack size is in there. Another thing that you can do, at least if you're in eclipse, is hold control and click on the class you are extending, or any class for that matter, and it will open and you can see many of the methods they use and override them in your own class.
September 25, 20159 yr Author I still can't figure out this item spawning thing. I have added maxStackSize(64). however it still wont stack, maybe it's because I am creating a new ItemStack() and a new Item(). however I can get it to work without recalling the constructors, any help on what I am doing wrong? my code is on my previous post, thanks.
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.