From 3e487739403f8206fb31817e2507b7e478df50c2 Mon Sep 17 00:00:00 2001 From: Kam Date: Tue, 20 Feb 2024 02:07:38 -0500 Subject: [PATCH] Convert Market to Dat File Command / Config Support Faster Loading Speeds for LARGE Markets --- src/main/java/foxz/utils/Market.java | 212 +++++++++++++++--- .../java/kamkeel/command/ConfigCommand.java | 63 +++++- .../java/noppes/npcs/PacketHandlerServer.java | 1 - .../java/noppes/npcs/config/ConfigMain.java | 9 +- .../controllers/PlayerDataController.java | 2 +- 5 files changed, 248 insertions(+), 39 deletions(-) diff --git a/src/main/java/foxz/utils/Market.java b/src/main/java/foxz/utils/Market.java index 737ab02fc..79e05ed1e 100644 --- a/src/main/java/foxz/utils/Market.java +++ b/src/main/java/foxz/utils/Market.java @@ -1,58 +1,214 @@ package foxz.utils; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ChatComponentText; import noppes.npcs.CustomNpcs; +import noppes.npcs.LogWriter; +import noppes.npcs.config.ConfigMain; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.roles.RoleTrader; import noppes.npcs.util.NBTJsonUtil; import java.io.File; +import java.io.FileOutputStream; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static noppes.npcs.controllers.PlayerDataController.loadNBTData; public class Market { static public void save(RoleTrader r, String name) { - if(name.isEmpty()) - return; - File file = getFile(name + "_new"); - File file1 = getFile(name); + if(name.isEmpty()) + return; + File file = getFile(name + "_new"); + File file1 = getFile(name); try { - NBTJsonUtil.SaveFile(file, r.writeNBT(new NBTTagCompound())); - if(file1.exists()){ - file1.delete(); - } - file.renameTo(file1); - } catch (Exception e) { + if(ConfigMain.MarketDatFormat){ + CompressedStreamTools.writeCompressed(r.writeNBT(new NBTTagCompound()), new FileOutputStream(file)); + } else { + NBTJsonUtil.SaveFile(file, r.writeNBT(new NBTTagCompound())); + } + if(file1.exists()){ + file1.delete(); + } + file.renameTo(file1); + } catch (Exception e) { - } + } } static public void load(RoleTrader role, String name){ - if(role.npc.worldObj.isRemote) - return; - File file = getFile(name); - if(!file.exists()) - return; + if(role.npc.worldObj.isRemote) + return; + File file = getFile(name); + if(!file.exists()) + return; - try { - role.readNBT(NBTJsonUtil.LoadFile(file)); - } catch (Exception e) { - } + try { + if(ConfigMain.MarketDatFormat){ + NBTTagCompound compound = loadNBTData(file); + role.readNBT(compound); + } + else { + role.readNBT(NBTJsonUtil.LoadFile(file)); + } + } catch (Exception e) { + } } + + public static File getMarketDir(){ + try{ + File file = new File(CustomNpcs.getWorldSaveDirectory(),"markets"); + if(!file.exists()) + file.mkdir(); + return file; + } + catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public File getNewMarketDir(){ + try{ + File file = new File(CustomNpcs.getWorldSaveDirectory(),"markets_new"); + if(file.exists()){ + return null; + } + file.mkdir(); + return file; + } + catch (Exception e) { + e.printStackTrace(); + return null; + } + } + private static File getFile(String name){ - File dir = new File(CustomNpcs.getWorldSaveDirectory(), "markets"); - if(!dir.exists()) - dir.mkdir(); - return new File(dir, name.toLowerCase() + ".json"); + String filename = name.toLowerCase(); + if(ConfigMain.MarketDatFormat){ + filename += ".dat"; + } else { + filename += ".json"; + } + + return new File(getMarketDir(), filename); } static public void setMarket(EntityNPCInterface npc, String marketName) { - if(marketName.isEmpty()) - return; - if(!getFile(marketName).exists()) - Market.save((RoleTrader) npc.roleInterface, marketName); + if(marketName.isEmpty()) + return; + if(!getFile(marketName).exists()) + Market.save((RoleTrader) npc.roleInterface, marketName); Market.load((RoleTrader) npc.roleInterface, marketName); } + + + public void convertMarketFiles(final EntityPlayerMP sender, final boolean type){ + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.execute(() -> { + String fileType; + if(type){ + fileType = ".dat"; + } + else { + fileType = ".json"; + } + + if(sender != null){ + LogWriter.info("Market Conversion queued by " + sender.getCommandSenderName()); + sender.addChatMessage(new ChatComponentText("Market Conversion to " + fileType + " format")); + } + + File dir = getMarketDir(); + LogWriter.info("Converting Market to " + fileType + " format"); + File[] files = dir.listFiles(); // Get an array of all files in the directory + if(files != null){ + int length = files.length; + if(length != 0){ + if(length > 100){ + LogWriter.info("Found " + length + " Market files... This may take a few minutes"); + } + int tenPercent = (int) ((double) length * 0.1); + int progress = 0; + File saveDir = getNewMarketDir(); + if(saveDir == null){ + if(sender != null){ + sender.addChatMessage(new ChatComponentText("markets_new folder already exists please delete it or rename it")); + } + LogWriter.error("markets_new folder already exists please delete it or rename it"); + return; + } + // 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") && !file.getName().endsWith(".dat"))) + continue; + try { + String filename = "error"; + boolean valid = false; + NBTTagCompound compound = new NBTTagCompound(); + if(type){ + if(file.getName().endsWith(".json")){ + compound = NBTJsonUtil.LoadFile(file); + if(compound.hasKey("PlayerName")) { + filename = file.getName().substring(0, file.getName().length() - 5); + valid = true; + } + } + } else { + if(file.getName().endsWith(".dat")){ + compound = loadNBTData(file); + if(compound.hasKey("PlayerName")){ + filename = file.getName().substring(0, file.getName().length() - 4); + valid = true; + } + } + } + if(valid){ + try { + File newFile = new File(saveDir, filename + "_new" + fileType); + File oldFile = new File(saveDir, filename + fileType); + if(type){ + CompressedStreamTools.writeCompressed(compound, new FileOutputStream(newFile)); + } else { + NBTJsonUtil.SaveFile(newFile, compound); + } + if(oldFile.exists()){ + oldFile.delete(); + } + newFile.renameTo(oldFile); + } catch (Exception e) { + LogWriter.except(e); + } + } + } catch (Exception e) { + LogWriter.error("Error loading: " + file.getAbsolutePath(), e); + } + if(tenPercent != 0 ){ + if(progress != 100){ + if (i % tenPercent == 0) { + progress += 10; + LogWriter.info("Converting Market: Progress: " + progress + "%"); + } + } + } + } + } + } + if(sender != null){ + sender.addChatMessage(new ChatComponentText("Market Conversion complete")); + } + LogWriter.info("Market Converted - Please rename the markets_new folder to markets and restart"); + }); + + executor.shutdown(); + } + } diff --git a/src/main/java/kamkeel/command/ConfigCommand.java b/src/main/java/kamkeel/command/ConfigCommand.java index b8d239904..5375afa9b 100644 --- a/src/main/java/kamkeel/command/ConfigCommand.java +++ b/src/main/java/kamkeel/command/ConfigCommand.java @@ -30,7 +30,7 @@ public class ConfigCommand extends CommandKamkeelBase { public String getDescription() { return "Some config things you can set"; } - + @SubCommand( desc = "Disable/Enable the natural leaves decay", usage = "[true/false]", @@ -56,7 +56,7 @@ public class ConfigCommand extends CommandKamkeelBase { sendResult(sender, "LeavesDecay is now \u00A7c" + ConfigMain.LeavesDecayEnabled); } } - + @SubCommand( desc = "Disable/Enable the vines growing", usage = "[true/false]", @@ -82,7 +82,7 @@ public class ConfigCommand extends CommandKamkeelBase { sendResult(sender, "VineGrowth is now \u00A7c" + ConfigMain.VineGrowthEnabled); } } - + @SubCommand( desc = "Disable/Enable the ice melting", usage = "[true/false]", @@ -127,7 +127,7 @@ public class ConfigCommand extends CommandKamkeelBase { sendResult(sender, "GunsEnabled is now \u00A7c" + ConfigMain.GunsEnabled); } } - + @SubCommand( desc = "Freezes/Unfreezes npcs", usage = "[true/false]", @@ -142,7 +142,7 @@ public class ConfigCommand extends CommandKamkeelBase { sendResult(sender, "FrozenNPCs is now \u00A7c" + CustomNpcs.FreezeNPCs); } } - + @SubCommand( desc = "Set number of active chunkloaders", usage = "", @@ -220,7 +220,54 @@ public class ConfigCommand extends CommandKamkeelBase { PlayerDataController.Instance.convertPlayerFiles(send, convertToDat); } } - + + @SubCommand( + desc = "Generate Market to JSON/DAT", + usage = "[fileType] [convert]", + permission = 4 + ) + public void market(ICommandSender sender, String[] args) throws CommandException{ + String fileType; + if(ConfigMain.MarketDatFormat){ + fileType = "DAT"; + } + else { + fileType = "JSON"; + } + if(args.length == 0){ + sendResult(sender, "Market Filetype: \u00A7c" + fileType); + } + else if(args.length == 1){ + sendResult(sender, "Please write the word 'convert' at the end to confirm. \u00A7c convert"); + } + else{ + if(args.length != 2){ + sendError(sender, "Two many arguments"); + return; + } + String formatType = args[0].toLowerCase(); + if(!formatType.equals("dat") && !formatType.equals("json")){ + sendError(sender, "Invalid Format Type - Please use dat or json"); + return; + } + + String convert = args[1].toLowerCase(); + if(!convert.equals("convert")){ + sendError(sender, "Please enter the word 'convert' at the end"); + return; + } + + boolean convertToDat = formatType.equals("dat"); + EntityPlayerMP send = null; + if(sender instanceof EntityPlayerMP){ + send = (EntityPlayerMP) sender; + } + + sendResult(sender, "Started Conversion Process for Market"); + PlayerDataController.Instance.convertPlayerFiles(send, convertToDat); + } + } + @SubCommand( desc = "Get/Set font", usage = "[type] [size]", @@ -236,7 +283,7 @@ public class ConfigCommand extends CommandKamkeelBase { args = Arrays.copyOfRange(args, 0, args.length - 1); } catch(Exception e){ - + } } String font = ""; @@ -245,6 +292,6 @@ public class ConfigCommand extends CommandKamkeelBase { } Server.sendData((EntityPlayerMP)sender, EnumPacketClient.CONFIG, 0, font.trim(), size); } - + } diff --git a/src/main/java/noppes/npcs/PacketHandlerServer.java b/src/main/java/noppes/npcs/PacketHandlerServer.java index 7b922dee2..fad1036f8 100644 --- a/src/main/java/noppes/npcs/PacketHandlerServer.java +++ b/src/main/java/noppes/npcs/PacketHandlerServer.java @@ -1100,7 +1100,6 @@ public class PacketHandlerServer{ Market.setMarket(npc, market); else Market.save((RoleTrader)npc.roleInterface, market); - //NoppesUtilServer.sendRoleData(player, npc); } } else if(type == EnumPacketServer.AnimationsGet){ diff --git a/src/main/java/noppes/npcs/config/ConfigMain.java b/src/main/java/noppes/npcs/config/ConfigMain.java index fc6efcf8d..f7e10f428 100644 --- a/src/main/java/noppes/npcs/config/ConfigMain.java +++ b/src/main/java/noppes/npcs/config/ConfigMain.java @@ -63,6 +63,10 @@ public class ConfigMain public static Property DatFormatProperty; public static boolean DatFormat = false; + public static Property MarketDatFormatProperty; + public static boolean MarketDatFormat = false; + + public static Property DefaultMaxPartySizetProperty; public static int DefaultMaxPartySize = 4; @@ -152,6 +156,9 @@ public class ConfigMain DatFormatProperty = config.get(GENERAL, "Dat Format for PlayerData", false, "You need to use '/kamkeel config playerdata' to convert existing playerdata to new format."); DatFormat = DatFormatProperty.getBoolean(false); + MarketDatFormatProperty = config.get(GENERAL, "Dat Format for Market", false, "You need to use '/kamkeel config market' to convert existing market to new format."); + MarketDatFormat = MarketDatFormatProperty.getBoolean(false); + DefaultMaxPartySizetProperty = config.get(GENERAL, "Default Max Party Size", 4, "When creating a new Quest sets the default max party size"); DefaultMaxPartySize = DefaultMaxPartySizetProperty.getInt(4); @@ -280,4 +287,4 @@ public class ConfigMain } } } -} \ No newline at end of file +} diff --git a/src/main/java/noppes/npcs/controllers/PlayerDataController.java b/src/main/java/noppes/npcs/controllers/PlayerDataController.java index b3a0f3a7f..aaac92b25 100644 --- a/src/main/java/noppes/npcs/controllers/PlayerDataController.java +++ b/src/main/java/noppes/npcs/controllers/PlayerDataController.java @@ -242,7 +242,7 @@ public class PlayerDataController { return new NBTTagCompound(); } - public NBTTagCompound loadNBTData(File file){ + public static NBTTagCompound loadNBTData(File file){ try { return CompressedStreamTools.readCompressed(new FileInputStream(file)); } catch (Exception e) {