Jump to content

Saving persistent global data


KGS

Recommended Posts

So have a datastructure that I need to access from events. This datastructure needs to be persistent. It will be saved to the nbt when minecraft is shut down, and it will be loaded from the nbt when minecraft starts.

 

I have found instructions as how to make it persistent: I make it extend WorldSavedData and "register" it as follows:

world.mapStorage.loadData(Datastructure.class, "mydatastructure");

(obviously doing a null check and otherwise generating a fresh entry)

 

The problem is that I don't know where I should do this call, because I don't have access to a world from within my mod's init function.

Link to comment
Share on other sites

How's that possible?

 

How does it even know my class exists if I have not referenced it anywhere?

 

Every other mod related thing I've written so far has required manual registration somewhere, with the exception of the mod itself which is detected with the @ tag things and reflection.

 

Right now I have a tracker class extending WorldSavedData. It has NBT read and write methods but it's not doing anything, because it's not registered anywhere. Registering it using the method I mentioned in the first post does not work because it requires a world. I tried a "hack" where I got a world from a world provider from DimensionManager or something like that, but got an NPE.

Link to comment
Share on other sites

If you're having issues using the WorldSavedData, you can read and write files through Java's native file IO, including NBT data by using CompressedStreamTools.

 

String fileName = "mySavedData.dat";
File myFile = new File(DimensionManager.getCurrentSaveRootDirectory(), fileName);
FileInputStream fis = new FileInputStream(myFile); //this makes it per-world
DataInputStream instream = new DataInputStream(fis);
nbt = CompressedStreamTools.read(instream);
CompressedStreamTools.write(nbt, myFile);
instream.close();
fis.close();

 

I have a small mod I made that NEEDED to be able to do this, as I was going to be saving an abnormally large amount of data and wanted to be able to access sections of it without loading all of it, and needed an arbitrary number of data points.

(Average usage seems to clock in at around 30 files each storing 129kb of data)

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Hi

 

To save your data into the storage you need world.setItemData, not .loadData.

 

The data will be automatically saved and loaded from disk for you but you will still need to read it back out when the world loads and do something with it.

 

There is probably a suitable forge event you can subscribe to for this, perhaps WorldEvent.Load ?  (Never used it myself).

 

-TGG

Link to comment
Share on other sites

I can't get this to work.

 

I have an event listener now that listens to WorldEvent.Load

 

In it, I call a static method in the Tracker class which creates a new Tracker:

 

public static Tracker forWorld(World world) {
	MapStorage storage = world.mapStorage;
	Tracker result = (Tracker)storage.loadData(Tracker.class, key);
	if (result == null) {
		result = new Tracker(key);
		storage.setData(key, result);
	}
	instance = result;
	return result;
}

 

The tracker also has a read from nbt and write to nbt method, but they seem to never get called (I don't get any output from them, i have println() calls inside them for "debug" purposes. I use setDirty() inside the tracker whenever I add anything to it.

 

The curious thing too, which makes very little sense, is that the event triggers four times when starting up. If it did it twice I'd guess server and client side. But four times? That makes no sense whatsoever.

Link to comment
Share on other sites

Hi

 

Hmmm

 

The server side has a whole array of Worlds, at a guess you're seeing four loads because it is one for client plus overworld, ender, nether for server.

 

You only want the data to save on the server side, yes?  If the client needs the data, it will have to ask the server for it. 

 

Perhaps the multiple loads on the server side are overwriting your static Tracker with a new (blank) one each time?

 

The problem has got me intrigued, I'll see if I can't code up a test framework to try it out.  Might take me a few hours though.

 

-TGG

 

 

 

 

Link to comment
Share on other sites

You were correct!

 

The multiple triggers caused the event to overwrite the instance.

 

I added a null check in the method that creates it, so that if the instance is already created, it doesn't make a new one, it just returns the old one.

 

Now the save/load trigger properly. They're just dummy methods now, though. All they do is println a message indicating it's being called. I'll see if I can make it write a list of coordinates to the NBT properly, and then read that list.

Link to comment
Share on other sites

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.



×
×
  • Create New...

Important Information

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