package joshie.progression.json; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import joshie.progression.Progression; import joshie.progression.api.criteria.*; import joshie.progression.api.special.IHasFilters; import joshie.progression.api.special.IInit; import joshie.progression.handlers.APICache; import joshie.progression.handlers.EventsManager; import joshie.progression.handlers.RemappingHandler; import joshie.progression.handlers.RuleHandler; import joshie.progression.helpers.FileHelper; import joshie.progression.helpers.JSONHelper; import joshie.progression.helpers.StackHelper; import joshie.progression.lib.CriteriaNotFoundException; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.io.FileUtils; import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.logging.log4j.Level; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.reflect.Field; import java.util.*; import static joshie.progression.gui.core.GuiList.TREE_EDITOR; public class JSONLoader { private static Gson gson; public static Gson getGson() { if (gson == null) { GsonBuilder builder = new GsonBuilder().setPrettyPrinting(); gson = builder.create(); } return gson; } private static String[] splitStringEvery(String s, int interval) { int arrayLength = (int) (Math.max(1, Math.ceil(((s.length() / (double) interval))))); String[] result = new String[arrayLength]; int j = 0; int lastIndex = result.length - 1; for (int i = 0; i < lastIndex; i++) { result[i] = s.substring(j, j + interval); j += interval; } result[lastIndex] = s.substring(j); return result; } @SideOnly(Side.CLIENT) public static String[] clientTabJsonData; public static String[] serverTabJsonData; public static int serverHashcode; public static String serverName; public final static int MAX_LENGTH = 10000; public static String getClientTabJsonData() { try { File file = FileHelper.getCriteriaFile(serverName, true); if (!file.exists()) { return ""; } else { String json = FileUtils.readFileToString(file); clientTabJsonData = splitStringEvery(json, MAX_LENGTH); return json; } } catch (Exception e) { return ""; } } public static DefaultSettings getServerTabData(String hostname) { DefaultSettings loader = null; try { File file = FileHelper.getCriteriaFile(hostname, false); if (!file.exists()) { loader = new DefaultSettings().setDefaults(); String json = getGson().toJson(loader); serverHashcode = json.hashCode(); serverTabJsonData = splitStringEvery(json, MAX_LENGTH); if (Options.debugMode) Progression.logger.log(Level.INFO, "Writing to the file is being done at getServerTabData("); Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); writer.write(json); writer.close(); return loader; } else { String json = FileUtils.readFileToString(file); serverHashcode = json.hashCode(); serverTabJsonData = splitStringEvery(json, MAX_LENGTH); return getGson().fromJson(json, DefaultSettings.class); } } catch (Exception e) { e.printStackTrace(); } return loader; //Return it whether it's null or not } //Client side only public static boolean setTabsAndCriteriaFromString(String json, boolean create) { try { DefaultSettings tab = getGson().fromJson(json, DefaultSettings.class); loadJSON(true, tab); if (create) { if (Options.debugMode) Progression.logger.log(Level.INFO, "Writing to the file is being done at setTabsAndCriteriaFromString"); //Attempt to write File file = FileHelper.getCriteriaFile(serverName, true); Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); writer.write(json); writer.close(); } TREE_EDITOR.onClientSetup(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public static void createTabFromData(DataTab data, boolean isClientside) { ItemStack stack = null; if (data.stack != null) { stack = StackHelper.getStackFromString(data.stack); } if (stack == null) { stack = new ItemStack(Items.BOOK); } ITab iTab = RuleHandler.newTab(data.uuid, isClientside); iTab.setDisplayName(data.displayName).setVisibility(data.isVisible).setStack(stack).setSortIndex(data.sortIndex); /** Step 1: we create add all instances of criteria to the registry **/ for (DataCriteria criteria : data.criteria) { createCriteriaFromData(iTab, criteria, isClientside); } /** Step 2 : Register all the conditions and triggers for this criteria **/ for (DataCriteria criteria : data.criteria) { createCriteriaInternals(criteria, isClientside); } /** Step 3, nAdd the extra data **/ for (DataCriteria criteria : data.criteria) { initialiseCriteria(criteria, isClientside); } } public static void createCriteriaFromData(ITab iTab, DataCriteria criteria, boolean isClientside) { RuleHandler.newCriteria(iTab, criteria.uuid, isClientside); } public static void createCriteriaInternals(DataCriteria criteria, boolean isClientside) { ICriteria theCriteria = APICache.getCache(isClientside).getCriteria(criteria.uuid); if (theCriteria == null) { throw new CriteriaNotFoundException(criteria.uuid); } if (criteria.triggers != null) { for (DataTrigger trigger: criteria.triggers) { ITriggerProvider iTrigger = RuleHandler.newTrigger(theCriteria, trigger.uuid, trigger.type, trigger.data, isClientside); if (trigger.conditions != null && iTrigger != null) { for (DataGeneric generic : trigger.conditions) { RuleHandler.newCondition(iTrigger, generic.uuid, generic.type, generic.data, isClientside); } } } } //Add the Rewards if (criteria.rewards != null) { for (DataGeneric reward : criteria.rewards) { RuleHandler.newReward(theCriteria, reward.uuid, reward.type, reward.data, isClientside); } } } public static void initialiseCriteria(DataCriteria criteria, boolean isClientside) { ICriteria theCriteria = APICache.getCache(isClientside).getCriteria(criteria.uuid); if (theCriteria == null) { Progression.logger.log(org.apache.logging.log4j.Level.WARN, "Criteria was not found, do not report this."); throw new CriteriaNotFoundException(criteria.uuid); } ICriteria[] thePrereqs = new ICriteria[0]; if (criteria.prereqs != null) { thePrereqs = new ICriteria[criteria.prereqs.length]; for (int i = 0; i < thePrereqs.length; i++) thePrereqs[i] = APICache.getCache(isClientside).getCriteria(criteria.prereqs[i]); } ICriteria[] theConflicts = new ICriteria[0]; if (criteria.conflicts != null) { theConflicts = new ICriteria[criteria.conflicts.length]; for (int i = 0; i < theConflicts.length; i++) theConflicts[i] = APICache.getCache(isClientside).getCriteria(criteria.conflicts[i]); } boolean allRequired = criteria.allTasks; int tasksRequired = criteria.tasksRequired; boolean allRewards = criteria.allRewards; int rewardsGiven = criteria.rewardsGiven; boolean isVisible = criteria.isVisible; boolean achievement = criteria.displayAchievement; boolean infinite = criteria.infinite; int repeatable = criteria.repeatable; int x = criteria.x; int y = criteria.y; ItemStack icon = null; if (criteria.displayStack != null) { icon = StackHelper.getStackFromString(criteria.displayStack); } if (icon == null) { icon = new ItemStack(Blocks.STONE); } String display = criteria.displayName; if (repeatable <= 1) { repeatable = 1; } theCriteria.init(thePrereqs, theConflicts, display, isVisible, achievement, repeatable, icon, allRequired, tasksRequired, infinite, allRewards, rewardsGiven, x, y); } public static void initEverything(boolean isClientside) { //Now that everything has been loaded in, we should go and init all the data for (ITab tab : APICache.getCache(isClientside).getTabSet()) { for (ICriteria criteria: tab.getCriteria()) { for (ITriggerProvider provider: criteria.getTriggers()) { ITrigger trigger = provider.getProvided(); if (trigger instanceof IInit) ((IInit)trigger).init(isClientside); if (trigger instanceof IHasFilters) { for (IFilterProvider filter: ((IHasFilters)trigger).getAllFilters()) { if (filter.getProvided() instanceof IInit) ((IInit)filter.getProvided()).init(isClientside); } } EventsManager.get(isClientside).onAdded(trigger); for (IConditionProvider conditionProvider: provider.getConditions()) { ICondition condition = conditionProvider.getProvided(); if (condition instanceof IInit) ((IInit)condition).init(isClientside); if (condition instanceof IHasFilters) { for (IFilterProvider filter: ((IHasFilters)condition).getAllFilters()) { if (filter.getProvided() instanceof IInit) ((IInit)filter.getProvided()).init(isClientside); } } } } for (IRewardProvider provider: criteria.getRewards()) { if (provider.getProvided() instanceof IInit) ((IInit)provider.getProvided()).init(isClientside); if (provider.getProvided() instanceof IHasFilters) { for (IFilterProvider filter: ((IHasFilters)provider.getProvided()).getAllFilters()) { if (filter.getProvided() instanceof IInit) ((IInit)filter.getProvided()).init(isClientside); } } EventsManager.get(isClientside).onAdded(provider.getProvided()); } } } } public static void loadJSON(boolean isClientside, DefaultSettings settings) { RemappingHandler.resetRegistries(isClientside); //Wipe existing data first if (Options.debugMode) { Progression.logger.log(Level.INFO, "Reloaded JSON at " + System.currentTimeMillis() + " " + isClientside); } Options.setSettings(settings); if (settings != null) { for (DataTab data : settings.tabs) { createTabFromData(data, isClientside); } } initEverything(isClientside); } public static void saveJSON(File file, Object toSave, boolean isClient, boolean backups) { try { if (Options.debugMode) Progression.logger.log(Level.INFO, "Writing to the file is being done at saveJSON"); //Make a backup if (Options.enableCriteriaBackups && backups) { File backup = FileHelper.getBackupFile(serverName, isClient); FileUtils.copyFile(file, backup); File[] files = FileHelper.getBackup().listFiles(); if (files.length > Options.maximumCriteriaBackups) { Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR); for (File filez : files) { filez.delete(); break; } } } Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); writer.write(getGson().toJson(toSave)); writer.close(); } catch (Exception e) { e.printStackTrace(); } if (Options.debugMode) Progression.logger.log(Level.INFO, "Saved JSON at " + System.currentTimeMillis()); } public static DataCriteria getDataCriteriaFromCriteria(ICriteria c) { DataCriteria data = new DataCriteria(); data.x = c.getX(); data.y = c.getY(); data.isVisible = c.isVisible(); data.displayAchievement = c.displayAchievement(); data.repeatable = c.getRepeatAmount(); data.infinite = c.canRepeatInfinite(); data.displayName = c.getLocalisedName(); data.tasksRequired = c.getTasksRequired(); data.allTasks = c.getIfRequiresAllTasks(); data.rewardsGiven = c.getAmountOfRewards(); data.allRewards = c.givesAllRewards(); if (Options.debugMode) Progression.logger.log(Level.INFO, "Saved the display name " + c.getLocalisedName()); data.uuid = c.getUniqueID(); data.displayStack = StackHelper.getStringFromStack(c.getIcon()); List<ITriggerProvider> triggers = c.getTriggers(); List<IRewardProvider> rewards = c.getRewards(); List<ICriteria> prereqs = c.getPreReqs(); List<ICriteria> conflicts = c.getConflicts(); ArrayList<DataTrigger> theTriggers = new ArrayList(); ArrayList<DataGeneric> theRewards = new ArrayList(); if (triggers.size() > 0) { for (ITriggerProvider provider : triggers) { ArrayList<DataGeneric> theConditions = null; if (provider.getConditions().size() > 0) { theConditions = new ArrayList(); for (IConditionProvider conditionProvider : provider.getConditions()) { JsonObject conditionData = new JsonObject(); conditionProvider.writeToJSON(conditionData); JSONHelper.writeJSON(conditionData, conditionProvider.getProvided()); DataGeneric dCondition = new DataGeneric(conditionProvider.getUniqueID(), conditionProvider.getUnlocalisedName(), conditionData); theConditions.add(dCondition); } } JsonObject triggerData = new JsonObject(); provider.writeToJSON(triggerData); JSONHelper.writeJSON(triggerData, provider.getProvided()); DataTrigger dTrigger = new DataTrigger(provider.getUniqueID(), provider.getUnlocalisedName(), triggerData, theConditions); theTriggers.add(dTrigger); } } if (rewards.size() > 0) { for (IRewardProvider provider : rewards) { JsonObject rewardData = new JsonObject(); provider.writeToJSON(rewardData); JSONHelper.writeJSON(rewardData, provider.getProvided()); DataGeneric dReward = new DataGeneric(provider.getUniqueID(), provider.getUnlocalisedName(), rewardData); theRewards.add(dReward); } } UUID[] thePrereqs = new UUID[prereqs.size()]; UUID[] theConflicts = new UUID[conflicts.size()]; for (int i = 0; i < thePrereqs.length; i++) thePrereqs[i] = prereqs.get(i).getUniqueID(); for (int i = 0; i < theConflicts.length; i++) theConflicts[i] = conflicts.get(i).getUniqueID(); if (theTriggers.size() > 0) data.triggers = theTriggers; if (theRewards.size() > 0) data.rewards = theRewards; if (thePrereqs.length > 0) data.prereqs = thePrereqs; if (theConflicts.length > 0) data.conflicts = theConflicts; return data; } public static DataTab getDataTabFromTab(ITab tab) { HashSet<UUID> names = new HashSet(); ArrayList<DataCriteria> list = new ArrayList<DataCriteria>(); DataTab tabData = new DataTab(); tabData.uuid = tab.getUniqueID(); tabData.displayName = tab.getLocalisedName(); tabData.sortIndex = tab.getSortIndex(); tabData.isVisible = tab.isVisible(); tabData.stack = StackHelper.getStringFromStack(tab.getIcon()); for (ICriteria c : tab.getCriteria()) { if (!names.add(c.getUniqueID())) continue; if (c.getIcon() == null) continue; list.add(getDataCriteriaFromCriteria(c)); } tabData.criteria = list; return tabData; } public static void saveData(boolean isClient) { if (Options.debugMode) Progression.logger.log(Level.INFO, "Begin logging"); HashSet<UUID> tabNames = new HashSet(); Collection<ITab> allTabs = APICache.getCache(isClient).getTabSet(); DefaultSettings forJSONTabs = new DefaultSettings(); //Copy over all the settings try { for (Field f : forJSONTabs.getClass().getFields()) { if (f.getName().equals("tabs")) continue; //Ignore the default f.set(forJSONTabs, f.get(Options.getSettings())); } } catch (Exception e) {} for (ITab tab : allTabs) { if (!tabNames.add(tab.getUniqueID())) continue; forJSONTabs.tabs.add(getDataTabFromTab(tab)); } saveJSON(FileHelper.getCriteriaFile(serverName, isClient), forJSONTabs, isClient, true); } }