package net.glowstone.io.nbt;
import net.glowstone.GlowChunk;
import net.glowstone.GlowServer;
import net.glowstone.GlowWorld;
import net.glowstone.generator.structures.GlowStructure;
import net.glowstone.io.StructureDataService;
import net.glowstone.io.structure.StructureStorage;
import net.glowstone.io.structure.StructureStore;
import net.glowstone.util.nbt.CompoundTag;
import net.glowstone.util.nbt.NBTInputStream;
import net.glowstone.util.nbt.NBTOutputStream;
import org.bukkit.Bukkit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
public class NbtStructureDataService implements StructureDataService {
private final GlowWorld world;
private final File structureDir;
private final GlowServer server;
public NbtStructureDataService(GlowWorld world, File structureDir) {
this.world = world;
this.structureDir = structureDir;
server = (GlowServer) Bukkit.getServer();
if (!structureDir.isDirectory() && !structureDir.mkdirs()) {
server.getLogger().warning("Failed to create directory: " + structureDir);
}
}
@Override
public Map<Integer, GlowStructure> readStructuresData() throws IOException {
final Map<Integer, GlowStructure> structures = new HashMap<>();
for (StructureStore<?> store : StructureStorage.getStructureStores()) {
File structureFile = new File(structureDir, store.getId() + ".dat");
if (structureFile.exists()) {
try (NBTInputStream in = new NBTInputStream(new FileInputStream(structureFile))) {
CompoundTag data = new CompoundTag();
data = in.readCompound();
if (data.isCompound("data")) {
data = data.getCompound("data");
if (data.isCompound("Features")) {
CompoundTag features = data.getCompound("Features");
for (String key : features.getValue().keySet()) {
if (features.isCompound(key)) {
GlowStructure structure = StructureStorage.loadStructure(world, features.getCompound(key));
structures.put(new GlowChunk.Key(structure.getChunkX(), structure.getChunkZ()).hashCode(), structure);
}
}
}
} else {
server.getLogger().log(Level.SEVERE, "No data tag in " + structureFile);
}
} catch (IOException e) {
server.getLogger().log(Level.SEVERE, "Failed to read structure data from " + structureFile, e);
}
}
}
return structures;
}
@Override
public void writeStructuresData(Map<Integer, GlowStructure> structures) throws IOException {
for (GlowStructure structure : structures.values()) {
if (structure.isDirty()) {
CompoundTag root = new CompoundTag();
CompoundTag data = new CompoundTag();
CompoundTag features = new CompoundTag();
CompoundTag feature = new CompoundTag();
StructureStore<GlowStructure> store = StructureStorage.saveStructure(structure, feature);
File structureFile = new File(structureDir, store.getId() + ".dat");
if (structureFile.exists()) {
try (NBTInputStream in = new NBTInputStream(new FileInputStream(structureFile))) {
data = new CompoundTag();
data = in.readCompound();
if (data.isCompound("data")) {
data = data.getCompound("data");
if (data.isCompound("Features")) {
features = data.getCompound("Features");
}
}
} catch (IOException e) {
server.getLogger().log(Level.SEVERE, "Failed to read structure data from " + structureFile, e);
}
}
final String key = "[" + structure.getChunkX() + "," + structure.getChunkZ() + "]";
features.putCompound(key, feature);
data.putCompound("Features", features);
root.putCompound("data", data);
try (NBTOutputStream nbtOut = new NBTOutputStream(new FileOutputStream(structureFile))) {
nbtOut.writeTag(root);
} catch (IOException e) {
server.getLogger().log(Level.SEVERE, "Failed to write structure data to " + structureFile, e);
}
structure.setDirty(false);
}
}
}
}