package codechicken.enderstorage.api; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import codechicken.lib.config.ConfigFile; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.event.world.WorldEvent.Load; import net.minecraftforge.event.world.WorldEvent.Save; public class EnderStorageManager { public static class EnderStorageSaveHandler { @SubscribeEvent public void onWorldLoad(Load event) { if (event.world.isRemote) reloadManager(true); } @SubscribeEvent public void onWorldSave(Save event) { if (!event.world.isRemote && instance(false) != null) instance(false).save(false); } @SubscribeEvent public void onPlayerLogin(PlayerLoggedInEvent event) { instance(false).sendClientInfo(event.player); } @SubscribeEvent public void onPlayerChangedDimension(PlayerLoggedOutEvent event) { instance(false).sendClientInfo(event.player); } } private static EnderStorageManager serverManager; private static EnderStorageManager clientManager; private static ConfigFile config; private static HashMap<String, EnderStoragePlugin> plugins = new HashMap<String, EnderStoragePlugin>(); private Map<String, AbstractEnderStorage> storageMap; private Map<String, List<AbstractEnderStorage>> storageList; public final boolean client; private File saveDir; private File[] saveFiles; private int saveTo; private List<AbstractEnderStorage> dirtyStorage; private NBTTagCompound saveTag; public EnderStorageManager(boolean client) { this.client = client; storageMap = Collections.synchronizedMap(new HashMap<String, AbstractEnderStorage>()); storageList = Collections.synchronizedMap(new HashMap<String, List<AbstractEnderStorage>>()); dirtyStorage = Collections.synchronizedList(new LinkedList<AbstractEnderStorage>()); for (String key : plugins.keySet()) storageList.put(key, new ArrayList<AbstractEnderStorage>()); if (!client) load(); } private void sendClientInfo(EntityPlayer player) { for (Entry<String, EnderStoragePlugin> plugin : plugins.entrySet()) plugin.getValue().sendClientInfo(player, storageList.get(plugin.getKey())); } private void load() { saveDir = new File(DimensionManager.getCurrentSaveRootDirectory(), "EnderStorage"); try { if (!saveDir.exists()) saveDir.mkdirs(); saveFiles = new File[]{new File(saveDir, "data1.dat"), new File(saveDir, "data2.dat"), new File(saveDir, "lock.dat")}; if (saveFiles[2].exists() && saveFiles[2].length() > 0) { FileInputStream fin = new FileInputStream(saveFiles[2]); saveTo = fin.read() ^ 1; fin.close(); if (saveFiles[saveTo ^ 1].exists()) { FileInputStream in = new FileInputStream(saveFiles[saveTo ^ 1]); saveTag = CompressedStreamTools.readCompressed(in); in.close(); } else { saveTag = new NBTTagCompound(); } } else saveTag = new NBTTagCompound(); } catch (Exception e) { throw new RuntimeException(e); } } private void save(boolean force) { if (!dirtyStorage.isEmpty() || force) { for (AbstractEnderStorage inv : dirtyStorage) { saveTag.setTag(inv.freq + "|" + inv.owner + "|" + inv.type(), inv.saveToTag()); inv.setClean(); } dirtyStorage.clear(); try { File saveFile = saveFiles[saveTo]; if (!saveFile.exists()) saveFile.createNewFile(); DataOutputStream dout = new DataOutputStream(new FileOutputStream(saveFile)); CompressedStreamTools.writeCompressed(saveTag, dout); dout.close(); FileOutputStream fout = new FileOutputStream(saveFiles[2]); fout.write(saveTo); fout.close(); saveTo ^= 1; } catch (Exception e) { throw new RuntimeException(e); } } } public static void reloadManager(boolean client) { EnderStorageManager newManager = new EnderStorageManager(client); if (client) clientManager = newManager; else serverManager = newManager; } public File getSaveDir() { return saveDir; } public static EnderStorageManager instance(boolean client) { return client ? clientManager : serverManager; } public AbstractEnderStorage getStorage(String owner, int freq, String type) { if (owner == null) owner = "global"; String key = freq + "|" + owner + "|" + type; AbstractEnderStorage storage = storageMap.get(key); if (storage == null) { storage = plugins.get(type).createEnderStorage(this, owner, freq); if (!client && saveTag.hasKey(key)) storage.loadFromTag(saveTag.getCompoundTag(key)); storageMap.put(key, storage); storageList.get(type).add(storage); } return storage; } public static int getFreqFromColours(int colour1, int colour2, int colour3) { return ((colour1 & 0xF) << 8) + ((colour2 & 0xF) << 4) + (colour3 & 0xF); } public static int getFreqFromColours(int[] colours) { return ((colours[0] & 0xF) << 8) + ((colours[1] & 0xF) << 4) + (colours[2] & 0xF); } public static int getColourFromFreq(int freq, int colour) { switch (colour) { case 0: return freq >> 8 & 0xF; case 1: return freq >> 4 & 0xF; case 2: return freq & 0xF; } return 0; } public static int[] getColoursFromFreq(int freq) { int[] ai = new int[3]; ai[0] = (freq >> 8) & 0xF; ai[1] = (freq >> 4) & 0xF; ai[2] = freq & 0xF; return ai; } public static void loadConfig(ConfigFile config2) { config = config2; for (Entry<String, EnderStoragePlugin> plugin : plugins.entrySet()) plugin.getValue().loadConfig(config.getTag(plugin.getKey())); } public static void registerPlugin(EnderStoragePlugin plugin) { plugins.put(plugin.identifer(), plugin); if (config != null) plugin.loadConfig(config.getTag(plugin.identifer())); if (serverManager != null) serverManager.storageList.put(plugin.identifer(), new ArrayList<AbstractEnderStorage>()); if (clientManager != null) clientManager.storageList.put(plugin.identifer(), new ArrayList<AbstractEnderStorage>()); } public void requestSave(AbstractEnderStorage storage) { dirtyStorage.add(storage); } }