Resource Initialization Question

There’s another question i have in mind for some longer time, but since now i can’t find, what would be really great for me.
My objects initialize with different values by size, position, velocity, mass, its representation as string and so on and so on.
during initialization it makes up my scene out of the objects i use.

as those are a couple of values, which really look like a table itself … what file format would i preferebly use ? i thought on using properties as i do it with the language file, but that would make me use of several files for that values, which i don’t want.

So my question is, how would/are you storing that kind of information to pass it through during initialization of the app.
Is there a good example i can look at to see, what i am trying to do.
Since now … as i really need them to start up, all the values are public static, just for getting this thing working, but i don’t want to keep that in this state of production :wink:

I use json files to load my circuits and vehicles.

You can either hold them in your assets and read them using TextLoader (that you can copy from the testJME lib).
Or you can hold them in a special folder and locate that folder using getAssetManager().registerLocator("./mods", FileLocator.class);
Easiest is the first solution. One caveat: you can’t modify / delete them… which is great for maps you want to somewhat force everybody to have the same.
Second solution is to be favored if you want to make your game moddable. One caveat: since that folder won’t be located at the same place on windows, android etc, you’ll have to use a different path depending on the OS (if you target multiple OS).

1 Like

That was really easy !

If your data are mainly table, json will be verbose.
IMHO, you should make a basic csv parser (see @Empire_Phoenix shared one to read i18n data, this week on the forum). And you use your favorite spreadsheet editor (or a text editor) to edit it.

I think csv is a bad format for such a scenario. Json is 5 order of magnitudes more adaptative.

Json is way more expressive , but why do you care about the storing loading yourself? You can speend month writing a good implementation.
Store it using objects and jackson.

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 *
 * @author empire
 *
 */
public final class JSONHelper {
	private static ObjectMapper	pretty	= JSONHelper.jacksonImpl(true);
	private static ObjectMapper	compact	= JSONHelper.jacksonImpl(false);

	private JSONHelper() {
	}

	private static ObjectMapper jacksonImpl(final boolean b) {
		final ObjectMapper mapper = new ObjectMapper();
		if (b) {
			mapper.enable(SerializationFeature.INDENT_OUTPUT);
		}
		mapper.enable(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS);
		mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
		mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
		mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
		return mapper;
	}

	public static ObjectMapper getPretty() {
		return JSONHelper.pretty;
	}

	public static ObjectMapper getCompact() {
		return JSONHelper.compact;
	}

	public static void addModule(final Module mod) {
		JSONHelper.pretty.registerModule(mod);
		JSONHelper.compact.registerModule(mod);
	}
}

Saving/Loading is pretty simple then, also allows to just serialize deserialize from String, and you can implement the String loading yourself then, so its compatible with jme assetmanager with very little work. Note json is not expressive enough for Using Hashmaps with non String keys. List structures work as expected.
Alternativly if you dont worry about file size look at XStream, it can serialize everything java Serializer is capable of and speed is even a little faster.

        final HashMap<String, DataHolder> level = new HashMap<String, DataHolder>();
	JSONHelper.getPretty().writeValue(new File("./gurke")), levels);
        final HashMap<String, DataHolder> restored = JSONHelper.getPretty().readValue(new File("./gurke"), HashMap.class);

I noticed your last post and moved it over to review it, but for now i can’t see the entry and exit of this thing, because i am unused to that thing yet.
first i think i take a normal textloader and give back objects i need to simplify my initialization massacre.
i have a clean json file i now try to use to init all that stuff i initialized static before.
be back soon ! :wink:

oh, btw, i am now standing in front of the problem on how to get that inputstream into the jsonobjectparser …
i am not used to that …

json is more expressive, but for raw table data : csv (or tsv) and spreadsheet editor is a better match (to add column, check missing cell,…).

In the contest of more expressive format, my 2c (better than json IMHO) :

And in binary format, my recommendation : protobuf - Protocol Buffers - Google’s data interchange format

@Yves_Tanas:
Depends what solution you are using; if it’s simply reading the files and loading it’s content yourself as I described, then:

I agree, but for instantiating different types of objects, csv is really not up to the task.

I like using a couple formats and not using one different format for each different case, but well, you peeps have bigger heads than I do so probably less a hassle for you :smiley: .

So this is what i have come up with now and it reaaaally fits my actual needs.
Thx a lot for contribution and i think i will review the tips in here later if it makes sense.
for now i now have a nice ArrayList that i can cycle throug easily while building up my fantastic awesome game :wink:

Btw. here’s the code.
I used google lib GSon. This is reaaally easy:

package mygame;

import com.google.gson.Gson;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import com.google.gson.JsonArray; 
import com.google.gson.JsonObject;

public class MyJSONLoader implements AssetLoader {
    public Object load(AssetInfo assetInfo) throws IOException {
         Gson gson = new Gson();
         ArrayList<OrbitDefinition>  system = new ArrayList<OrbitDefinition>();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(assetInfo.openStream())); 
            JsonObject json = gson.fromJson(reader, JsonObject.class);             
            JsonArray objects = json.getAsJsonArray("orbitDefinition"); 
            for(int i = 0; i < objects.size(); i++){ 
                JsonObject object = objects.get(i).getAsJsonObject(); 
                OrbitDefinition element = new OrbitDefinition();
                element.setName(object.get("name").getAsString());
                element.setRadius(object.get("radius").getAsFloat());
                element.setRotation(object.get("rotation").getAsFloat());
                element.setOrbitRange(object.get("orbitRange").getAsFloat());
                element.setColorMap(object.get("colorMap").getAsString());
                element.setSmallPic(object.get("smallPic").getAsString());
                element.setVelocity(object.get("velocity").getAsFloat());
                element.setMass(object.get("mass").getAsFloat());
                element.setDense(object.get("dense").getAsFloat());
                element.setEccentricity(object.get("eccentricity").getAsFloat());
                element.setAttachedTo(object.get("attachedTo").getAsString());
                system.add(element);
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return system;
    }
}

and here for some review my currently fantastic json object file

{
    "orbitDefinition": [
    {
        "name": "sun",
        "radius": "696342",
        "rotation": "25",
        "orbitRange": "696342e4",
        "distInAU": "0",
        "colorMap": "0_sun.jpg",
        "smallPic": "0_sun_sm.jpg",
        "velocity": "0",
        "mass": "1.98892e30",
        "dense": "1.408",
        "eccentricity": "0",
        "attachedTo": "cosmos"
    },{
        "name": "mercury",
        "radius": "2440",
        "rotation": "48",
        "orbitRange": "3e5",
        "distInAU": "0.38709893",
        "colorMap": "1_mercury.jpg",
        "smallPic": "1_mercury_sm.jpg",
        "velocity": "0",
        "mass": "3.302e23",
        "dense": "5.427",
        "eccentricity": "0",
        "attachedTo": "sun"
    },{
        "name": "venus",
        "radius": "6051.8",
        "rotation": "243",
        "orbitRange": "6e5",
        "distInAU": "0.723",
        "colorMap": "2_venus.jpg",
        "smallPic": "2_venus_sm.jpg",
        "velocity": "0",
        "mass": "4.8685e24",
        "dense": "5.243",
        "eccentricity": "0",
        "attachedTo": "sun"
    },
    {
        "name": "earth",
        "radius": "6378.16",
        "rotation": "1",
        "orbitRange": "6.6e5",
        "distInAU": "1",
        "colorMap": "3_earth.jpg",
        "smallPic": "3_earth_sm.jpg",
        "velocity": "0",
        "mass": "5.9736e25",
        "dense": "5.515",
        "eccentricity": "0",
        "attachedTo": "sun"
    },{
        "name": "moon",
        "radius": "1738",
        "rotation": "27.322",
        "orbitRange": "17e4",
        "distInAU": "2.575e-6",
        "colorMap": "3_1_moon.jpg",
        "smallPic": "3_1_moon_sm.jpg",
        "velocity": "0",
        "mass": "7.349e22",
        "dense": "3.345",
        "eccentricity": "0",
        "attachedTo": "earth"
    },
    {
        "name": "mars",
        "radius": "3376.2",
        "rotation": "1",
        "orbitRange": "4e5",
        "distInAU": "1.524",
        "colorMap": "4_mars.jpg",
        "smallPic": "4_mars_sm.jpg",
        "velocity": "0",
        "mass": "6.4185e23",
        "dense": "3.933",
        "eccentricity": "0",
        "attachedTo": "sun"
    },{
        "name": "jupiter",
        "radius": "71500",
        "rotation": "0.4083",
        "orbitRange": "7e6",
        "distInAU": "5.203",
        "colorMap": "5_jupiter.jpg",
        "smallPic": "5_jupiter_sm.jpg",
        "velocity": "0",
        "mass": "1.899e27",
        "dense": "1.326",
        "eccentricity": "0",
        "attachedTo": "sun"
    },{
        "name": "saturn",
        "radius": "60268",
        "rotation": "0.44791",
        "orbitRange": "6e6",
        "distInAU": "9.5826",
        "colorMap": "6_saturn.jpg",
        "smallPic": "6_saturn_sm.jpg",
        "velocity": "0",
        "mass": "5.6846e26",
        "dense": "0.687",
        "eccentricity": "0",
        "attachedTo": "sun"
    },{
        "name": "uranus",
        "radius": "25559",
        "rotation": "0.71875",
        "orbitRange": "6e5",
        "distInAU": "19.201",
        "colorMap": "7_uranus.jpg",
        "smallPic": "7_uranus_sm.jpg",
        "velocity": "0",
        "mass": "8.6832e25",
        "dense": "1.270",
        "eccentricity": "0",
        "attachedTo": "sun"
    },{
        "name": "neptune",
        "radius": "24764",
        "rotation": "0.666",
        "orbitRange": "6e5",
        "distInAU": "30.047",
        "colorMap": "8_neptune.jpg",
        "smallPic": "8_neptune_sm.jpg",
        "velocity": "0",
        "mass": "1.0243e26",
        "dense": "1.638",
        "eccentricity": "0",
        "attachedTo": "sun"
    }]
}
1 Like

Congrats!

Looking at this thread, it occurs to me that with a simple groovy builder you could have almost the exact same data structure, without all of the quotes, etc., and directly instantiating your data model instead of requiring a translation step.

You have something working so I wouldn’t necessarily change it and the learning curve was steep… it’s just like the convergence of a lot of thinking locally so I thought it might be interesting to say out loud.

Or at least it seems like it would take almost no code to support something like:

orbitDefinition [ 
        {
            name: "sun"
            radius: 696342
            rotation: 25
            orbitRange: 696342e4
            distInAU: 0
            colorMap: "0_sun.jpg"
            smallPic: "0_sun_sm.jpg"
            velocity: 0
            mass: 1.98892e30
            dense: 1.408
            eccentricity: 0
            attachedTo: "cosmos"
        },{
            name: "mercury"
            radius: 2440
            rotation: 48
            orbitRange: 3e5
            distInAU: 0.38709893
            colorMap: "1_mercury.jpg"
            smallPic: "1_mercury_sm.jpg"
            velocity: 0
            mass: 3.302e23
            dense": 5.427
            eccentricity": 0
            attachedTo": "sun"
        },
        ....
1 Like

Oh, i already thought, that i don’t really need to translate it to that special dummy class.
That was just my example data class, holding the values i am interested in, added with some setter and getter.
I could let it just be that JsonArray and use it the same way.
This is a small sample project for me to adapt that small piece of idea into, what is already being half a game. I knew, if i have it in a real java object of my choice, there’s nothing left for me i’d need to know.

btw.: your groovy code looks really a little bit cuter.
could you give me a solution onto reading in this ?

If you have no groovy experience and no experience in embedding groovy then it’s kind of a big can of worms to open. But even without any code at all, you could use groovy to load lists and maps using a syntax almost just like that. For groovy automatically creates a list and [:] automatically creates a map.

So…

[myList:["item1", "item2", "item3"], name:"Foobar"]

…is 100% valid groovy code that loads a map with two values, one a list at “myList” and one a string at “name”.

It’s if you want that mapped directly into real objects that requires a specific set of groovy knowledge.

1 Like

i keep that in mind and make me a favourit here for later review.
if any of you guys could give me a clou on my other problem one thread ahead, i would be greatful, present my solution and move back to dig into my source code ^^
it’s more important for me to get that nifty gui a little bit looped that learning groovy right now. thx a lot ! :wink: