cad97
Forge Modder-
Posts
61 -
Joined
-
Last visited
Everything posted by cad97
-
If my debug-crawling through the startup code is accurate, the current order is something like (trimmed to relevant items): The effect of this is that during the IRecipe registration event, vanilla JSON recipes are in the registry but forge-loaded ones are not. It would be more consistent to load all JSON recipes before firing the programmatic registration event. What's the reason I want this? During the recipe registration event, it is possible to remove vanilla JSON recipes: @SubscribeEvent public static void registerRecipes(RegistryEvent.Register<IRecipe> event) { ((IForgeRegistryModifiable<IRecipe>)event.getRegistry()).remove(new ResourceLocation("minecraft:anvil")); } With this listener registered, the minecraft:anvil recipe disappears without a trace. Unfortunately, because mod JSON recipes' loading is far off at this point, it is not possible to remove those, because they don't exist yet. Note that doing this during FMLInitializationEvent (via ForgeRegistries.RECIPES of course) removes the recipe but leads to a game crash when trying to render the recipe book. A feature to properly remove JSON loaded recipes programmatically (based on config settings) would render this unnecessary.
-
ob·fus·ca·tion ˌäbfəˈskāSH(ə)n/ noun noun: obfuscation; plural noun: obfuscations the action of making something obscure, unclear, or unintelligible. "when confronted with sharp questions they resort to obfuscation" The Minecraft source is obfuscated. That's where the unreadable parameter names come from (effectively). MCP is the community's mapping of these machine-generated names back into human-readable forms. You can try updating your mappings, and if that doesn't give names to the code (potentially breaking references -- be careful), you could consider contributing mappings yourself. But for the most part, trivial methods and newer methods have fewer/worse names because people haven't bothered to give them names again, because their effort was better spent on one of many other useful tasks.
-
bug ItemStackHolder crashes on private field (ObjectHolder doesn't)
cad97 replied to cad97's topic in Modder Support
Whoops. I could have sworn I gave a once-over for a proper board. Can this be moved or should I re-post? (@Draco18s) EDIT: reposted -
TL;DR reproduction case: import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.registry.GameRegistry; import org.apache.logging.log4j.Logger; @Mod(modid = "itemstackholder") public class ISHMod { private Logger logger; @GameRegistry.ObjectHolder("minecraft:iron_bars") private static Item itemIronBars; @GameRegistry.ItemStackHolder("minecraft:iron_bars") private static ItemStack stackIronBars; public Logger getLogger() { return logger; } @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { logger = event.getModLog(); } @Mod.EventHandler public void postInit(FMLPostInitializationEvent event) { logger.info(itemIronBars.toString()); logger.info(stackIronBars.toString()); } } This crashes with: [20:24:57] [main/INFO] [FML]: Processing ObjectHolder annotations [20:24:57] [main/INFO] [FML]: Found 1169 ObjectHolder annotations [20:24:57] [main/INFO] [FML]: Identifying ItemStackHolder annotations [20:24:57] [main/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:629]: ---- Minecraft Crash Report ---- // Everything's going to plan. No, really, that was supposed to happen. Time: 7/6/17 8:24 PM Description: Initializing game java.lang.RuntimeException: java.lang.NoSuchFieldException: stackIronBars at com.google.common.base.Throwables.propagate(Throwables.java:240) at net.minecraftforge.fml.common.registry.ItemStackHolderInjector.addHolder(ItemStackHolderInjector.java:97) at net.minecraftforge.fml.common.registry.ItemStackHolderInjector.findHolders(ItemStackHolderInjector.java:63) at net.minecraftforge.fml.common.Loader.preinitializeMods(Loader.java:602) at net.minecraftforge.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:266) at net.minecraft.client.Minecraft.init(Minecraft.java:508) at net.minecraft.client.Minecraft.run(Minecraft.java:416) at net.minecraft.client.main.Main.main(Main.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) at net.minecraft.launchwrapper.Launch.main(Launch.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) at GradleStart.main(GradleStart.java:26) Caused by: java.lang.NoSuchFieldException: stackIronBars at java.lang.Class.getField(Class.java:1703) at net.minecraftforge.fml.common.registry.ItemStackHolderInjector.addHolder(ItemStackHolderInjector.java:91) ... 18 more A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Thread: Client thread Stacktrace: at com.google.common.base.Throwables.propagate(Throwables.java:240) at net.minecraftforge.fml.common.registry.ItemStackHolderInjector.addHolder(ItemStackHolderInjector.java:97) at net.minecraftforge.fml.common.registry.ItemStackHolderInjector.findHolders(ItemStackHolderInjector.java:63) at net.minecraftforge.fml.common.Loader.preinitializeMods(Loader.java:602) at net.minecraftforge.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:266) at net.minecraft.client.Minecraft.init(Minecraft.java:508) -- Initialization -- Details: Stacktrace: at net.minecraft.client.Minecraft.run(Minecraft.java:416) at net.minecraft.client.main.Main.main(Main.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) at net.minecraft.launchwrapper.Launch.main(Launch.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) at GradleStart.main(GradleStart.java:26) -- System Details -- Details: Minecraft Version: 1.12 Operating System: Windows 10 (amd64) version 10.0 Java Version: 1.8.0_121, Oracle Corporation Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation Memory: 653341240 bytes (623 MB) / 789053440 bytes (752 MB) up to 3801088000 bytes (3625 MB) JVM Flags: 0 total; IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0 FML: MCP 9.40 Powered by Forge 14.21.1.2387 5 mods loaded, 5 mods active States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored UC minecraft{1.12} [Minecraft] (minecraft.jar) UC mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) UC FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.12-14.21.1.2387.jar) UC forge{14.21.1.2387} [Minecraft Forge] (forgeSrc-1.12-14.21.1.2387.jar) UC itemstackholder{1.0} [itemstackholder] (itemstackholder_main) Loaded coremods (and transformers): GL info: ' Vendor: 'NVIDIA Corporation' Version: '4.5.0 NVIDIA 382.05' Renderer: 'GeForce GTX 860M/PCIe/SSE2' Launched Version: 1.12 LWJGL: 2.9.4 OpenGL: GeForce GTX 860M/PCIe/SSE2 GL version 4.5.0 NVIDIA 382.05, NVIDIA Corporation GL Caps: Using GL 1.3 multitexturing. Using GL 1.3 texture combiners. Using framebuffer objects because OpenGL 3.0 is supported and separate blending is supported. Shaders are available because OpenGL 2.1 is supported. VBOs are available because OpenGL 1.5 is supported. Using VBOs: Yes Is Modded: Definitely; Client brand changed to 'fml,forge' Type: Client (map_client.txt) Resource Packs: Current Language: English (US) Profiler Position: N/A (disabled) CPU: 8x Intel(R) Core(TM) i7-4810MQ CPU @ 2.80GHz [20:24:57] [main/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:629]: #@!@# Game crashed! Crash report saved to: #@!@# D:\...\itemstackholder\run\.\crash-reports\crash-2017-07-06_20.24.57-client.txt The crash comes from a catch/throw in Minecraft Forge with a comment // unpossible?, so should be worth looking into. The behaviors are different, so one is (probably) more wrong. The difference looks to be this: ItemStackHolderInjector uses Field f = clazz.getField(annotationTarget); and ObjectHolderRegistry uses Field f = clazz.getDeclaredField(annotationTarget);. Switching ItemStackHolderInjector to use Class::getDeclaredField like ObjectHolderRegistry would, at the very least, save future modders the confusion I felt when java told me that the field that is right there doesn't exist. This would also enable the use case where I discovered this: private fields populated with ItemStacks for use in recipe registration. Because I've caught Kotlin fever, the linked code there is in Kotlin, but compiles to the equivalent private static member (with a private set method and a public get method, as of the linked commit; I plan to make it fully private, this was just the work commit where I caught this issue). I can make this an issue and/or PR against the MinecraftForge GitHub, but I didn't want to needlessly clutter the repository if this is considered a non-issue. Consider my vote to apply this one-line patch, though. I haven't tested this, because I don't currently have the setup required to build a custom version of forge and test it.
-
The new rendering system uses JSON resources to specify item model rendering. You can see a basic working example here: http://modwiki.temporal-reality.com/mw/index.php/Render_Item_Basic-1.9 The correct registration call is ModelLoader.setCustomModelResourceLocation(this, 0, new ModelResourceLocation("itemID", "inventory")); And a JSON file located at main/resources/assets/<yourmod>/models/item/itemID.json { "parent": "builtin/generated", "textures": { "layer0": "modID:items/itemtexture" }, "display": { "thirdperson": { "rotation": [ -90, 0, 0 ], "translation": [ 0, 1, -3 ], "scale": [ 0.55, 0.55, 0.55 ] }, "firstperson": { "rotation": [ 0, -135, 25 ], "translation": [ 0, 4, 2 ], "scale": [ 1.7, 1.7, 1.7 ] } } }
-
I noticed that net.minecraft.Block::isOpaqueCube(IBlockState) is @Deprecated. What is the preferred method of achieving a non-opaque block, in this case? Was the method deprecated incorrectly or is there a better way to achieve the same effect as overriding the method to return false? (I am looking at forgeSrc-1.10-12.18.0.1996-1.10.0-sources.jar)
-
Thanks, that's exactly what I needed. (And duh, I've done that before. Why didn't I think of that.)
-
Between two versions of my mod I've changed how data on an item is stored. I can easy convert to the new version, but where is the best place to call that update routine? I want a way to call updateToNewVersion(ItemStack) (for example) on all ItemStacks of one custom Item only one time if they need updating. (They need updating if they have non-zero metadata and no NBT tags.)
-
That's the answer I hoped not to hear, but it wasn't as hard to implement as I feared. Commit of solution here. I can't shake the feeling that I could have done NBTSensitiveShapedRecipe better though. All but 6 lines (effectively less) of the actual work methods are direct rips from the superclass ShapedRecipes, and copy/pasting code is a bad practice -- I mean OOP is about reusing code. The thing is the only way I saw to override checkMatch() (which is what I needed to add those 6 lines to) was to point matches() at a new version, as it is a private member of the superclass and as such cannot be overwritten directly. This is probably the easiest way to do it, but I still feel it could be done better with less repeated code. Even if what I wanted to do originally (@Override checkMatch()) wouldn't even have saved most of the copied lines. It's just those 6 lines of check need to be in that part of the process.
-
I'm trying to move my mod SpawnerCraft over to the new EntityRegistry system: i.e. looking at Strings and checking those against Forge's database instead of using the ID system used by Spawn Eggs as of old. This means that I've moved from using metadata to specify the mob in an item to an NBT tag. I need help creating a NBT sensitive recipe. I have my current recipe registration here but apparently the NBT tag on the ingredient is not considered in this way. It always gives out for creepers (the first on the EntityEgg list). How can I register a recipe that requires the same NBT data and spits out an item with the same NBT data? (To be clear, in abstract I want: four of my items in a square with identical NBT structure. It spits out one of next tier with the same NBT structure.)
-
Aaaand I'm a derp. configuration.get() takes the category then the field while configuration.getBoolean() takes the field and then the category. I switched them up and got weird results. It works though now!
-
You need to use this method: /** * Gets the block's texture. Args: side, meta */ @SideOnly(Side.CLIENT) public IIcon getIcon(int p_149691_1_, int p_149691_2_) In BlockSapling the body is this: { p_149691_2_ &= 7; return field_149881_b[MathHelper.clamp_int(p_149691_2_, 0, 5)]; } So looking at your code the body should look something like this: { p_149691_2_ &= 7; // Though I don't know exactly what this is for, I would keep it as long as it won't cause a problem. // This is a binary and on binary 0111 if you're curious, should have the same effect as %= 7 if I'm not mistaken. return saplingicon[MathHelper.clamp_int(p_149691_2_, 0, 1)]; // 0, 1 in clamp_int is to make sure you don't overIndex your saplingicon[] //which currently has two icons in it (at indexes 0 and 1). } And as always, feel free to rename parameter names in overridden code, you don't need to keep the parameter names just the types.
-
Thanks, diesieben, for clarifying, and jabelar and WorldsEnder for posting their .gitignores. I've got what I need now, thanks!
-
It took me a while to find, but I got it. I'd looked before for the solution you suggested, jabelar, by going through the event.harvester options, but not found it. Looking at the stacktrace for event.isSilkTouching, though, I was able to find the call required: EnchantmentHelper.getSilkTouchModifier(event.harvester) . Looking more at isSilkTouching it does only seem to be true for silktouch-able blocks.
-
I'm new to the forge configuration, so I'm kind of lost . From what you said and what I can read this looks like it *should* be working: public class ConfigurationHandler { public static Configuration configuration; public static boolean spawnerCraftable; public static boolean spawnerDropRequireSilk; public static void init(File configFile) { // Create configuration object from given file if (configuration == null) { configuration = new Configuration(configFile); loadConfiguration(); } } @SubscribeEvent public void onConfigurationChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event) { if (event.modID.equalsIgnoreCase(Reference.MOD_ID)) { loadConfiguration(); } } private static void loadConfiguration() { configuration.get("spawnerCraftable", Configuration.CATEGORY_GENERAL, false, "Whether you can craft an Empty spawner from iron bars").setRequiresMcRestart(true); spawnerCraftable = configuration.getBoolean("spawnerCraftable", Configuration.CATEGORY_GENERAL, false, "Whether you can craft an Empty spawner from iron bars"); spawnerDropRequireSilk = configuration.getBoolean("spawnerDropRequireSilk", Configuration.CATEGORY_GENERAL, false, "Whether Empty Spawner drop requires Silk Touch"); if (configuration.hasChanged()) { configuration.save(); } } } but the "Requires Minecraft Restart" flag isn't showing up for spawnerCraftable. The only thing that I can see that may be the cause is that the constructor for the GuiConfig overrides with the allRequireMinecraftRestart flag. (Full repo code is at https://github.com/CAD97/SpawnerCraft)
-
Is there an (easy) way to set one of your config settings as requiring a Minecraft restart? I see the way to set all to require a restart, but I don't see the place to set only one to that. (I've set up the GUI thanks to the wonderful tutorial at http://minalien.com/minecraft-forge-feature-spotlight-config-guis/ and that part works fine.)
-
I've recently switched over to the "proper" setup for Forge using gradle. What files should I commit to the mod repository and which should I .gitignore? (Basically, which files are critical to the mod download from repo and which can I rely on gradle to rebuild for the downloadee?) (I should mention I'm in the `gradlew idea` workspace) My current .gitignore: .gradle/ build/ gradle/ build.gradle gradlew.bat *.iml *.ipr *.iws run/ The folder hierarchy I'm working with: .git | <git stuff> .gradle | <gradle stuff> build | <build stuff> run | <run environment> src | <class files> .gitignore build.gradle gradlew.bat README.md <project>.iml <project>.ipr <project>.iws [code]
-
I've recently added a config to my mod to make an item drop only when silk touched. The config works. The silk touch doesn't. Whether I am using a Silk Touch pick or a normal one the HarvestDropsEvent.isSilkTouching is always false. From looking at calls to post a new HarvestDropsEvent, it looks like the game is only passing true to the isSilkTouching if the block could normally be silk touched. I need to be able to tell if a BlockMobSpawner is silk touched or not. My current SubscribeEvent looks like this: @SubscribeEvent public void onBlockDrops(HarvestDropsEvent event) { if (event.block instanceof BlockMobSpawner) { System.out.println("BlockMobSpawner broken"); if (ConfigurationHandler.spawnerDropRequireSilk) { System.out.println("spawnerDropRequireSilk"); if (event.isSilkTouching) { System.out.println("isSilkTouching"); event.drops.add(new ItemStack(SCBlocks.mobCage, 1)); } else { System.out.println("isntSilkTouching"); } } else { System.out.println("spawnerDropDoesntRequireSilk"); event.drops.add(new ItemStack(SCBlocks.mobCage, 1)); } } } My full mod can be found here: https://github.com/CAD97/SpawnerCraft I am using forge 1.7.10-10.13.0.1188
-
As of current, set up by the tutorial I followed, Forge (dev) is instructed to ignore minecraft validity and give me a random playername (e.g. Player145). Is there a / what is the way to tell Forge (dev) to log me in as my username?
-
A while ago Attributes were added in vanilla Minecraft and attribute modifiers allowed people to do cool things like give you boots that increased your speed or a chestplate that ignored knockback or a hat that gave you extra hearts. Sadly, this feature lounges mostly forgotten by all but the most elite mapmakers. (Wiki page - http://minecraft.gamepedia.com/Attribute) How should I go about adding attribute modifiers to a custom item? For this example let's just say I want an item that does nothing but have the attribute modifier for 200% speed while held.
-
Assuming you are set up the proper way (unlike me I apparently like making it hard on myself) your block png should be at this location: ~devforgeenvironment~\src\main\resources\assets\%modid%\textures\blocks\yourblock.png In Eclipse, (assuming you are using Eclipse,) you should see: ~projectfolder~ | src/main/java | | (all your mod .java packages) | | src/main/resources | | assets.modid.textures.blocks | | | (any block textures) | | | | assets.modid.textures.items | | | (any item textures) | | | | assets.modid.lang | | | (your lang file(s)) | | | | mcmod.info | | JRE System Library | | (whole bunch of things) | | Referenced Libraries | | (whole bunch of things) | | (whole bunch of other Forge things) I hope that's readable and can help =========================== I've been using setBlockTextureName() forever. (I've only used Forge 1.7.4.) I've never seen setBlockTextureNam() though, but I don't see that in his code either. I asssume yours was just a careless typo then
-
^^^^^^^^^^^^^^^^^^ ninja'd whilst I looked for it Just do a if (event.entity instanceof PlayerEntity) { //yourcode } inside your method that handles the livingDeathEvent event. (The PlayerEntity I have not found - it is more likely EntityPlayer and it could be something else - learn to use your IDE and look)
-
Thanks diesieben! I think the thing here is that with reflection you give it a string to find the field. If it were a variable the 'gradlew build' would catch it and obfuscate it to field_*****_X, but it doesn't change the String. (Just a guess, is not necessarily true.) This would be why you can reference the ex. EntityCreeper.class by name - even if it is referred to as wl.class in the standard environment, when you run 'gradlew build' the script catches the fact that you want EntityCreeper.class and changes the call to be the correct name. NOW, apart from my speculation on the inner workings on Forge, About how often should I expect to have to go find the fields.scv file to update the reflection? Should I expect it to keep working for most 1.7.4 forge builds or will I most likely have to update it every forge revision? {For those who really want to see the change that I made, go to the FMLListener class on the github project.} [spoiler=other] The funny thing is that I still got an error, but this one is non-fatal and is totally Minecraft's fault, not mine. [10:15:16 INFO]: Client> Exception in thread "Thread-9" java.lang.NullPointerException [10:15:16 INFO]: Client> at paulscode.sound.codecs.CodecJOrbis.readBytes(CodecJOrbis.java:643) [10:15:16 INFO]: Client> at paulscode.sound.codecs.CodecJOrbis.read(CodecJOrbis.java:354) [10:15:16 INFO]: Client> at paulscode.sound.Source.stream(Source.java:953) [10:15:16 INFO]: Client> at paulscode.sound.StreamThread.run(StreamThread.java:129) I'll be hosting the actual mod .jar on minecraft.curseforge later - right now I've got to go and do normal things.
-
So I'd be referring to the class by its private static final String __OBFID = "CL_00000764"; ? /goes to try after closing the dozen open Chrome tabs on this forum EDIT: well it's not that simple at least as i can't refer to a class CL_00000764 (it's a compile error) and don't know what to do here.