package noppes.npcs.controllers; import kamkeel.npcs.controllers.SyncController; import kamkeel.npcs.network.enums.EnumSyncType; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import noppes.npcs.CustomNpcs; import noppes.npcs.LogWriter; import noppes.npcs.NoppesStringUtils; import noppes.npcs.api.handler.IDialogHandler; import noppes.npcs.api.handler.data.IDialog; import noppes.npcs.api.handler.data.IDialogCategory; import noppes.npcs.constants.EnumOptionType; import noppes.npcs.controllers.data.Dialog; import noppes.npcs.controllers.data.DialogCategory; import noppes.npcs.controllers.data.DialogOption; import noppes.npcs.util.NBTJsonUtil; import java.io.File; import java.io.FileInputStream; import java.util.*; public class DialogController implements IDialogHandler { public HashMap categoriesSync = new HashMap(); public HashMap categories = new HashMap(); public HashMap dialogs = new HashMap(); public static DialogController Instance = new DialogController(); ; private int lastUsedDialogID = 0; private int lastUsedCatID = 0; public DialogController() { Instance = this; } public void load() { LogWriter.info("Loading Dialogs"); loadCategories(); LogWriter.info("Done loading Dialogs"); } private void loadCategories() { categories.clear(); dialogs.clear(); lastUsedCatID = 0; lastUsedDialogID = 0; try { File file = new File(CustomNpcs.getWorldSaveDirectory(), "dialog.dat"); if (file.exists()) { loadCategoriesOld(file); file.delete(); file = new File(CustomNpcs.getWorldSaveDirectory(), "dialog.dat_old"); if (file.exists()) file.delete(); return; } } catch (Exception e) { LogWriter.except(e); } File dir = getDir(); if (!dir.exists()) { dir.mkdir(); loadDefaultDialogs(); } else { for (File file : dir.listFiles()) { if (!file.isDirectory()) continue; DialogCategory category = loadCategoryDir(file); Iterator ite = category.dialogs.keySet().iterator(); while (ite.hasNext()) { int id = ite.next(); if (id > lastUsedDialogID) lastUsedDialogID = id; Dialog dialog = category.dialogs.get(id); if (dialogs.containsKey(id)) { LogWriter.error("Duplicate id " + dialog.id + " from category " + category.title); ite.remove(); } else { dialogs.put(id, dialog); } } lastUsedCatID++; category.id = lastUsedCatID; categories.put(category.id, category); } } } private DialogCategory loadCategoryDir(File dir) { DialogCategory category = new DialogCategory(); category.title = dir.getName(); for (File file : dir.listFiles()) { if (!file.isFile() || !file.getName().endsWith(".json")) continue; try { Dialog dialog = new Dialog(); dialog.id = Integer.parseInt(file.getName().substring(0, file.getName().length() - 5)); dialog.readNBTPartial(NBTJsonUtil.LoadFile(file)); category.dialogs.put(dialog.id, dialog); dialog.category = category; if (dialog.text != null && dialog.text.length() > 15000) { LogWriter.error("Extremely big dialog loaded: [ID: " + dialog.id + "] Title: " + dialog.title + " (Length: " + dialog.text.length() + " chars)"); } } catch (Exception e) { LogWriter.error("Error loading: " + file.getAbsolutePath(), e); } } return category; } private void loadCategoriesOld(File file) throws Exception { File dir = getDir(); if (!dir.exists()) { dir.mkdir(); } NBTTagCompound nbttagcompound1 = CompressedStreamTools.readCompressed(new FileInputStream(file)); NBTTagList list = nbttagcompound1.getTagList("Data", 10); if (list == null) return; for (int i = 0; i < list.tagCount(); i++) { DialogCategory category = new DialogCategory(); category.readNBT(list.getCompoundTagAt(i)); saveCategory(category); Iterator> ita = category.dialogs.entrySet().iterator(); while (ita.hasNext()) { Map.Entry entry = ita.next(); Dialog dialog = entry.getValue(); dialog.id = entry.getKey(); dialog.category = category; if (dialogs.containsKey(dialog.id)) ita.remove(); else { saveDialog(category.id, dialog); } } } } private void loadDefaultDialogs() { DialogCategory cat = new DialogCategory(); cat.id = lastUsedCatID++; cat.title = "Villager"; Dialog dia1 = new Dialog(); dia1.id = 1; dia1.category = cat; dia1.title = "Start"; dia1.text = "Hello {player}, " + '\n' + '\n' + "Welcome to our village. I hope you enjoy your stay"; Dialog dia2 = new Dialog(); dia2.id = 2; dia2.category = cat; dia2.title = "Ask about village"; dia2.text = "This village has been around for ages. Enjoy your stay here."; Dialog dia3 = new Dialog(); dia3.id = 3; dia3.category = cat; dia3.title = "Who are you"; dia3.text = "I'm a villager here. I have lived in this village my whole life."; cat.dialogs.put(dia1.id, dia1); cat.dialogs.put(dia2.id, dia2); cat.dialogs.put(dia3.id, dia3); DialogOption option = new DialogOption(); option.title = "Tell me something about this village"; option.dialogId = 2; option.optionType = EnumOptionType.DialogOption; DialogOption option2 = new DialogOption(); option2.title = "Who are you?"; option2.dialogId = 3; option2.optionType = EnumOptionType.DialogOption; DialogOption option3 = new DialogOption(); option3.title = "Goodbye"; option3.optionType = EnumOptionType.QuitOption; dia1.options.put(0, option2); dia1.options.put(1, option); dia1.options.put(2, option3); DialogOption option4 = new DialogOption(); option4.title = "Back"; option4.dialogId = 1; dia2.options.put(1, option4); dia3.options.put(1, option4); lastUsedDialogID = 3; saveCategory(cat); saveDialog(cat.id, dia1); saveDialog(cat.id, dia2); saveDialog(cat.id, dia3); } public void saveCategory(DialogCategory category) { category.title = NoppesStringUtils.cleanFileName(category.title); if (categories.containsKey(category.id)) { DialogCategory currentCategory = categories.get(category.id); if (!currentCategory.title.equals(category.title)) { while (containsCategoryName(category.title)) category.title += "_"; File newdir = new File(getDir(), category.title); File olddir = new File(getDir(), currentCategory.title); if (newdir.exists()) return; if (!olddir.renameTo(newdir)) return; } category.dialogs = currentCategory.dialogs; } else { if (category.id < 0) { lastUsedCatID++; category.id = lastUsedCatID; } while (containsCategoryName(category.title)) category.title += "_"; File dir = new File(getDir(), category.title); if (!dir.exists()) dir.mkdirs(); } categories.put(category.id, category); SyncController.syncUpdate(EnumSyncType.DIALOG_CATEGORY, -1, SyncController.updateDialogCat(category)); } public void removeCategory(int category) { DialogCategory cat = categories.get(category); if (cat == null) return; File dir = new File(getDir(), cat.title); if (!dir.delete()) return; for (int dia : cat.dialogs.keySet()) dialogs.remove(dia); categories.remove(category); SyncController.syncRemove(EnumSyncType.DIALOG_CATEGORY, category); } private boolean containsCategoryName(String name) { name = name.toLowerCase(); for (DialogCategory cat : categories.values()) { if (cat.title.toLowerCase().equals(name)) return true; } return false; } private boolean containsDialogName(DialogCategory category, Dialog dialog) { for (Dialog dia : category.dialogs.values()) { if (dia.id != dialog.id && dia.title.equalsIgnoreCase(dialog.title)) return true; } return false; } public Dialog saveDialog(int categoryId, Dialog dialog) { DialogCategory category = categories.get(categoryId); if (category == null) return dialog; dialog.category = category; while (containsDialogName(dialog.category, dialog)) { dialog.title = dialog.title + "_"; } if (dialog.id < 0) { lastUsedDialogID++; dialog.id = lastUsedDialogID; } dialogs.put(dialog.id, dialog); category.dialogs.put(dialog.id, dialog); File dir = new File(getDir(), category.title); if (!dir.exists()) dir.mkdirs(); File file = new File(dir, dialog.id + ".json_new"); File file2 = new File(dir, dialog.id + ".json"); try { NBTTagCompound compound = dialog.writeToNBTPartial(new NBTTagCompound()); NBTJsonUtil.SaveFile(file, compound); if (file2.exists()) file2.delete(); file.renameTo(file2); SyncController.syncUpdate(EnumSyncType.DIALOG, category.id, dialog.writeToNBT(new NBTTagCompound())); } catch (Exception e) { LogWriter.except(e); } return dialog; } public void removeDialog(Dialog dialog) { DialogCategory category = dialog.category; File file = new File(new File(getDir(), category.title), dialog.id + ".json"); if (!file.delete()) return; category.dialogs.remove(dialog.id); dialogs.remove(dialog.id); SyncController.syncRemove(EnumSyncType.DIALOG, dialog.id); } private File getDir() { return new File(CustomNpcs.getWorldSaveDirectory(), "dialogs"); } public boolean hasDialog(int dialogId) { return dialogs.containsKey(dialogId); } public Map getScroll() { Map map = new HashMap(); for (DialogCategory category : categories.values()) { map.put(category.title, category.id); } return map; } public List categories() { return new ArrayList(this.categories.values()); } public IDialog get(int id) { return (IDialog) this.dialogs.get(id); } }