Posted April 9, 20205 yr 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 April 9, 20205 yr by Roxane Solved Issue http://fs1.directupload.net/images/150105/uknhjhla.png[/img]
April 9, 20205 yr 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.
April 9, 20205 yr Author 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 April 9, 20205 yr by Roxane http://fs1.directupload.net/images/150105/uknhjhla.png[/img]
April 9, 20205 yr 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.
April 9, 20205 yr Author 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; } } http://fs1.directupload.net/images/150105/uknhjhla.png[/img]
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.