Changed the way world-specific data is stored. Old data will be transferred.

This commit is contained in:
Ellpeck 2016-12-28 14:55:03 +01:00
parent 7ff81ad637
commit 881a2006c2
10 changed files with 164 additions and 132 deletions

View file

@ -18,6 +18,7 @@ import de.ellpeck.actuallyadditions.mod.config.ConfigurationHandler;
import de.ellpeck.actuallyadditions.mod.crafting.CrusherCrafting;
import de.ellpeck.actuallyadditions.mod.crafting.InitCrafting;
import de.ellpeck.actuallyadditions.mod.crafting.ItemCrafting;
import de.ellpeck.actuallyadditions.mod.data.WorldData;
import de.ellpeck.actuallyadditions.mod.entity.InitEntities;
import de.ellpeck.actuallyadditions.mod.event.CommonEvents;
import de.ellpeck.actuallyadditions.mod.fluids.InitFluids;
@ -46,16 +47,16 @@ import de.ellpeck.actuallyadditions.mod.tile.TileEntityBase;
import de.ellpeck.actuallyadditions.mod.update.UpdateChecker;
import de.ellpeck.actuallyadditions.mod.util.ItemUtil;
import de.ellpeck.actuallyadditions.mod.util.ModUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLMissingMappingsEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.*;
// So that BuildCraft Oil always gets used
@Mod(modid = ModUtil.MOD_ID, name = ModUtil.NAME, version = ModUtil.VERSION, dependencies = "after:BuildCraft|Energy", guiFactory = "de.ellpeck.actuallyadditions.mod.config.GuiFactory")
@ -145,6 +146,17 @@ public class ActuallyAdditions{
ModUtil.LOGGER.info("PostInitialization Finished.");
}
@EventHandler
public void serverStarted(FMLServerStartedEvent event){
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
if(server != null){
World world = server.getEntityWorld();
if(world != null){
WorldData.get(world, true).markDirty();
}
}
}
@EventHandler
public void missingMapping(FMLMissingMappingsEvent event){
int totalRemaps = 0;

View file

@ -25,8 +25,11 @@ import java.util.concurrent.ConcurrentHashMap;
public final class PlayerData{
public static PlayerSave getDataFromPlayer(UUID id){
ConcurrentHashMap<UUID, PlayerSave> data = WorldData.getWorldUnspecificData().playerSaveData;
public static PlayerSave getDataFromPlayer(EntityPlayer player){
WorldData worldData = WorldData.get(player.getEntityWorld());
ConcurrentHashMap<UUID, PlayerSave> data = worldData.playerSaveData;
UUID id = player.getUniqueID();
if(data.containsKey(id)){
PlayerSave save = data.get(id);
if(save != null && save.id != null && save.id.equals(id)){
@ -37,13 +40,10 @@ public final class PlayerData{
//Add Data if none is existant
PlayerSave save = new PlayerSave(id);
data.put(id, save);
worldData.markDirty();
return save;
}
public static PlayerSave getDataFromPlayer(EntityPlayer player){
return getDataFromPlayer(player.getUniqueID());
}
public static class PlayerSave{
public UUID id;

View file

@ -18,119 +18,100 @@ import io.netty.util.internal.ConcurrentSet;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
import net.minecraft.world.WorldSavedData;
import net.minecraft.world.WorldServer;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraftforge.common.WorldSpecificSaveHandler;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class WorldData{
public class WorldData extends WorldSavedData{
public static final String DATA_TAG = ModUtil.MOD_ID+"data";
private static final ConcurrentHashMap<Integer, WorldData> WORLD_DATA = new ConcurrentHashMap<Integer, WorldData>();
private static WorldData data;
//TODO Remove this as well
public static List<File> legacyLoadWorlds = new ArrayList<File>();
public final ConcurrentSet<Network> laserRelayNetworks = new ConcurrentSet<Network>();
public final ConcurrentHashMap<UUID, PlayerSave> playerSaveData = new ConcurrentHashMap<UUID, PlayerSave>();
private final ISaveHandler handler;
private final int dimension;
public WorldData(ISaveHandler handler, int dimension){
this.handler = handler;
this.dimension = dimension;
public WorldData(String name){
super(name);
}
public static WorldData getWorldUnspecificData(){
return getDataForWorld(DimensionType.OVERWORLD.getId());
}
public static WorldData get(World world, boolean forceLoad){
if(forceLoad || data == null){
if(!world.isRemote){
WorldSavedData savedData = world.loadData(WorldData.class, DATA_TAG);
public static WorldData getDataForWorld(World world){
return getDataForWorld(world.provider.getDimension());
}
if(!(savedData instanceof WorldData)){
ModUtil.LOGGER.info("No WorldData found, creating...");
public static WorldData getDataForWorld(int dim){
WorldData data = WORLD_DATA.get(dim);
WorldData newData = new WorldData(DATA_TAG);
world.setData(DATA_TAG, newData);
data = newData;
}
else{
data = (WorldData)savedData;
ModUtil.LOGGER.info("Successfully loaded WorldData.");
}
if(data == null){
data = new WorldData(null, dim);
WORLD_DATA.put(dim, data);
//TODO Remove this part as well
if(!legacyLoadWorlds.isEmpty()){
for(File legacyFile : legacyLoadWorlds){
if(legacyFile != null && legacyFile.exists()){
String name = legacyFile.getName();
try{
FileInputStream stream = new FileInputStream(legacyFile);
NBTTagCompound compound = CompressedStreamTools.readCompressed(stream);
stream.close();
WorldData data = get(world);
data.readFromNBT(compound, true);
data.markDirty();
ModUtil.LOGGER.info("Successfully received and merged legacy WorldData "+name+"!");
if(legacyFile.delete()){
ModUtil.LOGGER.info("Successfully deleted legacy WorldData "+name+"!");
}
else{
ModUtil.LOGGER.warn("Couldn't delete legacy WorldData file "+name+"!");
}
}
catch(Exception e){
ModUtil.LOGGER.error("Something went wrong trying to load legacy WorldData "+name+"!", e);
}
}
}
legacyLoadWorlds.clear();
}
}
else{
data = new WorldData(DATA_TAG);
ModUtil.LOGGER.info("Created temporary WorldData to cache data on the client.");
}
}
return data;
}
public static void load(World world){
if(!world.isRemote && world instanceof WorldServer){
WorldData data = new WorldData(new WorldSpecificSaveHandler((WorldServer)world, world.getSaveHandler()), world.provider.getDimension());
WORLD_DATA.put(data.dimension, data);
try{
File dataFile = data.handler.getMapFileFromName(DATA_TAG+data.dimension);
if(dataFile != null && dataFile.exists()){
FileInputStream stream = new FileInputStream(dataFile);
NBTTagCompound compound = CompressedStreamTools.readCompressed(stream);
stream.close();
data.readFromNBT(compound);
ModUtil.LOGGER.info("Successfully received WorldData for world "+data.dimension+"!");
}
else{
ModUtil.LOGGER.info("No WorldData found for world "+data.dimension+", creating...");
}
}
catch(Exception e){
ModUtil.LOGGER.error("Something went wrong trying to load WorldData for world "+data.dimension+"!", e);
}
}
public static WorldData get(World world){
return get(world, false);
}
public static void save(World world){
if(!world.isRemote){
WorldData data = WORLD_DATA.get(world.provider.getDimension());
if(data != null && data.handler != null){
try{
File dataFile = data.handler.getMapFileFromName(DATA_TAG+data.dimension);
if(dataFile != null){
if(!dataFile.exists()){
dataFile.createNewFile();
ModUtil.LOGGER.info("Creating new WorldData file for world "+data.dimension+"!");
}
NBTTagCompound compound = new NBTTagCompound();
data.writeToNBT(compound);
FileOutputStream stream = new FileOutputStream(dataFile);
CompressedStreamTools.writeCompressed(compound, stream);
stream.close();
}
}
catch(Exception e){
ModUtil.LOGGER.error("Something went wrong trying to save WorldData for world "+data.dimension+"!", e);
}
}
else{
ModUtil.LOGGER.error("Tried to save WorldData for "+world.provider.getDimension()+" without any data handler being present!?");
}
}
}
public static void unload(World world){
if(!world.isRemote){
WORLD_DATA.remove(world.provider.getDimension());
ModUtil.LOGGER.info("Unloading WorldData for world "+world.provider.getDimension()+"!");
}
}
private void readFromNBT(NBTTagCompound compound){
//TODO Remove merging once removing old save handler
private void readFromNBT(NBTTagCompound compound, boolean merge){
//Laser World Data
this.laserRelayNetworks.clear();
if(!merge){
this.laserRelayNetworks.clear();
}
NBTTagList networkList = compound.getTagList("Networks", 10);
for(int i = 0; i < networkList.tagCount(); i++){
Network network = LaserRelayConnectionHandler.readNetworkFromNBT(networkList.getCompoundTagAt(i));
@ -138,7 +119,9 @@ public class WorldData{
}
//Player Data
this.playerSaveData.clear();
if(!merge){
this.playerSaveData.clear();
}
NBTTagList playerList = compound.getTagList("PlayerData", 10);
for(int i = 0; i < playerList.tagCount(); i++){
NBTTagCompound player = playerList.getCompoundTagAt(i);
@ -152,7 +135,13 @@ public class WorldData{
}
}
private void writeToNBT(NBTTagCompound compound){
@Override
public void readFromNBT(NBTTagCompound compound){
this.readFromNBT(compound, false);
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound){
//Laser World Data
NBTTagList networkList = new NBTTagList();
for(Network network : this.laserRelayNetworks){
@ -173,5 +162,17 @@ public class WorldData{
playerList.appendTag(player);
}
compound.setTag("PlayerData", playerList);
return compound;
}
//TODO Remove old loading mechanic after a while because it's legacy
public static void loadLegacy(World world){
if(!world.isRemote && world instanceof WorldServer){
int dim = world.provider.getDimension();
ISaveHandler handler = new WorldSpecificSaveHandler((WorldServer)world, world.getSaveHandler());
File dataFile = handler.getMapFileFromName(DATA_TAG+dim);
legacyLoadWorlds.add(dataFile);
}
}
}

View file

@ -87,6 +87,7 @@ public class CommonEvents{
PlayerData.PlayerSave save = PlayerData.getDataFromPlayer(event.player);
if(save != null && !save.bookGottenAlready){
save.bookGottenAlready = true;
WorldData.get(event.player.getEntityWorld()).markDirty();
EntityItem entityItem = new EntityItem(event.player.world, event.player.posX, event.player.posY, event.player.posZ, new ItemStack(InitItems.itemBooklet));
entityItem.setPickupDelay(0);
@ -109,16 +110,6 @@ public class CommonEvents{
@SubscribeEvent
public void onLoad(WorldEvent.Load event){
WorldData.load(event.getWorld());
}
@SubscribeEvent
public void onUnload(WorldEvent.Unload event){
WorldData.unload(event.getWorld());
}
@SubscribeEvent
public void onSave(WorldEvent.Save event){
WorldData.save(event.getWorld());
WorldData.loadLegacy(event.getWorld());
}
}

View file

@ -57,7 +57,9 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
firstNetwork.connections.add(secondPair);
}
WorldData.getDataForWorld(world).laserRelayNetworks.remove(secondNetwork);
WorldData data = WorldData.get(world);
data.laserRelayNetworks.remove(secondNetwork);
data.markDirty();
//System.out.println("Merged Two Networks!");
}
@ -67,7 +69,7 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
@Override
public ConcurrentSet<IConnectionPair> getConnectionsFor(BlockPos relay, World world){
ConcurrentSet<IConnectionPair> allPairs = new ConcurrentSet<IConnectionPair>();
for(Network aNetwork : WorldData.getDataForWorld(world).laserRelayNetworks){
for(Network aNetwork : WorldData.get(world).laserRelayNetworks){
for(IConnectionPair pair : aNetwork.connections){
if(pair.contains(relay)){
allPairs.add(pair);
@ -85,7 +87,9 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
Network network = this.getNetworkFor(relay, world);
if(network != null){
//Setup new network (so that splitting a network will cause it to break into two)
WorldData.getDataForWorld(world).laserRelayNetworks.remove(network);
WorldData data = WorldData.get(world);
data.laserRelayNetworks.remove(network);
data.markDirty();
for(IConnectionPair pair : network.connections){
if(!pair.contains(relay)){
this.addConnection(pair.getPositions()[0], pair.getPositions()[1], pair.getType(), world, pair.doesSuppressRender());
@ -100,7 +104,7 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
*/
@Override
public Network getNetworkFor(BlockPos relay, World world){
for(Network aNetwork : WorldData.getDataForWorld(world).laserRelayNetworks){
for(Network aNetwork : WorldData.get(world).laserRelayNetworks){
for(IConnectionPair pair : aNetwork.connections){
if(pair.contains(relay)){
return aNetwork;
@ -124,6 +128,7 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
if(firstRelay == null || secondRelay == null || firstRelay == secondRelay || firstRelay.equals(secondRelay)){
return false;
}
WorldData data = WorldData.get(world);
Network firstNetwork = this.getNetworkFor(firstRelay, world);
Network secondNetwork = this.getNetworkFor(secondRelay, world);
@ -131,7 +136,7 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
//No Network exists
if(firstNetwork == null && secondNetwork == null){
firstNetwork = new Network();
WorldData.getDataForWorld(world).laserRelayNetworks.add(firstNetwork);
data.laserRelayNetworks.add(firstNetwork);
firstNetwork.connections.add(new ConnectionPair(firstRelay, secondRelay, type, suppressConnectionRender));
firstNetwork.changeAmount++;
}
@ -158,6 +163,7 @@ public final class LaserRelayConnectionHandler implements ILaserRelayConnectionH
//System.out.println("Connected "+firstRelay.toString()+" to "+secondRelay.toString());
//System.out.println(firstNetwork == null ? secondNetwork.toString() : firstNetwork.toString());
//System.out.println(laserRelayNetworks);
data.markDirty();
return true;
}

View file

@ -11,9 +11,10 @@
package de.ellpeck.actuallyadditions.mod.network;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
public interface IDataHandler{
void handleData(NBTTagCompound compound);
void handleData(NBTTagCompound compound, MessageContext context);
}

View file

@ -60,13 +60,12 @@ public class PacketClientToServer implements IMessage{
public static class Handler implements IMessageHandler<PacketClientToServer, IMessage>{
@Override
public IMessage onMessage(PacketClientToServer aMessage, MessageContext ctx){
final PacketClientToServer message = aMessage;
public IMessage onMessage(final PacketClientToServer message, final MessageContext ctx){
FMLCommonHandler.instance().getMinecraftServerInstance().addScheduledTask(new Runnable(){
@Override
public void run(){
if(message.data != null && message.handler != null){
message.handler.handleData(message.data);
message.handler.handleData(message.data, ctx);
}
}
});

View file

@ -11,6 +11,7 @@
package de.ellpeck.actuallyadditions.mod.network;
import de.ellpeck.actuallyadditions.mod.data.PlayerData;
import de.ellpeck.actuallyadditions.mod.data.WorldData;
import de.ellpeck.actuallyadditions.mod.network.gui.IButtonReactor;
import de.ellpeck.actuallyadditions.mod.network.gui.INumberReactor;
import de.ellpeck.actuallyadditions.mod.network.gui.IStringReactor;
@ -30,6 +31,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@ -44,14 +46,14 @@ public final class PacketHandler{
public static final IDataHandler LASER_HANDLER = new IDataHandler(){
@Override
@SideOnly(Side.CLIENT)
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
AssetUtil.spawnLaserWithTimeClient(compound.getDouble("StartX"), compound.getDouble("StartY"), compound.getDouble("StartZ"), compound.getDouble("EndX"), compound.getDouble("EndY"), compound.getDouble("EndZ"), new float[]{compound.getFloat("Color1"), compound.getFloat("Color2"), compound.getFloat("Color3")}, compound.getInteger("MaxAge"), compound.getDouble("RotationTime"), compound.getFloat("Size"), compound.getFloat("Alpha"));
}
};
public static final IDataHandler TILE_ENTITY_HANDLER = new IDataHandler(){
@Override
@SideOnly(Side.CLIENT)
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
World world = Minecraft.getMinecraft().world;
if(world != null){
TileEntity tile = world.getTileEntity(new BlockPos(compound.getInteger("X"), compound.getInteger("Y"), compound.getInteger("Z")));
@ -64,7 +66,7 @@ public final class PacketHandler{
public static final IDataHandler LASER_PARTICLE_HANDLER = new IDataHandler(){
@Override
@SideOnly(Side.CLIENT)
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
Minecraft mc = Minecraft.getMinecraft();
ItemStack stack = new ItemStack(compound);
@ -84,7 +86,7 @@ public final class PacketHandler{
};
public static final IDataHandler GUI_BUTTON_TO_TILE_HANDLER = new IDataHandler(){
@Override
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
World world = DimensionManager.getWorld(compound.getInteger("WorldID"));
TileEntity tile = world.getTileEntity(new BlockPos(compound.getInteger("X"), compound.getInteger("Y"), compound.getInteger("Z")));
@ -99,7 +101,7 @@ public final class PacketHandler{
};
public static final IDataHandler GUI_BUTTON_TO_CONTAINER_HANDLER = new IDataHandler(){
@Override
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
World world = DimensionManager.getWorld(compound.getInteger("WorldID"));
Entity entity = world.getEntityByID(compound.getInteger("PlayerID"));
if(entity instanceof EntityPlayer){
@ -112,7 +114,7 @@ public final class PacketHandler{
};
public static final IDataHandler GUI_NUMBER_TO_TILE_HANDLER = new IDataHandler(){
@Override
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
World world = DimensionManager.getWorld(compound.getInteger("WorldID"));
TileEntity tile = world.getTileEntity(new BlockPos(compound.getInteger("X"), compound.getInteger("Y"), compound.getInteger("Z")));
@ -124,7 +126,7 @@ public final class PacketHandler{
};
public static final IDataHandler GUI_STRING_TO_TILE_HANDLER = new IDataHandler(){
@Override
public void handleData(NBTTagCompound compound){
public void handleData(NBTTagCompound compound, MessageContext context){
World world = DimensionManager.getWorld(compound.getInteger("WorldID"));
TileEntity tile = world.getTileEntity(new BlockPos(compound.getInteger("X"), compound.getInteger("Y"), compound.getInteger("Z")));
@ -136,12 +138,32 @@ public final class PacketHandler{
};
public static final IDataHandler CHANGE_PLAYER_DATA_HANDLER = new IDataHandler(){
@Override
public void handleData(NBTTagCompound compound){
NBTTagCompound data = compound.getCompoundTag("Data");
public void handleData(NBTTagCompound compound, MessageContext context){
NBTTagCompound dataTag = compound.getCompoundTag("Data");
UUID id = compound.getUniqueId("UUID");
PlayerData.getDataFromPlayer(id).readFromNBT(data, false);
if(compound.getBoolean("Log")){
ModUtil.LOGGER.info("Receiving (new or changed) Player Data for player with UUID "+id+".");
EntityPlayer player = null;
if(context.side == Side.SERVER){
int dim = compound.getInteger("Dimension");
World world = DimensionManager.getWorld(dim);
if(world != null){
player = world.getPlayerEntityByUUID(id);
}
}
else{
player = Minecraft.getMinecraft().player;
}
if(player != null){
PlayerData.getDataFromPlayer(player).readFromNBT(dataTag, false);
WorldData.get(player.getEntityWorld()).markDirty();
if(compound.getBoolean("Log")){
ModUtil.LOGGER.info("Receiving (new or changed) Player Data for player "+player.getName()+" with UUID "+id+".");
}
}
else{
ModUtil.LOGGER.error("Tried to receive Player Data for player with UUID "+id+", but he doesn't seem to be present!");
}
}
};

View file

@ -47,6 +47,7 @@ public final class PacketHandlerHelper{
}
}
else{
compound.setInteger("Dimension", player.world.provider.getDimension());
PacketHandler.theNetwork.sendToServer(new PacketClientToServer(compound, PacketHandler.CHANGE_PLAYER_DATA_HANDLER));
}
}

View file

@ -63,13 +63,12 @@ public class PacketServerToClient implements IMessage{
@Override
@SideOnly(Side.CLIENT)
public IMessage onMessage(PacketServerToClient aMessage, MessageContext ctx){
final PacketServerToClient message = aMessage;
public IMessage onMessage(final PacketServerToClient message, final MessageContext ctx){
Minecraft.getMinecraft().addScheduledTask(new Runnable(){
@Override
public void run(){
if(message.data != null && message.handler != null){
message.handler.handleData(message.data);
message.handler.handleData(message.data, ctx);
}
}
});