K-4U / Hydraulicraft

Entry for Modjam #3
Other
16 stars 9 forks source link

Crash with null item in smelting recipe #180

Closed whyo2 closed 8 years ago

whyo2 commented 8 years ago

Crash on start up. Latest version of all requirements (inc. multipart and k4lib) and forge. Tried with older forge still crashed. https://pastee.org/j3q5u

K-4U commented 8 years ago

Do you have copper and lead disabled?

whyo2 commented 8 years ago

no

whyo2 commented 8 years ago

will this be fixed in the next update?

K-4U commented 8 years ago

I cannot make any promises. Atm you're the only one who has this bug, so i'm assuming that it's another mod that's doing something to these recipes, as i'm doing nothing weird.

whyo2 commented 8 years ago

ok ill try and see which one

K-4U commented 8 years ago

It's still weird. Want to do a bit more research before closing it.

whyo2 commented 8 years ago

Found out conflicting mod is base metals by DrCyano. Should i send him crash as well?

K-4U commented 8 years ago

Yes, tell him about the crash too. If he has more questions tell him to contact me, or link to this issue.

CallMeFoxie commented 8 years ago

My bets are on that there is a recipe with a NULL output, but can only guess :)

LlubNek commented 8 years ago

Here's another crash report for this bug: http://pastebin.com/zBznvtms

And a log: http://pastebin.com/gDUM0ZJG

I'm using BaseMetals-1.6.1.jar and k4lib-1.8.9-1.0.8-universal.jar

DrPlantabyte commented 8 years ago

DrCyano here.

It looks to like somehow, Minecraft thinks there is either a null entry or a non-block item entry for "oreLead" or "oreCopper" in the OreDictionary, which I find rather puzzling. I added the following test code before and after each initialization stage in Base Metals (I register my blocks in the pre-init() stage) and found no null nor incompatible OreDictionary entries:

        FMLLog.info("Ore Dictionary Dump:");// TODO: remove this code block
        String[] oreNames = new String[OreDictionary.getOreNames().length];
        System.arraycopy(OreDictionary.getOreNames(), 0, oreNames, 0, oreNames.length);
        Arrays.sort(oreNames);
        for(String name : oreNames){
            FMLLog.info("%s: %s",name,OreDictionary.getOres(name));
            FMLLog.info("\t\t OreDictionary.getOres(\"%s\") == %s",name,OreDictionary.getOres(name));
            FMLLog.info("\t\t OreDictionary.getOres(\"%s\").get(0) == %s",name,OreDictionary.getOres(name).get(0));
            try{
                String dummy = (new ItemStack(Block.getBlockFromItem(OreDictionary.getOres(name).get(0).getItem()))).toString();
                FMLLog.info("\t\t new ItemStack(Block.getBlockFromItem(OreDictionary.getOres(\"%s\").get(0).getItem())) == %s",name,new ItemStack(Block.getBlockFromItem(OreDictionary.getOres(name).get(0).getItem())));
            }catch(Exception ex){
                FMLLog.info("\t\t new ItemStack(Block.getBlockFromItem(OreDictionary.getOres(\"%s\").get(0).getItem())) == %s",name,ex.getMessage());
            }
        }

I even tried doing the same operation as you do and did not get a crash:

GameRegistry.addSmelting(new ItemStack(Block.getBlockFromItem(OreDictionary.getOres("oreLead").get(0).getItem())),new ItemStack(OreDictionary.getOres("ingotLead").get(0).getItem()),0);

Although the above does spit out a message saying that Minecraft is ignoring the addSmelting(...) method call because Base Metals already has that recipe. It isn't clear to my why Hydraulicraft would expect other mods to add both an ore block and an ingot item without a corresponding smelting recipe, though that shouldn't cause any errors.

So the problem is not caused by Base Metals adding anything inappropriate to the OreDictionary, but something about Base Metals is causing the OreDictionaryHelper class in the K4lib to replace the Hydraulicraft ores with null references.

I'll keep digging and see if I can find the underlying cause, but at this point, I have no idea which mod is the source of the problem.

CallMeFoxie commented 8 years ago

I've found this bug today with yet another mod -- Foundry.

There was a smelting recipe (in => out @ in creative tab) !! NULL => 1xitem.ingot@0 @ exter.foundry.creativetab.FoundryTabMaterials@14a8b97 which was causing our crash.

CallMeFoxie commented 8 years ago

Adding just ingot or just ore should not break this though. It makes no sense :)

DrPlantabyte commented 8 years ago

I'm trying to find the source code for OreDictionary.doesOreNameExist(String) but it does not exist in my version of Forge (version 1.8.9-11.15.0.1705). K-4U, which version of Forge are you using?

K-4U commented 8 years ago

It's not forge version, but mappings version that you need to be concerned about. Atm all of my mods use "snapshot_20160117" for the mappings.

DrPlantabyte commented 8 years ago

I see, I'm still on "stable_20" (I started updating my projects before the Jan. 17). I'll update that and see if anything changes.

Update: Using black magic (aka reflection), I can confirm that the ore block instances for oreCopper and oreLead in the HC Ores class are being set to null, yet the corresponding ingot items from Base Metals are properly detected.

DrPlantabyte commented 8 years ago

I think I found the bug. The big clue was this output from my static field dump

k4unl.minecraft.Hydraulicraft.ores.Ores
    oreCopper = Block{null}
    oreLead = Block{null}
    oreLonezium = Block{hydcraft:oreLonezium}
    oreNadsiumBicarbinate = Block{hydcraft:oreNadsiumBicarbinate}
    oreBeachium = Block{hydcraft:oreBeachium}
    oreFoxium = Block{hydcraft:oreFoxium}
    oreCopperReplacement = Block{basemetals:copper_ore}
    oreLeadReplacement = Block{basemetals:lead_ore}

Which caused me to take a second look at the k4unl.minecraft.Hydraulicraft.ores.Ores class (I added comments to highlight what I noticed)

public static void init(){
  oreCopper = new OreCopper(); // <-- this variable is used to make a smelting recipe
  oreLead = new OreLead(); // <-- this variable is used to make a smelting recipe
  oreLonezium = new OreLonezium();
  oreNadsiumBicarbinate = new OreNadsiumBicarbinate();
  oreBeachium = new OreBeachium();
  oreFoxium = new OreFoxium();

  registerOres();
}

public static void registerOres(){
  oreCopperReplacement = OreDictionaryHelper.registerBlock(oreCopper, Names.oreCopper.unlocalized);
  oreLeadReplacement = OreDictionaryHelper.registerBlock(oreLead, Names.oreLead.unlocalized);
  oreLonezium = OreDictionaryHelper.registerBlock(oreLonezium, Names.oreLonezium.unlocalized);
  oreNadsiumBicarbinate = OreDictionaryHelper.registerBlock(oreNadsiumBicarbinate, Names.oreNadsiumBicarbinate.unlocalized);
  oreBeachium = OreDictionaryHelper.registerBlock(oreBeachium, Names.oreBeachium.unlocalized);
  oreFoxium = OreDictionaryHelper.registerBlock(oreFoxium, Names.oreFoxium.unlocalized);
  // Where is oreCopper and oreLead?
}

In class k4unl.minecraft.Hydraulicraft.ores.Ores, you register oreCopperReplacement and oreLeadReplacement and they successfully find the Base Metals versions of these ores, but you never register oreCopper or oreLead. In class k4unl.minecraft.Hydraulicraft.lib.recipes.HydraulicRecipes, you create the smelting recipes with the following code

private static void initializeSmeltingRecipes() {
  GameRegistry.addSmelting(Ores.oreCopper, new ItemStack(HCItems.ingotCopper), 0);
  GameRegistry.addSmelting(Ores.oreLead, new ItemStack(HCItems.ingotLead), 0);
}

Note that you are using the unregistered Ores.oreCopper and Ores.oreLead variables instead of the Ores.oreCopperReplacement and Ores.oreLeadReplacement variables that have the Base Metals ore blocks.

To positively prove that this is the root problem, I added the following code to Base Metals:

Class oresClass = getClass().getClassLoader().loadClass("k4unl.minecraft.Hydraulicraft.ores.Ores");
oresClass.getField("oreCopper").set(null, oresClass.getField("oreCopperReplacement").get(null));
oresClass.getField("oreLead").set(null, oresClass.getField("oreLeadReplacement").get(null));

and it fixed the crash! Minecraft launched successfully to the menu screen.

I therefore recommend getting rid of the replacement variables and registering the regular ore variables.

CallMeFoxie commented 8 years ago

Wow, thanks! I never noticed those *Replacement variables! I'll let K4 fix it as he knows that part of the code.

AngelCry commented 8 years ago

come here to confirm - BaseMetals with HydrauliCraft (K4Lib) now do not crash (at least in versions: BaseMetals-1.7.0, HydCraft-1.8.9-3.1.64-universal, k4lib-1.8.9-1.0.16-universal, Forge 1724), but now HC lead and copper ingots removed from world (in my case HC been already installed and BaseMetals added later). not a big deal, because there still ingots from BaseMetals, but i think oredicted things used to coexist together.