Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[SOLVED] [1.15.2] Saving and Loading data per world


Roxane
 Share

Recommended Posts

Hi there,

 

For my mod I want an inventory like an Ender Chest that is shared between all players. Whereever anyone is accessing this inventory it is the same.

In previous versions I did this by saving a "per world inventory" NBT to the world save file. Aditionally I want to save all positions of these "chests", so I always know where they are.

 

With saving the data I have some Issues:

1) My onWorldLoaded and onWorldSaved events do not get called, even though I registered them in my mod's constructor. (The onClientSetupEvent gets called, so I assume the basic setup is ok).

2) How do I store my NBT data to the world save file? In previous versions I used a class extending WorldSavedData. I looked at https://mcforge.readthedocs.io/en/latest/datastorage/worldsaveddata/. But I can't figure out why

MapStorage storage = world.getMapStorage();

does not work. It seems neither MapStorage nor getMapStorage() exist...

3) May be related to Problem 1): The WorldEvent.Load::getWorld only returns an IWorld. My old MySavedData::forWorld required a World. Is that a problem at all? If yes, where do I get my World from?

 

This is my main mod class (For demonstration purposes I stripped all unnecessary stuff like Blocks and Items, they are working fine):

package de.tetopia.question;

import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.World;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

// The value here should match an entry in the META-INF/mods.toml file
@Mod(ModQuestion.MODID)
public class ModQuestion
{
    public static final String MODID = "questionmod";
	private static final Logger LOGGER = LogManager.getLogger();

    public ModQuestion() 
    {
    	FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientSetupEvent);
    	FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onWorldLoaded);
    	FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onWorldSaved);
    }
    
    private void onClientSetupEvent(final FMLClientSetupEvent event) 
    {
    	LOGGER.debug("Hello from the Client Setup!");
    }
    
	public void onWorldLoaded(WorldEvent.Load event)
	{
		LOGGER.debug("Hello from World Loading!");
		
		World world = null; //Where do I get my world from? event.getWorld() returns an IWorld
		if (!world.isRemote()) 
		{
			//Get the data from the world save file
			CompoundNBT tag = new CompoundNBT();
			
			CompoundNBT tagCompound = new CompoundNBT();
			MySavedData saver = MySavedData.forWorld(world);
			tag = saver.data;
			
			if(tagCompound.contains("MyTagName"))
			{
				//Do Stuff with the data
			}
		}
	}
	
	public void onWorldSaved(WorldEvent.Save event)
	{
		LOGGER.debug("Hello from World Saving!");
		
		World world = null; //Where do I get my world from? event.getWorld() returns an IWorld
		
		if (!world.isRemote())
		{
			CompoundNBT dataToSave = new CompoundNBT();
			
			//Store some data in dataToSave
			//dataToSave.put("MyTagName", ...);
					
			MySavedData saver = MySavedData.forWorld(world);
			saver.data = dataToSave;
			saver.markDirty();
		}
	}
}

 

And this is my custom WorldSavedData class:

package de.tetopia.question;

import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.World;
import net.minecraft.world.storage.WorldSavedData;

public class MySavedData extends WorldSavedData
{
	public CompoundNBT data = new CompoundNBT();
	
	public MySavedData()
	{
		super(ModQuestion.MODID);
	}
	
	public MySavedData(String name)
	{
		super(name);
	}

	@Override
	public void read(CompoundNBT nbt)
	{
		data = nbt.getCompound("MyTagName");
	}

	@Override
	public CompoundNBT write(CompoundNBT nbt)
	{
		nbt.put("MyTagName", data);
		return nbt;
	}
	
	public static MySavedData forWorld(World world)
	{
		MapStorage storage = world.getMapStorage(); //PROBLEM: What is the 1.15 way of doing this?
		MySavedData saver = (MySavedData) storage.getOrLoadData(MySavedData.class, ModQuestion.MODID);

		if (saver == null) 
		{
			saver = new MySavedData();
			storage.setData(ModQuestion.MODID, saver);
		}
		return saver;
	}
}

 

Edited by Roxane
Solved Issue
Link to comment
Share on other sites

7 minutes ago, Roxane said:

FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onWorldLoaded); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onWorldSaved);

The WorldEvent.Load and WorldEvent.Save do not fire on the mod event bus. They instead fire on the MinecraftForge.EVENT_BUS. The mod event bus is only for life-cycle events such as FMLCommonSetupEvent.

 

10 minutes ago, Roxane said:

But I can't figure out why

It seems to have been renamed to World::getMapData or ServerWorld::getSavedData()::getOrCreate

 

At the moment I'm not fully aware of how the WorldSavedData system has changed, however you can use a Capability that is attached to the World.

13 minutes ago, Roxane said:

If yes, where do I get my World from?

instanceof and cast.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

21 minutes ago, Animefan8888 said:

The WorldEvent.Load and WorldEvent.Save do not fire on the mod event bus. They instead fire on the MinecraftForge.EVENT_BUS. The mod event bus is only for life-cycle events such as FMLCommonSetupEvent.

Thanks! Calling "MinecraftForge.EVENT_BUS.addListener(this::onWorldLoaded);" did the trick ?

 

21 minutes ago, Animefan8888 said:

It seems to have been renamed to World::getMapData or ServerWorld::getSavedData()::getOrCreate

Hmm... I can't find the World::getMapData. And ServerWorld::getSavedData()::getOrCreate want's a Supplier <T> as parameter. Where do I get that from?

 

21 minutes ago, Animefan8888 said:

however you can use a Capability that is attached to the World.

Thanks for that tip, I'll look into that direction.

 

 

 

Edited by Roxane
Link to comment
Share on other sites

2 minutes ago, Roxane said:

Where do I get that from?

You create one. A Supplier is just a functional interface that returns an instance of type T. In this case I believe it would be an instance of your WorldSavedData class.

 

3 minutes ago, Roxane said:

Is it only the Capability you mentioned? Or is there something else?

It's the only forge provided way of doing it yes. There's three ways to do this. WorldSavedData(which has apparently changed a little bit), Capabilities(which to my knowledge are still the same as when they were first introduced), and of course you can write the file to disk yourself(not really the best option because the first two already exist).

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Thank you very much! With your Information I could get it to work ?

 

For anybody interested, this is my code now.

Mod class:

import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

// The value here should match an entry in the META-INF/mods.toml file
@Mod(ModQuestion.MODID)
public class ModQuestion
{
    public static final String MODID = "questionmod";
	private static final Logger LOGGER = LogManager.getLogger();

    public ModQuestion() 
    {
    	FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientSetupEvent);
    	MinecraftForge.EVENT_BUS.addListener(this::onWorldLoaded);
    	MinecraftForge.EVENT_BUS.addListener(this::onWorldSaved);
    }
    
    private void onClientSetupEvent(final FMLClientSetupEvent event) 
    {
    	//LOGGER.debug("Hello from the Client Setup!");
    }
    
	public void onWorldLoaded(WorldEvent.Load event)
	{
		if (!event.getWorld().isRemote() && event.getWorld() instanceof ServerWorld)
		{
			MySavedData saver = MySavedData.forWorld((ServerWorld) event.getWorld());
   			
			if(saver.data.contains("MyData"))
			{
				LOGGER.debug("Found my data: " + saver.data.get("MyData"));
				//Do whatever you want to do with the data
			}
		}
	}
	
	public void onWorldSaved(WorldEvent.Save event)
	{
		if (!event.getWorld().isRemote() && event.getWorld() instanceof ServerWorld)
		{
			MySavedData saver = MySavedData.forWorld((ServerWorld) event.getWorld());
			CompoundNBT myData = new CompoundNBT();
			myData.putInt("MyData", 0); //Put in whatever you want with myData.put
			saver.data = myData;
			saver.markDirty();
			LOGGER.debug("Put my data in!");
		}
	}
}

 

WorldSaverData class:

import java.util.function.Supplier;

import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.DimensionSavedDataManager;
import net.minecraft.world.storage.WorldSavedData;

public class MySavedData extends WorldSavedData implements Supplier
{
	public CompoundNBT data = new CompoundNBT();
	
	public MySavedData()
	{
		super(ModQuestion.MODID);
	}
	
	public MySavedData(String name)
	{
		super(name);
	}

	@Override
	public void read(CompoundNBT nbt)
	{
		data = nbt.getCompound("MyCompound");
	}

	@Override
	public CompoundNBT write(CompoundNBT nbt)
	{
		nbt.put("MyCompound", data);
		return nbt;
	}
	
	public static MySavedData forWorld(ServerWorld world)
	{
		DimensionSavedDataManager storage = world.getSavedData();
		Supplier<MySavedData> sup = new MySavedData();
		MySavedData saver = (MySavedData) storage.getOrCreate(sup, ModQuestion.MODID);

		if (saver == null) 
		{
			saver = new MySavedData();
			storage.set(saver);
		}
		return saver;
	}
	
	@Override
	public Object get()
	{
		return this;
	}
}

 

  • Like 1
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
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.

 Share



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • by running the run.bat with this in it "java -Xmx3072M -Xms3072M -jar forgeserver.jar nogui PAUSE"
    • You have to download... what first?
    • 1.12 is no longer supported on this forum. Please update to a modern version of Minecraft to receive support.
    • I've been trying to install Forge version 1.12.2 to play a minecraft server with some friends but it is not working. I saw another post with the same issue as me; that being that a certain library will not install. The recommendation for that post was running the installer through CMD. I have tried that and am still getting the same error.   Logs JVM info: Oracle Corporation - 1.8.0_321 - 25.321-b07 java.net.preferIPv4Stack=true Found java version 1.8.0_321 Extracting json Considering minecraft client jar Downloading libraries Found 0 additional library directories Considering library net.minecraftforge:forge:1.12.2-14.23.5.2859   File exists: Checksum validated. Considering library org.ow2.asm:asm-debug-all:5.2   File exists: Checksum validated. Considering library net.minecraft:launchwrapper:1.12   File exists: Checksum validated. Considering library org.jline:jline:3.5.1   File exists: Checksum validated. Considering library com.typesafe.akka:akka-actor_2.11:2.3.3   File exists: Checksum validated. Considering library com.typesafe:config:1.2.1   File exists: Checksum validated. Considering library org.scala-lang:scala-actors-migration_2.11:1.1.0   File exists: Checksum validated. Considering library org.scala-lang:scala-compiler:2.11.1   File exists: Checksum invalid, deleting file:     Expected: 56ea2e6c025e0821f28d73ca271218b8dd04926a     Actual:   e36a29a94e39c5b4215e88a2bf5c044539cf3203   Downloading library from https://maven.minecraftforge.net/org/scala-lang/scala-compiler/2.11.1/scala-compiler-2.11.1.jar java.net.SocketTimeoutException: Read timed out     at java.net.SocketInputStream.socketRead0(Native Method)     at java.net.SocketInputStream.socketRead(Unknown Source)     at java.net.SocketInputStream.read(Unknown Source)     at java.net.SocketInputStream.read(Unknown Source)     at sun.security.ssl.SSLSocketInputRecord.read(Unknown Source)     at sun.security.ssl.SSLSocketInputRecord.readFully(Unknown Source)     at sun.security.ssl.SSLSocketInputRecord.decodeInputRecord(Unknown Source)     at sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source)     at sun.security.ssl.SSLTransport.decode(Unknown Source)     at sun.security.ssl.SSLSocketImpl.decode(Unknown Source)     at sun.security.ssl.SSLSocketImpl.readApplicationRecord(Unknown Source)     at sun.security.ssl.SSLSocketImpl.access$300(Unknown Source)     at sun.security.ssl.SSLSocketImpl$AppInputStream.read(Unknown Source)     at java.io.BufferedInputStream.read1(Unknown Source)     at java.io.BufferedInputStream.read(Unknown Source)     at sun.net.www.MeteredStream.read(Unknown Source)     at java.io.FilterInputStream.read(Unknown Source)     at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)     at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)     at java.nio.file.Files.copy(Unknown Source)     at java.nio.file.Files.copy(Unknown Source)     at net.minecraftforge.installer.DownloadUtils.download(DownloadUtils.java:186)     at net.minecraftforge.installer.DownloadUtils.download(DownloadUtils.java:174)     at net.minecraftforge.installer.DownloadUtils.downloadLibrary(DownloadUtils.java:159)     at net.minecraftforge.installer.actions.Action.downloadLibraries(Action.java:89)     at net.minecraftforge.installer.actions.ClientInstall.run(ClientInstall.java:110)     at net.minecraftforge.installer.InstallerPanel.run(InstallerPanel.java:423)     at net.minecraftforge.installer.SimpleInstaller.launchGui(SimpleInstaller.java:175)     at net.minecraftforge.installer.SimpleInstaller.main(SimpleInstaller.java:147) Considering library org.scala-lang.plugins:scala-continuations-library_2.11:1.0.2_mc   File exists: Checksum validated. Considering library org.scala-lang.plugins:scala-continuations-plugin_2.11.1:1.0.2_mc   File exists: Checksum validated. Considering library org.scala-lang:scala-library:2.11.1   File exists: Checksum validated. Considering library org.scala-lang:scala-parser-combinators_2.11:1.0.1   File exists: Checksum validated. Considering library org.scala-lang:scala-reflect:2.11.1   File exists: Checksum validated. Considering library org.scala-lang:scala-swing_2.11:1.0.1   File exists: Checksum validated. Considering library org.scala-lang:scala-xml_2.11:1.0.2   File exists: Checksum validated. Considering library lzma:lzma:0.0.1   File exists: Checksum validated. Considering library java3d:vecmath:1.5.2   File exists: Checksum validated. Considering library net.sf.trove4j:trove4j:3.0.3   File exists: Checksum validated. Considering library org.apache.maven:maven-artifact:3.5.3   File exists: Checksum validated. Considering library net.sf.jopt-simple:jopt-simple:5.0.3   File exists: Checksum validated. Considering library org.apache.logging.log4j:log4j-api:2.15.0   File exists: Checksum validated. Considering library org.apache.logging.log4j:log4j-core:2.15.0   File exists: Checksum validated. Considering library org.apache.logging.log4j:log4j-slf4j18-impl:2.15.0   File exists: Checksum validated. These libraries failed to download. Try again. org.scala-lang:scala-compiler:2.11.1
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.