diff --git a/src/main/java/noppes/npcs/NoppesUtilServer.java b/src/main/java/noppes/npcs/NoppesUtilServer.java index 76f552ba0..cced40865 100644 --- a/src/main/java/noppes/npcs/NoppesUtilServer.java +++ b/src/main/java/noppes/npcs/NoppesUtilServer.java @@ -475,6 +475,7 @@ public class NoppesUtilServer { } else { PlayerDataController.instance.nameUUIDs.remove(name); + PlayerDataController.instance.savePlayerDataMap(); } } if(type == EnumPlayerData.Quest){ @@ -506,6 +507,10 @@ public class NoppesUtilServer { } sendPlayerData(type, player, name); } + + public static void regenPlayerData(EntityPlayerMP player) throws IOException { + PlayerDataController.instance.generatePlayerMap(player); + } public static void sendRecipeData(EntityPlayerMP player, int size) { HashMap map = new HashMap(); diff --git a/src/main/java/noppes/npcs/PacketHandlerServer.java b/src/main/java/noppes/npcs/PacketHandlerServer.java index 13376a8f1..db0ffe5c5 100644 --- a/src/main/java/noppes/npcs/PacketHandlerServer.java +++ b/src/main/java/noppes/npcs/PacketHandlerServer.java @@ -794,6 +794,9 @@ public class PacketHandlerServer{ else if(type == EnumPacketServer.PlayerDataRemove){ NoppesUtilServer.removePlayerData(buffer,player); } + else if(type == EnumPacketServer.PlayerDataRegen){ + NoppesUtilServer.regenPlayerData(player); + } else if(type == EnumPacketServer.MainmenuDisplayGet){ Server.sendData(player, EnumPacketClient.GUI_DATA, npc.display.writeToNBT(new NBTTagCompound())); } diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiNpcManagePlayerData.java b/src/main/java/noppes/npcs/client/gui/global/GuiNpcManagePlayerData.java index 1be624891..e4a4b69b6 100644 --- a/src/main/java/noppes/npcs/client/gui/global/GuiNpcManagePlayerData.java +++ b/src/main/java/noppes/npcs/client/gui/global/GuiNpcManagePlayerData.java @@ -1,7 +1,12 @@ package noppes.npcs.client.gui.global; import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiYesNo; +import net.minecraft.client.gui.GuiYesNoCallback; +import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.client.Client; +import noppes.npcs.client.NoppesUtil; +import noppes.npcs.client.controllers.ClientCloneController; import noppes.npcs.client.gui.util.*; import noppes.npcs.constants.EnumPacketServer; import noppes.npcs.constants.EnumPlayerData; @@ -12,7 +17,7 @@ import java.util.HashMap; import java.util.List; import java.util.Vector; -public class GuiNpcManagePlayerData extends GuiNPCInterface2 implements IScrollData,ICustomScrollListener +public class GuiNpcManagePlayerData extends GuiNPCInterface2 implements IScrollData,ICustomScrollListener,GuiYesNoCallback { private GuiCustomScroll scroll; private String selectedPlayer = null; @@ -45,7 +50,9 @@ public class GuiNpcManagePlayerData extends GuiNPCInterface2 implements IScrollD this.addButton(new GuiNpcButton(4, guiLeft + 200, guiTop + 98,98, 20, "Transport Data")); this.addButton(new GuiNpcButton(5, guiLeft + 200, guiTop + 120,98, 20, "Bank Data")); this.addButton(new GuiNpcButton(6, guiLeft + 200, guiTop + 142,98, 20, "Faction Data")); - + + this.addButton(new GuiNpcButton(7, guiLeft + 200, guiTop + 193,98, 20, "Regen PlayerMap")); + addTextField(new GuiNpcTextField(0, this, fontRendererObj, guiLeft + 4, guiTop + 193, 190, 20, search)); getTextField(0).enabled = selection == EnumPlayerData.Players; @@ -126,6 +133,9 @@ public class GuiNpcManagePlayerData extends GuiNPCInterface2 implements IScrollD Client.sendData(EnumPacketServer.PlayerDataGet, selection, selectedPlayer); selected = null; } + if(id == 7){ + displayGuiScreen(new GuiYesNo(this, "Warning", "Do not operate on PlayerData as its regenerating", 1)); + } } @Override @@ -155,5 +165,14 @@ public class GuiNpcManagePlayerData extends GuiNPCInterface2 implements IScrollD selectedPlayer = selected; } + @Override + public void confirmClicked(boolean confirm, int id){ + if(confirm){ + Client.sendData(EnumPacketServer.PlayerDataRegen); + close(); + } + else + displayGuiScreen(this); + } } diff --git a/src/main/java/noppes/npcs/constants/EnumPacketServer.java b/src/main/java/noppes/npcs/constants/EnumPacketServer.java index 036ee6b14..48e77d218 100644 --- a/src/main/java/noppes/npcs/constants/EnumPacketServer.java +++ b/src/main/java/noppes/npcs/constants/EnumPacketServer.java @@ -53,7 +53,7 @@ public enum EnumPacketServer { LinkedGetAll, LinkedRemove(CustomNpcsPermissions.GLOBAL_LINKED), LinkedAdd(CustomNpcsPermissions.GLOBAL_LINKED), ScriptDataSave(CustomNpcsPermissions.TOOL_SCRIPTER, true), ScriptDataGet(true), EventScriptDataSave(CustomNpcsPermissions.TOOL_SCRIPTER, true), EventScriptDataGet(true), - PlayerDataRemove(CustomNpcsPermissions.GLOBAL_PLAYERDATA), + PlayerDataRemove(CustomNpcsPermissions.GLOBAL_PLAYERDATA), PlayerDataRegen(CustomNpcsPermissions.GLOBAL_PLAYERDATA), BankSave(CustomNpcsPermissions.GLOBAL_BANK), BanksGet, BankGet, BankRemove(CustomNpcsPermissions.GLOBAL_BANK), DialogCategorySave(CustomNpcsPermissions.GLOBAL_DIALOG), DialogCategoriesGet, DialogsGetFromDialog, diff --git a/src/main/java/noppes/npcs/controllers/PlayerDataController.java b/src/main/java/noppes/npcs/controllers/PlayerDataController.java index 6e5c712f0..db9b24d29 100644 --- a/src/main/java/noppes/npcs/controllers/PlayerDataController.java +++ b/src/main/java/noppes/npcs/controllers/PlayerDataController.java @@ -6,50 +6,189 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; import noppes.npcs.CustomNpcs; import noppes.npcs.LogWriter; -import noppes.npcs.controllers.data.Bank; -import noppes.npcs.controllers.data.PlayerBankData; -import noppes.npcs.controllers.data.PlayerData; -import noppes.npcs.controllers.data.PlayerMail; +import noppes.npcs.controllers.data.*; import noppes.npcs.util.NBTJsonUtil; -import java.io.File; -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.io.*; +import java.util.*; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.zip.GZIPInputStream; public class PlayerDataController { public static PlayerDataController instance; - public Map nameUUIDs; + public HashMap nameUUIDs; + private static final Executor playerDataThread = Executors.newSingleThreadExecutor(); public PlayerDataController(){ instance = this; File dir = getSaveDir(); - if(dir != null){ - Map map = new HashMap(); - if(dir.listFiles() != null){ - for(File file : dir.listFiles()){ - if(file.isDirectory() || !file.getName().endsWith(".json")) - continue; - try { - NBTTagCompound compound = NBTJsonUtil.LoadFile(file); - if(compound.hasKey("PlayerName")){ - map.put(compound.getString("PlayerName"), file.getName().substring(0, file.getName().length() - 5)); + + LogWriter.info("Loading PlayerData..."); + // If no PlayerData MAP - Load PlayerData to create PlayerData Map + if(!getPlayerDataMap()){ + LogWriter.info("Generating PlayerData map file..."); + File[] files = dir.listFiles(); // Get an array of all files in the directory + HashMap map = new HashMap(); + if(files != null){ + int length = files.length; + if(length != 0){ + if(length > 100){ + LogWriter.info("Found " + length + " PlayerData files... This may take a few minutes"); + } + int tenPercent = (int) ((double) length * 0.1); + int progress = 0; + // Load the files in parallel using a stream + for(int i = 0; i < length; i++){ + File file = files[i]; + if(file.isDirectory() || !file.getName().endsWith(".json")) + continue; + try { + NBTTagCompound compound = NBTJsonUtil.LoadFile(file); + if(compound.hasKey("PlayerName")){ + map.put(compound.getString("PlayerName"), file.getName().substring(0, file.getName().length() - 5)); + } + } catch (Exception e) { + LogWriter.error("Error loading: " + file.getAbsolutePath(), e); + } + if(tenPercent != 0 ){ + if(progress != 100){ + if (i % tenPercent == 0) { + progress += 10; + LogWriter.info("Creating PlayerMap: Progress: " + progress + "%"); + } + } } - } catch (Exception e) { - LogWriter.error("Error loading: " + file.getAbsolutePath(), e); } } - nameUUIDs = map; } + nameUUIDs = map; + savePlayerDataMap(); + } + + LogWriter.info("Done loading PlayerData"); + } + + public void generatePlayerMap(EntityPlayerMP sender){ + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.execute(() -> { + if(sender != null){ + LogWriter.info("PlayerMap regeneration queued by " + sender.getCommandSenderName()); + sender.addChatMessage(new ChatComponentText("You have initiated PlayerMap regeneration")); + } + nameUUIDs.clear(); + + File dir = getSaveDir(); + LogWriter.info("Generating PlayerData map file..."); + File[] files = dir.listFiles(); // Get an array of all files in the directory + HashMap map = new HashMap(); + if(files != null){ + int length = files.length; + if(length != 0){ + if(length > 100){ + LogWriter.info("Found " + length + " PlayerData files... This may take a few minutes"); + } + int tenPercent = (int) ((double) length * 0.1); + int progress = 0; + // Load the files in parallel using a stream + for(int i = 0; i < length; i++){ + File file = files[i]; + if(file.isDirectory() || !file.getName().endsWith(".json")) + continue; + try { + NBTTagCompound compound = NBTJsonUtil.LoadFile(file); + if(compound.hasKey("PlayerName")){ + map.put(compound.getString("PlayerName"), file.getName().substring(0, file.getName().length() - 5)); + } + } catch (Exception e) { + LogWriter.error("Error loading: " + file.getAbsolutePath(), e); + } + if(tenPercent != 0 ){ + if(progress != 100){ + if (i % tenPercent == 0) { + progress += 10; + LogWriter.info("Creating PlayerMap: Progress: " + progress + "%"); + } + } + } + } + } + } + nameUUIDs = map; + savePlayerDataMap(); + + if(sender != null){ + sender.addChatMessage(new ChatComponentText("PlayerMap regeneration complete")); + } + }); + + executor.shutdown(); + } + + public boolean getPlayerDataMap(){ + try { + File file = new File(getSaveDir(), "___playermap.dat"); + if(file.exists()){ + loadPlayerDataMap(file); + return true; + } + } catch (Exception e) { + try { + File file = new File(getSaveDir(), "___playermap.dat_old"); + if(file.exists()){ + loadPlayerDataMap(file); + return true; + } + } catch (Exception ignored) {} + } + return false; + } + + private void loadPlayerDataMap(File file) throws IOException { + DataInputStream var1 = new DataInputStream(new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))); + loadPlayerDatasMap(var1); + var1.close(); + } + + + public void loadPlayerDatasMap(DataInputStream stream) throws IOException{ + NBTTagCompound nbttagcompound = CompressedStreamTools.read(stream); + readNBT(nbttagcompound); + } + + public void savePlayerDataMap(){ + try { + File saveDir = getSaveDir(); + File file = new File(saveDir, "___playermap.dat_new"); + File file1 = new File(saveDir, "___playermap.dat_old"); + File file2 = new File(saveDir, "___playermap.dat"); + CompressedStreamTools.writeCompressed(writeNBT(), new FileOutputStream(file)); + if(file1.exists()) + { + file1.delete(); + } + file2.renameTo(file1); + if(file2.exists()) + { + file2.delete(); + } + file.renameTo(file2); + if(file.exists()) + { + file.delete(); + } + } catch (Exception e) { + LogWriter.except(e); } } + public File getSaveDir(){ try{ File file = new File(CustomNpcs.getWorldSaveDirectory(),"playerdata"); @@ -113,10 +252,9 @@ public class PlayerDataController { return new NBTTagCompound(); } - private static Executor executor = Executors.newSingleThreadExecutor(); public void savePlayerData(PlayerData data){ NBTTagCompound compound = data.getNBT(); - executor.execute(() -> { + playerDataThread.execute(() -> { String filename = data.uuid + ".json"; try { File saveDir = getSaveDir(); @@ -130,6 +268,9 @@ public class PlayerDataController { } catch (Exception e) { LogWriter.except(e); } + + nameUUIDs.put(data.playername, data.uuid); + savePlayerDataMap(); }); } @@ -208,4 +349,31 @@ public class PlayerDataController { public boolean hasMail(EntityPlayer player) { return getPlayerData(player).mailData.hasMail(); } + public void readNBT(NBTTagCompound compound){ + this.nameUUIDs = new HashMap(); + NBTTagList list = compound.getTagList("PlayerDataMap", 10); + if(list != null){ + for(int i = 0; i < list.tagCount(); i++) + { + NBTTagCompound nbttagcompound = list.getCompoundTagAt(i); + String playerName = nbttagcompound.getString("Name"); + String uuid = nbttagcompound.getString("UUID"); + nameUUIDs.put(playerName, uuid); + } + } + } + + public NBTTagCompound writeNBT(){ + NBTTagCompound nbt = new NBTTagCompound(); + NBTTagList playerList = new NBTTagList(); + for(String key: nameUUIDs.keySet()){ + NBTTagCompound playerCompound = new NBTTagCompound(); + playerCompound.setString("Name", key); + playerCompound.setString("UUID", nameUUIDs.get(key)); + playerList.appendTag(playerCompound); + + } + nbt.setTag("PlayerDataMap", playerList); + return nbt; + } } \ No newline at end of file