diff --git a/src/main/java/cr0s/warpdrive/data/GlobalPosition.java b/src/main/java/cr0s/warpdrive/data/GlobalPosition.java index 4d3b997a..cdc6738b 100644 --- a/src/main/java/cr0s/warpdrive/data/GlobalPosition.java +++ b/src/main/java/cr0s/warpdrive/data/GlobalPosition.java @@ -1,5 +1,6 @@ package cr0s.warpdrive.data; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.WorldServer; @@ -55,6 +56,20 @@ public class GlobalPosition { return StarMapRegistry.getUniversalCoordinates(dimensionId, x, y, z); } + public GlobalPosition(final NBTTagCompound tagCompound) { + dimensionId = tagCompound.getInteger("dimensionId"); + x = tagCompound.getInteger("x"); + y = tagCompound.getInteger("y"); + z = tagCompound.getInteger("z"); + } + + public void writeToNBT(final NBTTagCompound tagCompound) { + tagCompound.setInteger("dimensionId", dimensionId); + tagCompound.setInteger("x", x); + tagCompound.setInteger("y", y); + tagCompound.setInteger("z", z); + } + public boolean equals(final TileEntity tileEntity) { return dimensionId == tileEntity.getWorldObj().provider.dimensionId && x == tileEntity.xCoord && y == tileEntity.yCoord && z == tileEntity.zCoord; diff --git a/src/main/java/cr0s/warpdrive/data/StarMapRegistry.java b/src/main/java/cr0s/warpdrive/data/StarMapRegistry.java index 8e50bbff..611b4eda 100644 --- a/src/main/java/cr0s/warpdrive/data/StarMapRegistry.java +++ b/src/main/java/cr0s/warpdrive/data/StarMapRegistry.java @@ -12,11 +12,14 @@ import cr0s.warpdrive.data.StarMapRegistryItem.EnumStarMapEntryType; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import net.minecraft.block.Block; import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MathHelper; @@ -26,6 +29,7 @@ import net.minecraft.world.WorldServer; import net.minecraft.world.gen.ChunkProviderServer; import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.common.util.Constants; /** * Registry of all known ships, jumpgates, etc. in the world @@ -309,13 +313,15 @@ public class StarMapRegistry { WarpDrive.logger.info("Starmap registry (" + registry.size() + " entries after " + trigger + "):"); for (Map.Entry> entryDimension : registry.entrySet()) { - String message = ""; + StringBuilder message = new StringBuilder(); for (StarMapRegistryItem registryItem : entryDimension.getValue()) { - message += "\n- " + registryItem.type + " '" + registryItem.name + "' @ " - + registryItem.dimensionId + ": " + registryItem.x + " " + registryItem.y + " " + registryItem.z - + " with " + registryItem.isolationRate + " isolation rate"; + message.append(String.format("\n- %s '%s' @ DIM%d (%d %d %d) with %.3f isolation rate", + registryItem.type, registryItem.name, + registryItem.dimensionId, registryItem.x, registryItem.y, registryItem.z, + registryItem.isolationRate)); } - WarpDrive.logger.info("- " + entryDimension.getValue().size() + " entries in dimension " + entryDimension.getKey() + ": " + message); + WarpDrive.logger.info(String.format("- %d entries in dimension %d: %s", + entryDimension.getValue().size(), entryDimension.getKey(), message.toString())); } } @@ -443,4 +449,54 @@ public class StarMapRegistry { LocalProfiler.stop(); } + + public void readFromNBT(NBTTagCompound tagCompound) { + if (tagCompound == null || !tagCompound.hasKey("starMapRegistryItems")) { + registry.clear(); + return; + } + + // read all entries in a flat structure + final NBTTagList tagList = tagCompound.getTagList("starMapRegistryItems", Constants.NBT.TAG_COMPOUND); + final StarMapRegistryItem[] registryFlat = new StarMapRegistryItem[tagList.tagCount()]; + final HashMap sizeDimensions = new HashMap<>(); + for(int index = 0; index < tagList.tagCount(); index++) { + final StarMapRegistryItem starMapRegistryItem = new StarMapRegistryItem(tagList.getCompoundTagAt(index)); + registryFlat[index] = starMapRegistryItem; + + // update stats + Integer count = sizeDimensions.computeIfAbsent(starMapRegistryItem.dimensionId, k -> (Integer) 0); + count++; + sizeDimensions.put(starMapRegistryItem.dimensionId, count); + } + + // pre-build the local collections using known stats to avoid re-allocations + final HashMap> registryLocal = new HashMap<>(); + for(Entry entryDimension : sizeDimensions.entrySet()) { + registryLocal.put(entryDimension.getKey(), new ArrayList<>(entryDimension.getValue())); + } + + // fill the local collections + for(StarMapRegistryItem starMapRegistryItem : registryFlat) { + registryLocal.get(starMapRegistryItem.dimensionId).add(starMapRegistryItem); + } + + // transfer to main one + registry.clear(); + for(Entry> entry : registryLocal.entrySet()) { + registry.put(entry.getKey(), new CopyOnWriteArraySet<>(entry.getValue())); + } + } + + public void writeToNBT(final NBTTagCompound tagCompound) { + final NBTTagList tagList = new NBTTagList(); + for(CopyOnWriteArraySet starMapRegistryItems : registry.values()) { + for(StarMapRegistryItem starMapRegistryItem : starMapRegistryItems) { + final NBTTagCompound tagCompoundItem = new NBTTagCompound(); + starMapRegistryItem.writeToNBT(tagCompoundItem); + tagList.appendTag(tagCompoundItem); + } + } + tagCompound.setTag("starMapRegistryItems", tagList); + } } diff --git a/src/main/java/cr0s/warpdrive/data/StarMapRegistryItem.java b/src/main/java/cr0s/warpdrive/data/StarMapRegistryItem.java index 5fcbc91f..dbb18792 100644 --- a/src/main/java/cr0s/warpdrive/data/StarMapRegistryItem.java +++ b/src/main/java/cr0s/warpdrive/data/StarMapRegistryItem.java @@ -6,6 +6,7 @@ import cr0s.warpdrive.api.IStarMapRegistryTileEntity; import java.util.HashMap; import java.util.UUID; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; @@ -140,6 +141,47 @@ public class StarMapRegistryItem extends GlobalPosition { return minX <= x && x <= maxX && minY <= y && y <= maxY && minZ <= z && z <= maxZ; } + + public StarMapRegistryItem(final NBTTagCompound tagCompound) { + super(tagCompound); + type = EnumStarMapEntryType.getByName(tagCompound.getString("type")); + UUID uuidLocal = new UUID(tagCompound.getLong("uuidMost"), tagCompound.getLong("uuidLeast")); + if (uuidLocal.getMostSignificantBits() == 0 && uuidLocal.getLeastSignificantBits() == 0) { + uuidLocal = UUID.randomUUID(); + } + uuid = uuidLocal; + maxX = tagCompound.getInteger("maxX"); + maxY = tagCompound.getInteger("maxY"); + maxZ = tagCompound.getInteger("maxZ"); + minX = tagCompound.getInteger("minX"); + minY = tagCompound.getInteger("minY"); + minZ = tagCompound.getInteger("minZ"); + mass = tagCompound.getInteger("mass"); + isolationRate = tagCompound.getDouble("isolationRate"); + name = tagCompound.getString("name"); + } + + @Override + public void writeToNBT(final NBTTagCompound tagCompound) { + super.writeToNBT(tagCompound); + tagCompound.setString("type", type.getName()); + if (uuid != null) { + tagCompound.setLong("uuidMost", uuid.getMostSignificantBits()); + tagCompound.setLong("uuidLeast", uuid.getLeastSignificantBits()); + } + tagCompound.setInteger("maxX", maxX); + tagCompound.setInteger("maxY", maxY); + tagCompound.setInteger("maxZ", maxZ); + tagCompound.setInteger("minX", minX); + tagCompound.setInteger("minY", minY); + tagCompound.setInteger("minZ", minZ); + tagCompound.setInteger("mass", mass); + tagCompound.setDouble("isolationRate", isolationRate); + if (name != null && !name.isEmpty()) { + tagCompound.setString("name", name); + } + } + @Override public int hashCode() { return dimensionId << 24 + (x >> 10) << 12 + y << 10 + (z >> 10); diff --git a/src/main/java/cr0s/warpdrive/event/ChunkHandler.java b/src/main/java/cr0s/warpdrive/event/ChunkHandler.java index cc0e776e..464d84e4 100644 --- a/src/main/java/cr0s/warpdrive/event/ChunkHandler.java +++ b/src/main/java/cr0s/warpdrive/event/ChunkHandler.java @@ -1,5 +1,6 @@ package cr0s.warpdrive.event; +import cr0s.warpdrive.Commons; import cr0s.warpdrive.WarpDrive; import cr0s.warpdrive.config.WarpDriveConfig; import cr0s.warpdrive.data.ChunkData; @@ -37,10 +38,14 @@ public class ChunkHandler { return; } if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { - WarpDrive.logger.info(String.format("World %s load", + WarpDrive.logger.info(String.format("World %s load.", event.world.provider.getDimensionName())); } - // @TODO load star map + + // load star map + final String filename = String.format("%s/%s.dat", event.world.getSaveHandler().getWorldDirectory().getPath(), WarpDrive.MODID); + final NBTTagCompound tagCompound = Commons.readNBTFromFile(filename); + WarpDrive.starMap.readFromNBT(tagCompound); } // (server side only) @@ -52,7 +57,7 @@ public class ChunkHandler { event.getChunk().getChunkCoordIntPair())); } - ChunkData chunkData = getChunkData(event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); + final ChunkData chunkData = getChunkData(event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); chunkData.load(event.getData()); } @@ -66,7 +71,7 @@ public class ChunkHandler { event.getChunk().getChunkCoordIntPair())); } - ChunkData chunkData = getChunkData(event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); + final ChunkData chunkData = getChunkData(event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); chunkData.load(new NBTTagCompound()); } } @@ -91,7 +96,7 @@ public class ChunkHandler { event.world.provider.getDimensionName(), event.getChunk().getChunkCoordIntPair())); } - ChunkData chunkData = getChunkData(event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); + final ChunkData chunkData = getChunkData(event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); chunkData.save(event.getData()); } @@ -102,10 +107,15 @@ public class ChunkHandler { return; } if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { - WarpDrive.logger.info(String.format("World %s saved", + WarpDrive.logger.info(String.format("World %s saved.", event.world.provider.getDimensionName())); } - // @TODO save star map + + // save star map + final String filename = String.format("%s/%s.dat", event.world.getSaveHandler().getWorldDirectory().getPath(), WarpDrive.MODID); + final NBTTagCompound tagCompound = new NBTTagCompound(); + WarpDrive.starMap.writeToNBT(tagCompound); + Commons.writeNBTToFile(filename, tagCompound); } @SubscribeEvent @@ -116,7 +126,7 @@ public class ChunkHandler { } // get dimension data - Map mapRegistryItems = registry.get(event.world.provider.dimensionId); + final Map mapRegistryItems = registry.get(event.world.provider.dimensionId); if (mapRegistryItems != null) { // unload chunks during shutdown for (ChunkData chunkData : mapRegistryItems.values()) { @@ -129,6 +139,7 @@ public class ChunkHandler { if (event.world.isRemote || event.world.provider.dimensionId != 0) { return; } + // @TODO unload star map } @@ -248,7 +259,7 @@ public class ChunkHandler { return true; } chunkData.updateTick(world); - ChunkCoordIntPair chunkCoordIntPair = chunkData.getChunkCoords(); + final ChunkCoordIntPair chunkCoordIntPair = chunkData.getChunkCoords(); // skip chunks with unloaded neighbours if ( isLoaded(mapRegistryItems, chunkCoordIntPair.chunkXPos + 1, chunkCoordIntPair.chunkZPos) && isLoaded(mapRegistryItems, chunkCoordIntPair.chunkXPos - 1, chunkCoordIntPair.chunkZPos)