cad97
Forge Modder-
Posts
61 -
Joined
-
Last visited
Everything posted by cad97
-
This is less an answer than a suggestion but - given as you are making rail, check out the vanilla handling for minecart rail. If you set the curve rules to be the same as "regular" rail then players will have an idea of how it works. You may even wish to extend the minecart rail class and just overwrite the texture assignment!
-
Make sure the package with textures is in the /assets/ folder and not the /src/ folder of forge. Other than that we will need to SEE your environment to help you.
-
Can you give us the file hierarchy and the registration class one more time? Just to make sure we know what we are dealing with.
-
I think I see your problem int amount = 10; This snippit is in the base class without any modifiers. The default one will apply but in practice it is always better to put one - and it looks out of place like that. This may not fix the problem, but change the line to private int amount = 10; After this, I would recommend putting a println inside the for loop where you spawn the particles to make sure it is running. Seeing as it's the same as in EntitySnowball it *should* be working, but it obviously isn't. Also just for bug-fixing, consider changing the particle line to directly copied from the EntitySnowball class. Once you get it working with that particle you can change it. Your problem may just be that you are asking for a particle that you can't see!
-
this. It also explains why you get a "ghost" version - your client thinks it is there but it's not, so when you try to interact the server says "nuh-uh" and kills the block that isn't there. One interesting way to check is to actually build the mod and put it in a player environment (i.e. your normal Forge install, not the Eclipse environment) and all (or at least most) of the messages will then be prefixed with <Client> or <Server> as appropriate.
-
http://www.wuppy29.com/minecraft/modding-tutorials/wuppys-minecraft-forge-modding-tutorials-for-1-7-crafting-recipes/#sthash.mOqdfWX1.dpbs Read the whole thing and learn something. The dyes are talked about in the third example I think. Basically rather than telling the craft registry to register an item as required you have to tell it the ItemStack you want with included damage value.
-
I have the strangest error with my mod. When running the mod in the dev environment (Eclipse) the mod works fine. Once I have run 'gradlew build' and taken the .jar into my Forge install's mods folder, the mod stops working. When booting up minecraft I get the error [22:10:37 INFO]: Client> java.lang.NoSuchFieldException: tileSign [22:10:37 INFO]: Client> at java.lang.Class.getDeclaredField(Unknown Source) [22:10:37 INFO]: Client> at cad97.commandblocksigns.CommandBlockSignsMFListener.<clinit>(CommandBlockSignsMFListener.java:22) [22:10:37 INFO]: Client> at cad97.commandblocksigns.CommandBlockSigns.preinit(CommandBlockSigns.java:29) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at java.lang.reflect.Method.invoke(Unknown Source) [22:10:37 INFO]: Client> at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:513) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at java.lang.reflect.Method.invoke(Unknown Source) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74) [22:10:37 INFO]: Client> at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:47) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventBus.dispatch(EventBus.java:314) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventBus.post(EventBus.java:267) [22:10:37 INFO]: Client> at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:208) [22:10:37 INFO]: Client> at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:187) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at java.lang.reflect.Method.invoke(Unknown Source) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74) [22:10:37 INFO]: Client> at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:47) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventBus.dispatch(EventBus.java:314) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296) [22:10:37 INFO]: Client> at com.google.common.eventbus.EventBus.post(EventBus.java:267) [22:10:37 INFO]: Client> at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:118) [22:10:37 INFO]: Client> at cpw.mods.fml.common.Loader.preinitializeMods(Loader.java:512) [22:10:37 INFO]: Client> at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:239) [22:10:37 INFO]: Client> at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:467) [22:10:37 INFO]: Client> at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:815) [22:10:37 INFO]: Client> at net.minecraft.client.main.Main.main(SourceFile:103) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [22:10:37 INFO]: Client> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [22:10:37 INFO]: Client> at java.lang.reflect.Method.invoke(Unknown Source) [22:10:37 INFO]: Client> at net.minecraft.launchwrapper.Launch.launch(Launch.java:134) [22:10:37 INFO]: Client> at net.minecraft.launchwrapper.Launch.main(Launch.java:28) from the static constructor in my FMLListener class. I and some other modders on the forums had decided earlier (http://www.minecraftforge.net/forum/index.php/topic,20082) that reflection was probably the best way to go about grabbing the TileEntitySign from the GUISignEdit. However, this seems to be causing a problem now. I'm stumped as for the difference between the dev environment and the standard environment - it must be something with the deobfuscated environment of dev versus the standard environment. If you want a closer look at my code, here is the GitHub repo: https://github.com/CAD97/CommandBlockSigns/tree/master
-
OK so going back into it - make sure that when you are getting the items it is the item from the item class if you are using it and not the auto-item-from-block. The item then needs the /** * Returns the metadata of the block which this Item (ItemBlock) can place */ public int getMetadata(int par1) { return 0; } method overridden.
-
In the BlockWood.class I found this: /** * Determines the damage on the item the block drops. Used in cloth and wood. */ public int damageDropped(int p_149692_1_) { return p_149692_1_; } You'll need to use this so the block drops the correct item. I remember seeing something similar for block placement but I can't find it right now - if you look some you should be able to find it. What's happening is that the game doesn't realize when you place the item that it needs to convert damage -> metadata. The above should take care of block -> item, but as stated I can't find the call for item -> block.
-
Your file is not there. Java is looking for the file and failing to find it. Where is your file currently?
-
Honestly guys we should let it rest. It's (somewhat) like Mac vs. PC vs. Linux, there's no real answer, just the best for each person. As long as it works for you, it's fine. If it doesn't work, set it up by the "official" way before you complain to the people who want you to set it up that way
-
What is the proper way of setting up a git repo and mirroring it to Github/Bitbucket? I've done git before, but only through NetBeans' automation of the process.
-
Yep! Works like a charm! Thank you! FILE_PATH = new File(DimensionManager.getCurrentSaveRootDirectory().toPath() + "/data/commandblocksigns.json"); Just have to make sure this is called when the world is open. (obviously.)
-
The method you will want is getIconFromDamage(int damage). Depending on the damage passed, return a different IIcon to be rendered.
-
The mod I'm working on currently needs a data file to be saved. I am using .json and have no problems with that. My problem is saving it properly. To save the file I need to get a Java File object pointing at <minecraftdir>\saves\<worldname>\data\myFile.dat. I can have generated a file pointing to the saves folder of the current minecraft directory, and this code works. public static final File SAVES_DIRECTORY = new File(Minecraft.getMinecraft().mcDataDir, "/saves"); However, when attempting to get to the data folder, I've run into a hitch. With world w, I can make the call w.getWorldInfo().getWorldName() to (theoretically) get the name of the world, and can use this to access the correct directory. But instead of returning the name of my world save, the above snippet is returning "MpServer". TLDR; So my question is, what is the best way to access the data folder inside of the save folder for a world?
-
[Solved] Multiplying Drops based on Fortune Level
cad97 replied to XDdrummer's topic in Modder Support
getItemDropped(...) is the call to decide what item a block drops. use quantityDropped(Random random) for non fortune drops. The method you are interested in is quantityDropped(int meta, int fortune, Random random) { return quantityDroppedWithBonus(fortune, random); } You will want to override public int quantityDroppedWithBonus(int p_149679_1_, Random p_149679_2_) to return something with the fortune value rather than the default return this.quantityDropped(p_149679_2_); My, this needs to be mapped doesn't it maybe I could go name some variables -
If you're interested, here is my final code. package cad97.commandblocksigns; import java.lang.reflect.Field; import net.minecraft.client.gui.inventory.GuiEditSign; import net.minecraft.tileentity.TileEntitySign; import net.minecraftforge.client.event.GuiScreenEvent.ActionPerformedEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; public class CommandBlockSignsListener { static { try { f = GuiEditSign.class.getDeclaredField("tileSign"); } catch (NoSuchFieldException | SecurityException e) { e.printStackTrace(); } } private static Field f; @SubscribeEvent public void onSignDone(ActionPerformedEvent.Pre event) { if (event.gui instanceof GuiEditSign) { if (f != null) { try { f.setAccessible(true); GuiEditSign ges = (GuiEditSign) event.gui; TileEntitySign tileSign; tileSign = (TileEntitySign) f.get(ges); if (WaypointSign.isValidWaypointSign(tileSign)) { WaypointSign.register(tileSign.getWorldObj(), new WaypointSign(tileSign.signText)); } } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } } } } } I unfortunately can't do f.setAccessible(true); in the static constructor; Eclipse tells me "Cannot reference a field before it is defined." Oh well, re-setting one boolean every time is no real cost
-
@Kwibble It doesn't have the @Cancelable annotation so I don't think so. Well going back to the matter at hand, [[What do you say, are you back in the band? (sorry)]] It might be better to use func_150996_a in the mysteryItem rather than minus-ing the stack and adding an item to the player's inventory. I (really) need to test it, but doing something like onCreated(/*whatever the params are) { parItemStack.func_150996_a(/*whatever item you want*/); } may be the best way to go about this. Just make sure to set the maxStackSize to 1.
-
So I'm testing it... this produces some interesting results. [spoiler=Subscribing to onCrafted:] @SubscribeEvent public void on(ItemCraftedEvent event) { event.crafting.stackSize = 0; event.player.inventory.addItemStackToInventory(new ItemStack(Blocks.stone)); } This leaves you with a ghost item when crafting and gives you a block of stone in the inventory. Setting the stackSize to 1 and then subtracting one doesn't help either. event.crafting is final and as such I can't just change the ItemStack. For poops and giggles, I tried this: @SubscribeEvent public void on(ItemCraftedEvent event) { event.crafting.func_150996_a(Items.apple); } What does it do? (I mean it's an obfuscated function it can't do anything useful.) IT SETS THE ITEM OF THE STACK TO AN APPLE. This is what we want! .......unfortunately this fails (as does anything changing the itemstack) when shift clicking. So sad. So the final answer is .... don't use this method for altering the itemStack output. You could probably use it to do things with the craftingMatrix though. I still need to check how onCreated holds up though.... [[This is like a personal quest now]]
-
Well I fixed it! Can you spot the difference? @SubscribeEvent public void onSignDone(ActionPerformedEvent.Pre event) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException // yes I know this throws chain is undesirable I'll add a catch later { if (event.gui instanceof GuiEditSign) { GuiEditSign ges = (GuiEditSign) event.gui; if (f == null) { f = ges.getClass().getDeclaredField("tileSign"); f.setAccessible(true); } TileEntitySign tileSign = (TileEntitySign) f.get(ges); System.out.println(Arrays.asList(tileSign.signText)); } } [spoiler=differences] It's two lines. Looking back at my code after a break, I realized that before I was using .getDeclaredField("tileSign") but switched somewhere to .getField("tileSign"). Looking at the documentation both should work, but something about the way they work only grabs it properly with .getDeclaredField("tileSign"). After I changed this, I got a NullPointer on the line with .get(null). [[GAH THAT THUNDER SCARED ME]] [[OK, breathe. in. out. in. out. Ok I'm fine.]] Reading the javadoc for this made me realize just why you can instantiate the field without a specific object reference and use the same one - you pass the specific reference to .get(). So, now the code works. I'm actually going to move the Field instantiate to a static constructor to simplify the actual hook. It'll work, though, so no need for me to put it here A great big THANK YOU (as in the button AND an internet hug (assuming you aren't a hug-hater or anything) #hugamodder (this is not a thing to my knowledge)) to the people who helped me. I couldn't have figured this out on my own. I love doing this and I love learning - THANK YOU for helping me
-
That would be because you are trying to implicitly cast a Block to an ItemStack. These are not the same things. The code you want there (instead of Blocks.beacon) is this: new ItemStack(Blocks.beacon, /*size of stack*/ 1, /*data, if applicable*/ 0) Leave the data bit of the ItemStack constructor off if you don't need it. And Kwibble, I'm going to go take a look at the Item.onCreated() method. I was looking for a hook for about a quarter hour before posting my clickable solution, so I got tired of looking and may have missed something obvious EDIT: Looking at the method, it looks like you could just replace the onRightClick from my previous explanation with onCreated and it should work. so: /** * Called when item is crafted/smelted. Used only by maps so far. */ public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) { if (!par3EntityPlayer.capabilities.isCreativeMode) { --par1ItemStack.stackSize; } int rand = (int) (Math.random()*craftables.length); par3EntityPlayer.inventory.addItemStackToInventory(craftables[rand]); //or whatever randomizer you want return par1ItemStack; }
-
send data from GUI-Container to TileEntity and the other way around
cad97 replied to aligator123456's topic in Modder Support
You could always just call a method. I'm assuming your Container retains a reference to the TileEntity. So put a public method incrementSomethingAndGetNewIcon (or something) in the TileEntity's class and call it from the Container when you need to send the data. Send the data you wish to send in the method call and use the return to get the Icon. -
The point of the setup is that they aren't. Yes, this is not the intended way of setting up your workspace. No, it does not not work. (not not = does) For the gradlew build to work, the files have to be there, and to build a mod if I wish to release it I move them there. For writing, however, it works fine to have them in their own project AS LONG AS you actually set up the whole enviroment correctly, and messing one thing up could screw you over. I set this up following wuppy's tutorial and just modifying a couple folder hierarchies to make it fit my organization style better. Oh, and I should probably say this (I forgot it originally): I did set up a JAVA_HOME Environment Variable. I did not set up a PATH Environment Variable.
-
OK, I just wanted to comment here - I set up my workspace via wuppy's advanced setup and IT WORKS GREAT. I have not installed gradle (nor even know exactly what it is), and I don't have to edit the build.gradle but once per project. I understand that every setup has advantages and disadvantages, and that some people will fight tooth and nail for setups that make no sense to other people. It's like bracket placement rules or hard/soft tab arguments or even Mac vs. PC - both sides are valid and full of people that will never change. Use what you are used to and learn to use it properly. Let me try explain how this advanced setup is supposed to make things work. I have a single folder for all of my modding related stuff. In that folder are a folder for eclipse and related files (extracted zip), a folder for forge and related files (extracted zip) and a folder for my Eclpise workspace, in which I save my mods. Once creating these folders and unzipping force src and eclipse into their respective folders, I ran "gradlew setupDecompWorkspace" and "gradlew eclipse" in the ~\modding\forge\ directory. I then ran Eclipse and selected ~\modding\workspace as my Eclipse workspace. In Eclipse, when I want to make a new mod, such as my SpawnerCraft mod (made on this system), I make a new project in Eclipse called the mod name. I then make the build path for that project include Forge, and setup a new Run Configuration for Forge that includes the new project. TADA, the mod has its own folder and I only ever have to install all the Forge files (386 MB) once. This is not that big of a deal, honestly, and new people should do the simple option of a new forge enviroment for each mod - it is simpler. To publish (case study) Spawnercraft, I take the com.cad97.Spawnercraft package and copy it over to the src/main/java. I take the other files (excluding build.gradle if this isn't the first jar build) and put them in src/main/resources. I run my Run Config of just Forge (no other projects) to make sure the mod is working. If this is my first time building the mod, I will edit the build.gradle as appropriate. If not, I'll copy over the pre-existing one in the mod folder already and use it (checking that the forge version is the same, as I may have updated since the last build). I then "gradlew build" in ~\modding\forge and I have the .jar for the mod. Then I delete the new files out of the Forge project and carry on my way. If I feel it necessary to save myself the agonizing effort of editing three tags in build.gradle, I'll copy it over into the mod project to keep it for the future. Then, I can repeat as necessary. Advantages of this format: If I were to use git or mercurial or whatever to mirror my mod to github or bitbucket or whatever, I would not be uploading the Minecraft/Forge source. It is easy for me to see what files are directly pertaining to the mod in a nice small folder. I have the same enviroment that I've been used to from previous projects that every project is (gasp) its own project. When updating Forge I only have to do it once (taking several (>10 even) minutes on my old machine). Profit Disadvanteges: Some setup time to get the Run configs and the different folders. People not being able to comprehend this setup. Having to copy over files to export a project (which should only happen once per project if you're good). If people are grabbing my mod source, they will have to realize that it needs to be built and ran through Forge rather than being self-contained (but really these are mods not programs). Sorry for the rant, and just to clarify, everything here is opinion and as such could be very wrong to some people if they are of the opposite opinion. Screengrab of my setup in Eclipse: Did I really just spend thirty minutes explaining an opinion on the internet. In a location where it has been discouraged. What am I doing with my time? (Waiting for a response on another topic.)
-
onItemRightClick goes into the mysteryItem class. (This is the item that crafting gives you.) If you want to do a different randomizer, do something along the following: If you want to do something with percentages: