Jump to content

Recommended Posts

Posted

Hey,

 

I was working on the deconstruction of a structure into NBT format, which I had mentioned before. http://www.minecraftforge.net/forum/index.php/topic,27717.0.html

 

But I ran into a snag... I couldn't find a way to read the NBT's keys beforehand to actually iterate through my data structure. :(

 

So I started to scratch my head, and came up with and idea to actually read the underlying "tagMap" keys, the obstacle was the field was private so I used my Reflection Skilz! :P

 

And made this:

public final class NBTUtils
{
private static final String TAG_MAP_KEY = "tagMap";

/**
 * Using reflection we fetch the NBTTagCompound Keys
 *
 * @param nbtTagCompound The tag compound we need keys from.
 * @return The keys as a string array.
 */
public static String[] getTagCompoundKeys(NBTTagCompound nbtTagCompound)
{
                // Get the class of the NBTTagCompound type.
	Class<NBTTagCompound> nbtTagCompoundClass = (Class<NBTTagCompound>) nbtTagCompound.getClass();
                
                // A string array to hold the keys in.
	String[] keysArray = null;

	try
	{
                        // Got the "tagMap" field.
		Field tagMapField = nbtTagCompoundClass.getDeclaredField(TAG_MAP_KEY);
                        
                        // Checking if the field is accessible.
		if (!tagMapField.isAccessible())
		{
			// If not let's be naughty and make it accessable 
			tagMapField.setAccessible(true);
		}
                       
                        // Getting the actual data from the tagMap field.
		Map tagMap = (Map) tagMapField.get(nbtTagCompound);

                        // Getting the key set.
		Set keys = tagMap.keySet();
                        
                        // Setting the keysArray array the same size as the keys.
		keysArray = new String[keys.size()];

                        // Converting it to an array.
		keys.toArray(keysArray);
	}
	catch (NoSuchFieldException e)
	{
		LogHelper.error("Could not find field '" + TAG_MAP_KEY + "'");
	}
	catch (IllegalAccessException e)
	{
		LogHelper.error("Could not access '" + TAG_MAP_KEY + "'");
	}

	return keysArray;
}
}

 

So question, did I waste like 10 minutes of my life writing this or does it deserve as spot in the tutorials section?

 

Be honest people! I can take a hit! :P

I require Java, both the coffee and the code :)

Posted

Well, not that this is useless (it MIGHT be useful if you want it to be), but there are some things here:

1. You don't know what given key represents (int, long, string)

- So you would have to also read it and/or return e.g array of pairs <String, Object> e.g: <"someKey", Integer>, so that you can instantly know to use getInteger()

- Without it, the tool is pretty very not-optimized.

2. There is a data structure that allows you to iterate: NBTTagList, yet maybe not in the way you want (reconstruction of unknown).

 

Overall, if you want to use this tool as a clean-up device it might be useful to remove some garbage-data from e.g updating data-structure mods, otherwise - I don't like Reflection for data-reading.

 

If you'd like to go totally hardcore you could actually take NBTTagCompound.toString() and use Matchers to get all data and even nicely return it in List of HashMaps or other stuff. Idk, it might be actually more expensive on big strings.

1.7.10 is no longer supported by forge, you are on your own.

Posted

1. You don't know what given key represents (int, long, string)

- So you would have to also read it and/or return e.g array of pairs <String, Object> e.g: <"someKey", Integer>, so that you can instantly know to use getInteger()

- Without it, the tool is pretty very not-optimized.

 

Since it's my own data I will be look for, in a CompoundTag with a known key then it's not a problem in guessing what the DataType would be, It's like s standard I guess in my code.

 

2. There is a data structure that allows you to iterate: NBTTagList, yet maybe not in the way you want (reconstruction of unknown).

Yes I actually thought about that approach, I was going to create an NBTTagList with each Tag Containing an other List or Custom NBTTag of two items, Index[0]:Key and Index[1]:Value, All I do then iterate the known structure and the keys will become available while iterating.

 

I might try that one when I have a chance, and maybe even load test them see how they behave.

 

Overall, if you want to use this tool as a clean-up device it might be useful to remove some garbage-data from e.g updating data-structure mods, otherwise - I don't like Reflection for data-reading.

I hear you, I don't like reflection either. The only time I use it is for unit testing something that I don't have access to.

 

If you'd like to go totally hardcore you could actually take NBTTagCompound.toString() and use Matchers to get all data and even nicely return it in List of HashMaps or other stuff. Idk, it might be actually more expensive on big strings.

This could work too, might be a bit more expensive (I think) to parse the strings into hash-maps, the data will become larger and larger... Will put a limit on it though.

 

Thank you for the insight!

I require Java, both the coffee and the code :)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.