minecraft forge doesnt seem to call postInit

293 views Asked by At

I am writing an addon to the minecraft mod Thaumcraft, specifically one that adds aspects to blocks based on the contents of a file. This is for Minecraft 1.7.10

The code runs the preInit method, everything goes fine. However, the game crashes on the postInit method. I cannot figure out why it crashes

Here is the stacktrace from the crash report:

---- Minecraft Crash Report ----
// I'm sorry, Dave.

Time: 6/10/15 5:40 PM
Description: Initializing game

    java.lang.StringIndexOutOfBoundsException: String index out of range: 
-1
at java.lang.String.substring(Unknown Source)
at polymer.aspectadder.AspectAdder.decodeValues(AspectAdder.java:105)
at polymer.aspectadder.AspectAdder.postInit(AspectAdder.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at cpw.mods.fml.common.FMLModContainer.
handleModStateEvent(FMLModContainer.java:513)
at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventSubscriber.
handleEvent(EventSubscriber.java:74)
at com.google.common.eventbus.SynchronizedEventSubscriber.
handleEvent(SynchronizedEventSubscriber.java:47)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
at com.google.common.eventbus.EventBus.
dispatchQueuedEvents(EventBus.java:304)
at com.google.common.eventbus.EventBus.post(EventBus.java:275)
at cpw.mods.fml.common.LoadController.
sendEventToModContainer(LoadController.java:208)
at cpw.mods.fml.common.LoadController.
propogateStateMessage(LoadController.java:187)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventSubscriber.
handleEvent(EventSubscriber.java:74)
at com.google.common.eventbus.SynchronizedEventSubscriber
.handleEvent(SynchronizedEventSubscriber.java:47)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
at com.google.common.eventbus.EventBus.
dispatchQueuedEvents(EventBus.java:304)
at com.google.common.eventbus.EventBus.post(EventBus.java:275)
at cpw.mods.fml.common.LoadController.
distributeStateMessage(LoadController.java:118)
at cpw.mods.fml.common.Loader.initializeMods(Loader.java:694)
at cpw.mods.fml.client.FMLClientHandler.
finishMinecraftLoading(FMLClientHandler.java:288)
at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:541)
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:867)
at net.minecraft.client.main.Main.main(SourceFile:148)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)


A detailed walkthrough of the error, its code path and all known details  
is as follows:    
---------------------------------------------------------------------------
------------

-- Head --
Stacktrace:
at java.lang.String.substring(Unknown Source)
at polymer.aspectadder.AspectAdder.decodeValues(AspectAdder.java:105)
at polymer.aspectadder.AspectAdder.postInit(AspectAdder.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at cpw.mods.fml.common.FMLModContainer.
handleModStateEvent(FMLModContainer.java:513)
at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventSubscriber.
handleEvent(EventSubscriber.java:74)
at com.google.common.eventbus.SynchronizedEventSubscriber.
handleEvent(SynchronizedEventSubscriber.java:47)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
at com.google.common.eventbus.EventBus.
dispatchQueuedEvents(EventBus.java:304)
at com.google.common.eventbus.EventBus.post(EventBus.java:275)
at cpw.mods.fml.common.LoadController.
sendEventToModContainer(LoadController.java:208)
at cpw.mods.fml.common.LoadController.
propogateStateMessage(LoadController.java:187)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventSubscriber.
handleEvent(EventSubscriber.java:74)
at com.google.common.eventbus.SynchronizedEventSubscriber.
handleEvent(SynchronizedEventSubscriber.java:47)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
at com.google.common.eventbus.EventBus.
dispatchQueuedEvents(EventBus.java:304)
at com.google.common.eventbus.EventBus.post(EventBus.java:275)
at cpw.mods.fml.common.LoadController.
distributeStateMessage(LoadController.java:118)
at cpw.mods.fml.common.Loader.initializeMods(Loader.java:694)
at cpw.mods.fml.client.FMLClientHandler.
finishMinecraftLoading(FMLClientHandler.java:288)
at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:541)

-- Initialization --
Details:
Stacktrace:
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:867)
at net.minecraft.client.main.Main.main(SourceFile:148)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)

The file had the following line in it:

minecraft:sponge=WATER,WATER,WATER,VOID,VOID,CROP

This should add 3 WATER aspects, 2 VOID aspects, and 1 CROP aspect.

Here is my code:

package polymer.aspectadder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;

import net.minecraft.item.Item;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;

@Mod(modid = "aspectadder", name = "Aspect Adder", 
version = "1.0,minecraft 1.7.10", 
dependencies="required-after:Thaumcraft")
public class AspectAdder {


/*
 * A mod that allows the adding of Thaumcraft aspects to items, blocks,
 * or entities (enchantments may be added one day :D) 
 * This is done through a config file.
 * 
 * This is an example of how to add an aspect to something, in this case
 * adding 3 telum and 2 instrumentum to a Tinker's Construct Battleaxe
 * 
 * tconstruct:battleaxe=WEAPON,WEAPON,WEAPON,TOOL,TOOL
 */
public static Logger log = Logger.getLogger("Aspect Adder");
static String pathOfClass =
AspectAdder.class.getProtectionDomain()
.getCodeSource().getLocation().getPath();

static String pathOfInstall = pathOfClass.substring(0, 
pathOfClass.indexOf("mods")); //back up to the install folder
static String path = 
pathOfInstall.concat("config/aspectadder").substring(6);


@EventHandler
public void preInit(FMLPreInitializationEvent event){
        if(System.getProperty("os.name").startsWith("Windows")){
            path.replaceAll("/", "\\\\");
        }
    log.info("Creating a file at " + path + " if one does not exist.");
    try {
        new File(path).mkdirs();
        new File(path + File.separator + "entries.txt").createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }


}

@EventHandler
public void init(FMLInitializationEvent event){

}

@EventHandler
public void postInit(FMLPostInitializationEvent event){
    decodeValues(readFile());
}

static Properties readFile(){
    Properties p = new Properties();
    File f = new File(path + File.separator + "entries.txt");

        FileInputStream inStream;
        try {
            inStream = new FileInputStream(f);
            p.load(inStream);
            inStream.close();
        } catch (FileNotFoundException fnfe) {
            try {
                f.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // do nothing, since we handled this at lines 39-44
            // this catch clause is just here so the code runs
            // plus, the file is blank anyways if it wasn't there
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

    return p;
}


static void decodeValues(Properties p){
    Set<Object> keySet= p.keySet();
    Object[] keys = new Object[p.size()];
    int dex = 0;
    for(Object o : keySet){
        keys[dex] = o;
        dex++;
    }

    for(int i = 0; i < keys.length; i++){
        String key = keys[i].toString();
        Item item = GameRegistry.findItem(
                key.toString().substring(0, key.indexOf(":")),
                key.toString().substring(key.indexOf(":") + 1));
                //these are modID and item name, without the colon
        addAspects(item, p.getProperty(key));

    }
}


static void addAspects(Item item, String aspects) {
    log.info("Adding Aspects: " + aspects + " to " + 
item.getUnlocalizedName());
    AspectList list = new AspectList();
            int commaIndex = 0;
    int i = 0;
    do{
        String aspect = aspects.substring(commaIndex + 1, aspects.substring(commaIndex + 1).indexOf(","));
        commaIndex = aspects.substring(commaIndex + 1).indexOf(",");
        list.add(Aspect.getAspect(aspect), 1);
        i++;
        log.info("Attempting to add " + Aspect.getAspect(aspect).getTag() + " (" + aspect.toLowerCase() + ") to " + item.getUnlocalizedName());
    }while(commaIndex < aspects.lastIndexOf(","));
    ThaumcraftApi.registerObjectTag(item.getUnlocalizedName(), list);
}
}

So you don't have to count all those lines, the crash seems to be caused by this section of the code:

    for(int i = 0; i < keys.length; i++){
        String key = keys[i].toString();
        Item item = GameRegistry.findItem(
                //the following line is the one in the crash report
                key.toString().substring(0, key.indexOf(":")), 
                key.toString().substring(key.indexOf(":") + 1));
                //these are modID and item name, without the colon
        addAspects(item, p.getProperty(key));

    }
3

There are 3 answers

0
Barett On

Most likely it's crashing on an empty line, because it can't find a : character in it. Add this line above the one that creates an Item:

if (key.length() == 0) continue;

Also, you shouldn't need to call key.toString() : just key should be fine. It is already a String.

0
Cyrbil On

One of your key does not contain any ":" during execution, so key.toString().substring(0, key.indexOf(":")) is evaluated as key.substring(0, -1) which cause the error.

Check for presence of ":" before using substring()

0
Tschallacka On

You are looking for minecraft:sponge in the item registry. Sponge is a block and not an item. The BlockItem has a whole different id and won't appear in the item registry under minecraft:sponge.

So instead of:

Item item = GameRegistry.findItem(
            //the following line is the one in the crash report
            key.toString().substring(0, key.indexOf(":")), 
            key.toString().substring(key.indexOf(":") + 1));
            //these are modID and item name, without the colon

you should do

 Item item = GameRegistry.findItem(
            //the following line is the one in the crash report
            key.toString().substring(0, key.indexOf(":")), 
            key.toString().substring(key.indexOf(":") + 1));
            //these are modID and item name, without the colon
  // nothing found, assume it's a block
  if(item == null) {
      Block block = GameRegistry.findBlock(key.toString().substring(0,key.indexOf(":")),
                                           key.toString().substring(key.indexOf(":") + 1));
      if(block != null) {
          item = Block.getItemFromBlock(block);// You should probaly also do something with metadata here...
      }
  }
  if(item != null) {
      addAspects(item, p.getProperty(key));
  }

EDIT I noticed a simple blatant grab fromt he item registry without any checks, so i added the stuff above. but the stuff below is also important to keep in mind. I did not add the below steps in the code above.

You should learn how to process strings. Always check if something exists(index not -1, returned value not null) Then proceed.

Simple if then else. Especially with user custom input. you must always assume they will enter it wrong. And since this is only done at startup you can affor to make it "expensive" in checks.

int pos = str.indexOf(":");
if(pos > -1) {
     String[] contents = str.split(":");
     if(contents.length == 2) {
          String modname = contents[0];
          String itemid = contents[2];
          if(modname != null && itemid != null && modname.length() > 0 && itemid.length > 0
     }
}