mirror of
https://github.com/OMGeeky/ATCS.git
synced 2025-12-26 15:57:22 +01:00
1366 lines
47 KiB
Java
1366 lines
47 KiB
Java
package com.gpl.rpg.atcontentstudio.model;
|
|
|
|
import java.awt.Image;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.FileWriter;
|
|
import java.io.IOException;
|
|
import java.io.Serializable;
|
|
import java.io.StringReader;
|
|
import java.io.StringWriter;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
import java.util.HashMap;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Properties;
|
|
|
|
import javax.swing.tree.TreeNode;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import javax.xml.transform.OutputKeys;
|
|
import javax.xml.transform.Result;
|
|
import javax.xml.transform.Source;
|
|
import javax.xml.transform.Transformer;
|
|
import javax.xml.transform.TransformerException;
|
|
import javax.xml.transform.TransformerFactory;
|
|
import javax.xml.transform.dom.DOMSource;
|
|
import javax.xml.transform.stream.StreamResult;
|
|
import javax.xml.transform.stream.StreamSource;
|
|
|
|
import org.json.simple.JSONArray;
|
|
import org.w3c.dom.Comment;
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.InputSource;
|
|
import org.xml.sax.SAXException;
|
|
|
|
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
|
import com.gpl.rpg.atcontentstudio.Notification;
|
|
import com.gpl.rpg.atcontentstudio.io.JsonPrettyWriter;
|
|
import com.gpl.rpg.atcontentstudio.io.SettingsSave;
|
|
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage;
|
|
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
|
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
|
|
import com.gpl.rpg.atcontentstudio.model.maps.Worldmap;
|
|
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
|
|
import com.gpl.rpg.atcontentstudio.model.saves.SavedGamesSet;
|
|
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
|
import com.gpl.rpg.atcontentstudio.model.tools.writermode.WriterModeData;
|
|
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
|
import com.gpl.rpg.atcontentstudio.ui.WorkerDialog;
|
|
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
|
|
|
|
public class Project implements ProjectTreeNode, Serializable {
|
|
|
|
private static final long serialVersionUID = 4807454973303366758L;
|
|
|
|
//Every instance field that is not transient will be saved in this file.
|
|
public static final String SETTINGS_FILE = ".project";
|
|
|
|
public String name;
|
|
|
|
public File baseFolder;
|
|
public boolean open;
|
|
|
|
public GameSource baseContent; //A.k.a library
|
|
|
|
public GameSource referencedContent; //Pointers to base content
|
|
public transient GameSource alteredContent; //Copied from base content (does not overwrite yet)
|
|
public transient GameSource createdContent; //Stand-alone.
|
|
|
|
public SavedGamesSet saves; //For simulations.
|
|
|
|
public transient SavedSlotCollection v;
|
|
|
|
public transient Workspace parent;
|
|
|
|
public Properties knownSpritesheetsProperties = null;
|
|
|
|
public static enum ResourceSet {
|
|
gameData,
|
|
debugData,
|
|
allFiles
|
|
}
|
|
|
|
public ResourceSet sourceSetToUse = ResourceSet.allFiles;
|
|
|
|
public Project(Workspace w, String name, File source, ResourceSet sourceSet) {
|
|
this.parent = w;
|
|
this.name = name;
|
|
this.sourceSetToUse = sourceSet;
|
|
|
|
//CREATE PROJECT
|
|
baseFolder = new File(w.baseFolder, name+File.separator);
|
|
try {
|
|
baseFolder.mkdir();
|
|
} catch (SecurityException e) {
|
|
Notification.addError("Eror creating project root folder: "+e.getMessage());
|
|
e.printStackTrace();
|
|
}
|
|
open = true;
|
|
v = new SavedSlotCollection();
|
|
|
|
knownSpritesheetsProperties = new Properties();
|
|
try {
|
|
knownSpritesheetsProperties.load(Project.class.getResourceAsStream("/spritesheets.properties"));
|
|
} catch (IOException e) {
|
|
Notification.addWarn("Unable to load default spritesheets properties.");
|
|
e.printStackTrace();
|
|
}
|
|
|
|
|
|
baseContent = new GameSource(source, this);
|
|
|
|
// referencedContent = new GameSource(this, GameSource.Type.referenced);
|
|
|
|
alteredContent = new GameSource(this, GameSource.Type.altered);
|
|
createdContent = new GameSource(this, GameSource.Type.created);
|
|
|
|
saves = new SavedGamesSet(this);
|
|
|
|
v.add(createdContent);
|
|
v.add(alteredContent);
|
|
// v.add(referencedContent);
|
|
v.add(baseContent);
|
|
v.add(saves);
|
|
|
|
linkAll();
|
|
|
|
save();
|
|
}
|
|
|
|
|
|
@Override
|
|
public TreeNode getChildAt(int childIndex) {
|
|
return v.getNonEmptyElementAt(childIndex);
|
|
}
|
|
|
|
@Override
|
|
public int getChildCount() {
|
|
return v.getNonEmptySize();
|
|
}
|
|
|
|
@Override
|
|
public TreeNode getParent() {
|
|
return parent;
|
|
}
|
|
|
|
@Override
|
|
public int getIndex(TreeNode node) {
|
|
return v.getNonEmptyIndexOf((ProjectTreeNode) node);
|
|
}
|
|
|
|
@Override
|
|
public boolean getAllowsChildren() {
|
|
return open;
|
|
}
|
|
|
|
@Override
|
|
public boolean isLeaf() {
|
|
return !open;
|
|
}
|
|
|
|
@Override
|
|
public Enumeration<ProjectTreeNode> children() {
|
|
return v.getNonEmptyElements();
|
|
}
|
|
|
|
@Override
|
|
public void childrenAdded(List<ProjectTreeNode> path) {
|
|
path.add(0,this);
|
|
parent.childrenAdded(path);
|
|
}
|
|
|
|
@Override
|
|
public void childrenChanged(List<ProjectTreeNode> path) {
|
|
path.add(0,this);
|
|
parent.childrenChanged(path);
|
|
}
|
|
|
|
@Override
|
|
public void childrenRemoved(List<ProjectTreeNode> path) {
|
|
path.add(0,this);
|
|
parent.childrenRemoved(path);
|
|
}
|
|
@Override
|
|
public void notifyCreated() {
|
|
childrenAdded(new ArrayList<ProjectTreeNode>());
|
|
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
|
|
node.notifyCreated();
|
|
}
|
|
}
|
|
@Override
|
|
public String getDesc() {
|
|
return (needsSaving() ? "*" : "")+name;
|
|
}
|
|
|
|
|
|
public void close() {
|
|
this.open = false;
|
|
childrenRemoved(new ArrayList<ProjectTreeNode>());
|
|
}
|
|
|
|
public void open() {
|
|
open = true;
|
|
}
|
|
|
|
|
|
public static Project fromFolder(Workspace w, File projRoot) {
|
|
Project p = null;
|
|
File f = new File(projRoot, Project.SETTINGS_FILE);
|
|
if (!f.exists()) {
|
|
Notification.addError("Unable to find "+SETTINGS_FILE+" for project "+projRoot.getName());
|
|
return null;
|
|
} else {
|
|
p = (Project) SettingsSave.loadInstance(f, "Project");
|
|
}
|
|
p.refreshTransients(w);
|
|
return p;
|
|
}
|
|
|
|
public void refreshTransients(Workspace w) {
|
|
this.parent = w;
|
|
|
|
projectElementListeners = new HashMap<Class<? extends GameDataElement>, List<ProjectElementListener>>();
|
|
|
|
try {
|
|
knownSpritesheetsProperties = new Properties();
|
|
knownSpritesheetsProperties.load(Project.class.getResourceAsStream("/spritesheets.properties"));
|
|
} catch (IOException e) {
|
|
Notification.addWarn("Unable to load default spritesheets properties.");
|
|
e.printStackTrace();
|
|
}
|
|
|
|
if (sourceSetToUse == null) {
|
|
sourceSetToUse = ResourceSet.allFiles;
|
|
}
|
|
|
|
// long l = new Date().getTime();
|
|
baseContent.refreshTransients(this);
|
|
// l = new Date().getTime() - l;
|
|
// System.out.println("All initialized in "+l+"ms.");
|
|
// referencedContent.refreshTransients(this);
|
|
alteredContent = new GameSource(this, GameSource.Type.altered);
|
|
createdContent = new GameSource(this, GameSource.Type.created);
|
|
|
|
saves.refreshTransients();
|
|
|
|
v = new SavedSlotCollection();
|
|
v.add(createdContent);
|
|
v.add(alteredContent);
|
|
// v.add(referencedContent);
|
|
v.add(baseContent);
|
|
v.add(saves);
|
|
|
|
|
|
linkAll();
|
|
|
|
}
|
|
|
|
public void linkAll() {
|
|
for (ProjectTreeNode node : baseContent.gameData.v.getNonEmptyIterable()) {
|
|
if (node instanceof GameDataCategory<?>) {
|
|
for (GameDataElement e : ((GameDataCategory<?>) node)) {
|
|
e.link();
|
|
}
|
|
}
|
|
}
|
|
for (ProjectTreeNode node : baseContent.gameMaps.tmxMaps) {
|
|
((TMXMap)node).link();
|
|
}
|
|
for (ProjectTreeNode node : alteredContent.gameData.v.getNonEmptyIterable()) {
|
|
if (node instanceof GameDataCategory<?>) {
|
|
for (GameDataElement e : ((GameDataCategory<?>) node)) {
|
|
e.link();
|
|
}
|
|
}
|
|
}
|
|
for (ProjectTreeNode node : alteredContent.gameMaps.tmxMaps) {
|
|
((TMXMap)node).link();
|
|
}
|
|
for (ProjectTreeNode node : createdContent.gameData.v.getNonEmptyIterable()) {
|
|
if (node instanceof GameDataCategory<?>) {
|
|
for (GameDataElement e : ((GameDataCategory<?>) node)) {
|
|
e.link();
|
|
}
|
|
}
|
|
}
|
|
for (ProjectTreeNode node : createdContent.gameMaps.tmxMaps) {
|
|
((TMXMap)node).link();
|
|
}
|
|
|
|
for (WorldmapSegment node : createdContent.worldmap) {
|
|
node.link();
|
|
}
|
|
for (WorldmapSegment node : alteredContent.worldmap) {
|
|
node.link();
|
|
}
|
|
for (WorldmapSegment node : baseContent.worldmap) {
|
|
node.link();
|
|
}
|
|
}
|
|
|
|
public void save() {
|
|
SettingsSave.saveInstance(this, new File(baseFolder, Project.SETTINGS_FILE), "Project "+this.name);
|
|
}
|
|
|
|
|
|
public JSONElement getGameDataElement(Class<? extends JSONElement> gdeClass, String id) {
|
|
if (gdeClass == ActorCondition.class) {
|
|
return getActorCondition(id);
|
|
}
|
|
if (gdeClass == Dialogue.class) {
|
|
return getDialogue(id);
|
|
}
|
|
if (gdeClass == Droplist.class) {
|
|
return getDroplist(id);
|
|
}
|
|
if (gdeClass == ItemCategory.class) {
|
|
return getItemCategory(id);
|
|
}
|
|
if (gdeClass == Item.class) {
|
|
return getItem(id);
|
|
}
|
|
if (gdeClass == NPC.class) {
|
|
return getNPC(id);
|
|
}
|
|
if (gdeClass == Quest.class) {
|
|
return getQuest(id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getNodeCount(Class<? extends GameDataElement> gdeClass) {
|
|
if (gdeClass == ActorCondition.class) {
|
|
return getActorConditionCount();
|
|
}
|
|
if (gdeClass == Dialogue.class) {
|
|
return getDialogueCount();
|
|
}
|
|
if (gdeClass == Droplist.class) {
|
|
return getDroplistCount();
|
|
}
|
|
if (gdeClass == ItemCategory.class) {
|
|
return getItemCategoryCount();
|
|
}
|
|
if (gdeClass == Item.class) {
|
|
return getItemCount();
|
|
}
|
|
if (gdeClass == NPC.class) {
|
|
return getNPCCount();
|
|
}
|
|
if (gdeClass == Quest.class) {
|
|
return getQuestCount();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public int getNodeIndex(GameDataElement node) {
|
|
Class<? extends GameDataElement> gdeClass = node.getClass();
|
|
if (gdeClass == ActorCondition.class) {
|
|
return getActorConditionIndex((ActorCondition) node);
|
|
}
|
|
if (gdeClass == Dialogue.class) {
|
|
return getDialogueIndex((Dialogue) node);
|
|
}
|
|
if (gdeClass == Droplist.class) {
|
|
return getDroplistIndex((Droplist) node);
|
|
}
|
|
if (gdeClass == ItemCategory.class) {
|
|
return getItemCategoryIndex((ItemCategory) node);
|
|
}
|
|
if (gdeClass == Item.class) {
|
|
return getItemIndex((Item) node);
|
|
}
|
|
if (gdeClass == NPC.class) {
|
|
return getNPCIndex((NPC) node);
|
|
}
|
|
if (gdeClass == Quest.class) {
|
|
return getQuestIndex((Quest) node);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public ActorCondition getActorCondition(String id) {
|
|
ActorCondition gde = createdContent.gameData.getActorCondition(id);
|
|
if (gde == null) gde = alteredContent.gameData.getActorCondition(id);
|
|
if (gde == null) gde = baseContent.gameData.getActorCondition(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getActorConditionCount() {
|
|
return createdContent.gameData.actorConditions.size() + baseContent.gameData.actorConditions.size();
|
|
}
|
|
|
|
public ActorCondition getActorCondition(int index) {
|
|
if (index < createdContent.gameData.actorConditions.size()) {
|
|
return createdContent.gameData.actorConditions.get(index);
|
|
} else if (index < getActorConditionCount()){
|
|
return getActorCondition(baseContent.gameData.actorConditions.get(index - createdContent.gameData.actorConditions.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getActorConditionIndex(ActorCondition ac) {
|
|
if (ac.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.actorConditions.getIndex(ac);
|
|
} else {
|
|
return createdContent.gameData.actorConditions.size() + baseContent.gameData.actorConditions.indexOf(baseContent.gameData.getActorCondition(ac.id));
|
|
}
|
|
}
|
|
|
|
|
|
public Dialogue getDialogue(String id) {
|
|
Dialogue gde = createdContent.gameData.getDialogue(id);
|
|
if (gde == null) gde = alteredContent.gameData.getDialogue(id);
|
|
if (gde == null) gde = baseContent.gameData.getDialogue(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getDialogueCount() {
|
|
return createdContent.gameData.dialogues.size() + baseContent.gameData.dialogues.size();
|
|
}
|
|
|
|
public Dialogue getDialogue(int index) {
|
|
if (index < createdContent.gameData.dialogues.size()) {
|
|
return createdContent.gameData.dialogues.get(index);
|
|
} else if (index < getDialogueCount()){
|
|
return getDialogue(baseContent.gameData.dialogues.get(index - createdContent.gameData.dialogues.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getDialogueIndex(Dialogue dialogue) {
|
|
if (dialogue.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.dialogues.getIndex(dialogue);
|
|
} else {
|
|
return createdContent.gameData.dialogues.size() + baseContent.gameData.dialogues.indexOf(baseContent.gameData.getDialogue(dialogue.id));
|
|
}
|
|
}
|
|
|
|
|
|
public Droplist getDroplist(String id) {
|
|
Droplist gde = createdContent.gameData.getDroplist(id);
|
|
if (gde == null) gde = alteredContent.gameData.getDroplist(id);
|
|
if (gde == null) gde = baseContent.gameData.getDroplist(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getDroplistCount() {
|
|
return createdContent.gameData.droplists.size() + baseContent.gameData.droplists.size();
|
|
}
|
|
|
|
public Droplist getDroplist(int index) {
|
|
if (index < createdContent.gameData.droplists.size()) {
|
|
return createdContent.gameData.droplists.get(index);
|
|
} else if (index < getDroplistCount()){
|
|
return getDroplist(baseContent.gameData.droplists.get(index - createdContent.gameData.droplists.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getDroplistIndex(Droplist droplist) {
|
|
if (droplist.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.droplists.getIndex(droplist);
|
|
} else {
|
|
return createdContent.gameData.droplists.size() + baseContent.gameData.droplists.indexOf(baseContent.gameData.getDroplist(droplist.id));
|
|
}
|
|
}
|
|
|
|
|
|
public Item getItem(String id) {
|
|
Item gde = createdContent.gameData.getItem(id);
|
|
if (gde == null) gde = alteredContent.gameData.getItem(id);
|
|
if (gde == null) gde = baseContent.gameData.getItem(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getItemCount() {
|
|
return createdContent.gameData.items.size() + baseContent.gameData.items.size();
|
|
}
|
|
|
|
public Item getItem(int index) {
|
|
if (index < createdContent.gameData.items.size()) {
|
|
return createdContent.gameData.items.get(index);
|
|
} else if (index < getItemCount()){
|
|
return getItem(baseContent.gameData.items.get(index - createdContent.gameData.items.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getItemCountIncludingAltered() {
|
|
return createdContent.gameData.items.size() + alteredContent.gameData.items.size() + baseContent.gameData.items.size();
|
|
}
|
|
|
|
public Item getItemIncludingAltered(int index) {
|
|
if (index < createdContent.gameData.items.size()) {
|
|
return createdContent.gameData.items.get(index);
|
|
} else if (index < createdContent.gameData.items.size() + alteredContent.gameData.items.size()){
|
|
return alteredContent.gameData.items.get(index - createdContent.gameData.items.size());
|
|
} else if (index < getItemCountIncludingAltered()) {
|
|
return baseContent.gameData.items.get(index - (createdContent.gameData.items.size() + alteredContent.gameData.items.size()));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getItemIndex(Item item) {
|
|
if (item.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.items.getIndex(item);
|
|
} else {
|
|
return createdContent.gameData.items.size() + baseContent.gameData.items.indexOf(baseContent.gameData.getItem(item.id));
|
|
}
|
|
}
|
|
|
|
|
|
public ItemCategory getItemCategory(String id) {
|
|
ItemCategory gde = createdContent.gameData.getItemCategory(id);
|
|
if (gde == null) gde = alteredContent.gameData.getItemCategory(id);
|
|
if (gde == null) gde = baseContent.gameData.getItemCategory(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getItemCategoryCount() {
|
|
return createdContent.gameData.itemCategories.size() + baseContent.gameData.itemCategories.size();
|
|
}
|
|
|
|
public ItemCategory getItemCategory(int index) {
|
|
if (index < createdContent.gameData.itemCategories.size()) {
|
|
return createdContent.gameData.itemCategories.get(index);
|
|
} else if (index < getItemCategoryCount()){
|
|
return getItemCategory(baseContent.gameData.itemCategories.get(index - createdContent.gameData.itemCategories.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getItemCategoryIndex(ItemCategory iCat) {
|
|
if (iCat.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.itemCategories.getIndex(iCat);
|
|
} else {
|
|
return createdContent.gameData.itemCategories.size() + baseContent.gameData.itemCategories.indexOf(baseContent.gameData.getItemCategory(iCat.id));
|
|
}
|
|
}
|
|
|
|
|
|
public NPC getNPC(String id) {
|
|
NPC gde = createdContent.gameData.getNPC(id);
|
|
if (gde == null) gde = alteredContent.gameData.getNPC(id);
|
|
if (gde == null) gde = baseContent.gameData.getNPC(id);
|
|
return gde;
|
|
}
|
|
|
|
public NPC getNPCIgnoreCase(String id) {
|
|
NPC gde = createdContent.gameData.getNPCIgnoreCase(id);
|
|
if (gde == null) gde = alteredContent.gameData.getNPCIgnoreCase(id);
|
|
if (gde == null) gde = baseContent.gameData.getNPCIgnoreCase(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getNPCCount() {
|
|
return createdContent.gameData.npcs.size() + baseContent.gameData.npcs.size();
|
|
}
|
|
|
|
public NPC getNPC(int index) {
|
|
if (index < createdContent.gameData.npcs.size()) {
|
|
return createdContent.gameData.npcs.get(index);
|
|
} else if (index < getNPCCount()){
|
|
return getNPC(baseContent.gameData.npcs.get(index - createdContent.gameData.npcs.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getNPCCountIncludingAltered() {
|
|
return createdContent.gameData.npcs.size() + alteredContent.gameData.npcs.size() + baseContent.gameData.npcs.size();
|
|
}
|
|
|
|
public NPC getNPCIncludingAltered(int index) {
|
|
if (index < createdContent.gameData.npcs.size()) {
|
|
return createdContent.gameData.npcs.get(index);
|
|
} else if (index < createdContent.gameData.npcs.size() + alteredContent.gameData.npcs.size()){
|
|
return alteredContent.gameData.npcs.get(index - createdContent.gameData.npcs.size());
|
|
} else if (index < getNPCCountIncludingAltered()) {
|
|
return baseContent.gameData.npcs.get(index - (createdContent.gameData.npcs.size() + alteredContent.gameData.npcs.size()));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getNPCIndex(NPC npc) {
|
|
if (npc.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.npcs.getIndex(npc);
|
|
} else {
|
|
return createdContent.gameData.npcs.size() + baseContent.gameData.npcs.indexOf(baseContent.gameData.getNPC(npc.id));
|
|
}
|
|
}
|
|
|
|
|
|
public Quest getQuest(String id) {
|
|
Quest gde = createdContent.gameData.getQuest(id);
|
|
if (gde == null) gde = alteredContent.gameData.getQuest(id);
|
|
if (gde == null) gde = baseContent.gameData.getQuest(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getQuestCount() {
|
|
return createdContent.gameData.quests.size() + baseContent.gameData.quests.size();
|
|
}
|
|
|
|
public Quest getQuest(int index) {
|
|
if (index < createdContent.gameData.quests.size()) {
|
|
return createdContent.gameData.quests.get(index);
|
|
} else if (index < getQuestCount()){
|
|
return getQuest(baseContent.gameData.quests.get(index - createdContent.gameData.quests.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getQuestIndex(Quest quest) {
|
|
if (quest.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameData.quests.getIndex(quest);
|
|
} else {
|
|
return createdContent.gameData.quests.size() + baseContent.gameData.quests.indexOf(baseContent.gameData.getQuest(quest.id));
|
|
}
|
|
}
|
|
|
|
public WorldmapSegment getWorldmapSegment(String id) {
|
|
WorldmapSegment gde = createdContent.getWorldmapSegment(id);
|
|
if (gde == null) gde = alteredContent.getWorldmapSegment(id);
|
|
if (gde == null) gde = baseContent.getWorldmapSegment(id);
|
|
return gde;
|
|
}
|
|
|
|
public int getWorldmapSegmentCount() {
|
|
return createdContent.worldmap.size() + baseContent.worldmap.size();
|
|
}
|
|
|
|
public WorldmapSegment getWorldmapSegment(int index) {
|
|
if (index < createdContent.worldmap.size()) {
|
|
return createdContent.worldmap.get(index);
|
|
} else if (index < getWorldmapSegmentCount()){
|
|
return getWorldmapSegment(baseContent.worldmap.get(index - createdContent.worldmap.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getWorldmapSegmentIndex(WorldmapSegment segment) {
|
|
if (segment.getDataType() == GameSource.Type.created) {
|
|
return createdContent.worldmap.getIndex(segment);
|
|
} else {
|
|
return createdContent.worldmap.size() + baseContent.worldmap.indexOf(baseContent.getWorldmapSegment(segment.id));
|
|
}
|
|
}
|
|
|
|
public Image getIcon(String iconId) {
|
|
return baseContent.getIcon(iconId);
|
|
}
|
|
|
|
public Image getImage(String iconId) {
|
|
return baseContent.getImage(iconId);
|
|
}
|
|
|
|
public Spritesheet getSpritesheet(String id) {
|
|
Spritesheet sheet = createdContent.gameSprites.getSpritesheet(id);
|
|
if (sheet == null) sheet = alteredContent.gameSprites.getSpritesheet(id);
|
|
if (sheet == null) sheet = baseContent.gameSprites.getSpritesheet(id);
|
|
return sheet;
|
|
}
|
|
|
|
public int getSpritesheetCount() {
|
|
return createdContent.gameSprites.spritesheets.size() + baseContent.gameSprites.spritesheets.size();
|
|
}
|
|
|
|
public Spritesheet getSpritesheet(int index) {
|
|
if (index < createdContent.gameSprites.spritesheets.size()) {
|
|
return createdContent.gameSprites.spritesheets.get(index);
|
|
} else if (index < getSpritesheetCount()){
|
|
return getSpritesheet(baseContent.gameSprites.spritesheets.get(index - createdContent.gameSprites.spritesheets.size()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getSpritesheetIndex(Spritesheet spritesheet) {
|
|
if (spritesheet.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameSprites.spritesheets.indexOf(spritesheet);
|
|
} else {
|
|
return createdContent.gameSprites.spritesheets.size() + baseContent.gameSprites.spritesheets.indexOf(baseContent.gameSprites.getSpritesheet(spritesheet.id));
|
|
}
|
|
}
|
|
|
|
public TMXMap getMap(String id) {
|
|
TMXMap map = createdContent.gameMaps.getMap(id);
|
|
if (map == null) map = alteredContent.gameMaps.getMap(id);
|
|
if (map == null) map = baseContent.gameMaps.getMap(id);
|
|
return map;
|
|
}
|
|
|
|
public int getMapCount() {
|
|
return createdContent.gameMaps.getChildCount() + baseContent.gameMaps.getChildCount();
|
|
}
|
|
|
|
public TMXMap getMap(int index) {
|
|
if (index < createdContent.gameMaps.getChildCount()) {
|
|
return createdContent.gameMaps.get(index);
|
|
} else if (index < getMapCount()){
|
|
return getMap(baseContent.gameMaps.get(index - createdContent.gameMaps.getChildCount()).id);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getMapIndex(TMXMap map) {
|
|
if (map.getDataType() == GameSource.Type.created) {
|
|
return createdContent.gameMaps.tmxMaps.indexOf(map);
|
|
} else {
|
|
return createdContent.gameMaps.tmxMaps.size() + baseContent.gameMaps.tmxMaps.indexOf(baseContent.gameMaps.getMap(map.id));
|
|
}
|
|
}
|
|
|
|
public int getWriterSketchCount() {
|
|
return createdContent.writerModeDataSet.getChildCount();
|
|
}
|
|
|
|
public WriterModeData getWriterSketch(String id) {
|
|
return createdContent.writerModeDataSet.getWriterSketch(id);
|
|
}
|
|
|
|
public WriterModeData getWriterSketch(int index) {
|
|
if (index < createdContent.writerModeDataSet.getChildCount()) {
|
|
return createdContent.writerModeDataSet.get(index);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Project getProject() {
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public Image getIcon() {
|
|
return getOpenIcon();
|
|
}
|
|
@Override
|
|
public Image getClosedIcon() {
|
|
//TODO Create a cool Project icon.
|
|
return DefaultIcons.getStdClosedIcon();
|
|
}
|
|
@Override
|
|
public Image getLeafIcon() {
|
|
//TODO Create a cool Project icon.
|
|
return DefaultIcons.getStdClosedIcon();
|
|
}
|
|
@Override
|
|
public Image getOpenIcon() {
|
|
//TODO Create a cool Project icon.
|
|
return DefaultIcons.getStdOpenIcon();
|
|
}
|
|
|
|
public void makeWritable(JSONElement node) {
|
|
GameSource.Type type = node.getDataType();
|
|
if (type == null) {
|
|
Notification.addError("Unable to make "+node.getDesc()+" writable. No owning GameDataSet found.");
|
|
} else {
|
|
if (type == GameSource.Type.source) {
|
|
JSONElement clone = (JSONElement) node.clone();
|
|
if (node instanceof Quest) {
|
|
for (QuestStage oldStage : ((Quest) node).stages) {
|
|
QuestStage newStage = ((Quest) clone).getStage(oldStage.progress);
|
|
for (GameDataElement backlink : oldStage.getBacklinks()) {
|
|
backlink.elementChanged(oldStage, newStage);
|
|
}
|
|
oldStage.getBacklinks().clear();
|
|
}
|
|
}
|
|
for (GameDataElement backlink : node.getBacklinks()) {
|
|
backlink.elementChanged(node, clone);
|
|
}
|
|
node.getBacklinks().clear();
|
|
clone.writable = true;
|
|
clone.state = GameDataElement.State.created;
|
|
alteredContent.gameData.addElement(clone);
|
|
} else {
|
|
Notification.addError("Unable to make "+node.getDesc()+" writable. It does not originate from game source material.");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void makeWritable(TMXMap node) {
|
|
GameSource.Type type = node.getDataType();
|
|
if (type == null) {
|
|
Notification.addError("Unable to make "+node.getDesc()+" writable. No owning GameDataSet found.");
|
|
} else {
|
|
if (type == GameSource.Type.source) {
|
|
TMXMap clone = node.clone();
|
|
for (GameDataElement backlink : node.getBacklinks()) {
|
|
backlink.elementChanged(node, clone);
|
|
}
|
|
node.getBacklinks().clear();
|
|
clone.writable = true;
|
|
clone.state = GameDataElement.State.created;
|
|
alteredContent.gameMaps.addMap(clone);
|
|
} else {
|
|
Notification.addError("Unable to make "+node.getDesc()+" writable. It does not originate from game source material.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public void makeWritable(WorldmapSegment node) {
|
|
GameSource.Type type = node.getDataType();
|
|
if (type == null) {
|
|
Notification.addError("Unable to make "+node.getDesc()+" writable. No owning GameDataSet found.");
|
|
} else {
|
|
if (type == GameSource.Type.source) {
|
|
WorldmapSegment clone = node.clone();
|
|
for (GameDataElement backlink : node.getBacklinks()) {
|
|
backlink.elementChanged(node, clone);
|
|
}
|
|
clone.state = GameDataElement.State.init;
|
|
clone.parse();
|
|
node.getBacklinks().clear();
|
|
clone.writable = true;
|
|
clone.state = GameDataElement.State.created;
|
|
alteredContent.worldmap.addSegment(clone);
|
|
} else {
|
|
Notification.addError("Unable to make "+node.getDesc()+" writable. It does not originate from game source material.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param node. Before calling this method, make sure that no other node with the same class and id exist in either created or altered.
|
|
*/
|
|
public void createElement(JSONElement node) {
|
|
node.writable = true;
|
|
if (getGameDataElement(node.getClass(), node.id) != null) {
|
|
GameDataElement existingNode = getGameDataElement(node.getClass(), node.id);
|
|
for (GameDataElement backlink : existingNode.getBacklinks()) {
|
|
backlink.elementChanged(existingNode, node);
|
|
}
|
|
existingNode.getBacklinks().clear();
|
|
node.writable = true;
|
|
alteredContent.gameData.addElement(node);
|
|
node.link();
|
|
node.state = GameDataElement.State.created;
|
|
} else {
|
|
createdContent.gameData.addElement(node);
|
|
node.link();
|
|
node.state = GameDataElement.State.created;
|
|
}
|
|
fireElementAdded(node, getNodeIndex(node));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param node. Before calling this method, make sure that no other node with the same class and id exist in either created or altered.
|
|
*/
|
|
public void createElements(List<? extends JSONElement> nodes) {
|
|
for (JSONElement node : nodes) {
|
|
//Already added.
|
|
if (node.getProject() != null) continue;
|
|
node.writable = true;
|
|
if (getGameDataElement(node.getClass(), node.id) != null) {
|
|
GameDataElement existingNode = getGameDataElement(node.getClass(), node.id);
|
|
for (GameDataElement backlink : existingNode.getBacklinks()) {
|
|
backlink.elementChanged(existingNode, node);
|
|
}
|
|
existingNode.getBacklinks().clear();
|
|
node.writable = true;
|
|
alteredContent.gameData.addElement(node);
|
|
} else {
|
|
createdContent.gameData.addElement(node);
|
|
}
|
|
}
|
|
for (JSONElement node : nodes) {
|
|
node.link();
|
|
node.state = GameDataElement.State.created;
|
|
fireElementAdded(node, getNodeIndex(node));
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param node. Before calling this method, make sure that no other map with the same id exist in either created or altered.
|
|
*/
|
|
public void createElement(TMXMap node) {
|
|
node.writable = true;
|
|
if (getMap(node.id) != null) {
|
|
GameDataElement existingNode = getMap(node.id);
|
|
for (GameDataElement backlink : existingNode.getBacklinks()) {
|
|
backlink.elementChanged(existingNode, node);
|
|
}
|
|
existingNode.getBacklinks().clear();
|
|
node.writable = true;
|
|
node.tmxFile = new File(alteredContent.baseFolder, node.tmxFile.getName());
|
|
node.parent = alteredContent.gameMaps;
|
|
alteredContent.gameMaps.addMap(node);
|
|
node.link();
|
|
node.state = GameDataElement.State.created;
|
|
} else {
|
|
node.tmxFile = new File(createdContent.baseFolder, node.tmxFile.getName());
|
|
node.parent = createdContent.gameMaps;
|
|
createdContent.gameMaps.addMap(node);
|
|
node.link();
|
|
node.state = GameDataElement.State.created;
|
|
}
|
|
fireElementAdded(node, getNodeIndex(node));
|
|
}
|
|
|
|
|
|
public void moveToCreated(JSONElement target) {
|
|
target.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
|
((GameDataCategory<?>)target.getParent()).remove(target);
|
|
target.state = GameDataElement.State.created;
|
|
createdContent.gameData.addElement(target);
|
|
}
|
|
|
|
public void moveToAltered(JSONElement target) {
|
|
target.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
|
((GameDataCategory<?>)target.getParent()).remove(target);
|
|
target.state = GameDataElement.State.created;
|
|
((JSONElement) target).jsonFile = new File(baseContent.gameData.getGameDataElement(((JSONElement)target).getClass(), target.id).jsonFile.getAbsolutePath());
|
|
alteredContent.gameData.addElement((JSONElement) target);
|
|
}
|
|
|
|
public void createWorldmapSegment(WorldmapSegment node) {
|
|
node.writable = true;
|
|
if (getWorldmapSegment(node.id) != null) {
|
|
WorldmapSegment existingNode = getWorldmapSegment(node.id);
|
|
for (GameDataElement backlink : existingNode.getBacklinks()) {
|
|
backlink.elementChanged(existingNode, node);
|
|
}
|
|
existingNode.getBacklinks().clear();
|
|
node.writable = true;
|
|
node.state = GameDataElement.State.created;
|
|
alteredContent.worldmap.addSegment(node);
|
|
node.link();
|
|
} else {
|
|
createdContent.worldmap.addSegment(node);
|
|
node.state = GameDataElement.State.created;
|
|
node.link();
|
|
}
|
|
fireElementAdded(node, getNodeIndex(node));
|
|
}
|
|
|
|
|
|
|
|
public void createWriterSketch(WriterModeData node) {
|
|
node.writable = true;
|
|
createdContent.writerModeDataSet.add(node);
|
|
node.link();
|
|
fireElementAdded(node, getNodeIndex(node));
|
|
}
|
|
|
|
|
|
@Override
|
|
public GameDataSet getDataSet() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Type getDataType() {
|
|
return null;
|
|
}
|
|
|
|
|
|
public String getSpritesheetsProperty(String string) {
|
|
return knownSpritesheetsProperties.getProperty(string);
|
|
}
|
|
|
|
public void setSpritesheetsProperty(String key, String value) {
|
|
knownSpritesheetsProperties.setProperty(key, value);
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return v.isEmpty();
|
|
}
|
|
|
|
|
|
public void addSave(File selectedFile) {
|
|
saves.addSave(selectedFile);
|
|
}
|
|
|
|
|
|
public List<NPC> getSpawnGroup(String spawngroup_id) {
|
|
List<NPC> result = new ArrayList<NPC>();
|
|
int i = getNPCCount();
|
|
boolean alreadyAdded = false;
|
|
int index = -1;
|
|
while (--i >= 0) {
|
|
NPC npc = getNPC(i);
|
|
if (spawngroup_id.equalsIgnoreCase(npc.spawngroup_id)) {
|
|
for (NPC present : result) {
|
|
if (present.id.equals(npc.id)) {
|
|
alreadyAdded = true;
|
|
index = result.indexOf(present);
|
|
break;
|
|
}
|
|
}
|
|
if (alreadyAdded) {
|
|
result.set(index, npc);
|
|
} else {
|
|
result.add(npc);
|
|
}
|
|
}
|
|
alreadyAdded = false;
|
|
}
|
|
if (result.isEmpty()) {
|
|
//Fallback case. A single NPC does not declare a spawn group, but is referred by its ID in maps' spawn areas.
|
|
NPC npc = getNPCIgnoreCase(spawngroup_id);
|
|
if (npc != null) result.add(npc);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
transient Map<Class<? extends GameDataElement>, List<ProjectElementListener>> projectElementListeners = new HashMap<Class<? extends GameDataElement>, List<ProjectElementListener>>();
|
|
|
|
public void addElementListener(Class<? extends GameDataElement> interestingType, ProjectElementListener listener) {
|
|
if (projectElementListeners.get(interestingType) == null) {
|
|
projectElementListeners.put(interestingType, new ArrayList<ProjectElementListener>());
|
|
}
|
|
projectElementListeners.get(interestingType).add(listener);
|
|
}
|
|
|
|
public void removeElementListener(Class<? extends GameDataElement> interestingType, ProjectElementListener listener) {
|
|
if (projectElementListeners.get(interestingType) != null) projectElementListeners.get(interestingType).remove(listener);
|
|
}
|
|
|
|
public void fireElementAdded(GameDataElement element, int index) {
|
|
if (projectElementListeners.get(element.getClass()) != null) {
|
|
for (ProjectElementListener l : projectElementListeners.get(element.getClass())) {
|
|
l.elementAdded(element, index);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void fireElementRemoved(GameDataElement element, int index) {
|
|
if (projectElementListeners.get(element.getClass()) != null) {
|
|
for (ProjectElementListener l : projectElementListeners.get(element.getClass())) {
|
|
l.elementRemoved(element, index);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void exportProjectAsZipPackage(final File target) {
|
|
WorkerDialog.showTaskMessage("Exporting project "+name+"...", ATContentStudio.frame, true, new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Notification.addInfo("Exporting project \""+name+"\" as "+target.getAbsolutePath());
|
|
|
|
File tmpDir = exportProjectToTmpDir();
|
|
|
|
FileUtils.writeToZip(tmpDir, target);
|
|
FileUtils.deleteDir(tmpDir);
|
|
Notification.addSuccess("Project \""+name+"\" exported as "+target.getAbsolutePath());
|
|
}
|
|
|
|
|
|
});
|
|
}
|
|
|
|
public void exportProjectOverGameSource(final File target) {
|
|
WorkerDialog.showTaskMessage("Exporting project "+name+"...", ATContentStudio.frame, true, new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Notification.addInfo("Exporting project \""+name+"\" into "+target.getAbsolutePath());
|
|
|
|
File tmpDir = exportProjectToTmpDir();
|
|
|
|
FileUtils.copyOver(tmpDir, target);
|
|
FileUtils.deleteDir(tmpDir);
|
|
Notification.addSuccess("Project \""+name+"\" exported into "+target.getAbsolutePath());
|
|
}
|
|
|
|
|
|
});
|
|
}
|
|
|
|
public File exportProjectToTmpDir() {
|
|
File tmpDir = new File(baseFolder, "tmp");
|
|
FileUtils.deleteDir(tmpDir);
|
|
tmpDir.mkdir();
|
|
File tmpJsonDataDir = new File(tmpDir, GameDataSet.DEFAULT_REL_PATH_IN_SOURCE);
|
|
tmpJsonDataDir.mkdirs();
|
|
|
|
// for (File createdJsonFile : createdContent.gameData.baseFolder.listFiles()) {
|
|
// FileUtils.copyFile(createdJsonFile, new File(tmpJsonDataDir, createdJsonFile.getName()));
|
|
// }
|
|
Map<Class<? extends GameDataElement>, List<String>> writtenFilesPerDataType = new LinkedHashMap<Class<? extends GameDataElement>, List<String>>();
|
|
List<String> writtenFiles;
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.actorConditions, alteredContent.gameData.actorConditions, baseContent.gameData.actorConditions, ActorCondition.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(ActorCondition.class, writtenFiles);
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.dialogues, alteredContent.gameData.dialogues, baseContent.gameData.dialogues, Dialogue.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(Dialogue.class, writtenFiles);
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.droplists, alteredContent.gameData.droplists, baseContent.gameData.droplists, Droplist.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(Droplist.class, writtenFiles);
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.itemCategories, alteredContent.gameData.itemCategories, baseContent.gameData.itemCategories, ItemCategory.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(ItemCategory.class, writtenFiles);
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.items, alteredContent.gameData.items, baseContent.gameData.items, Item.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(Item.class, writtenFiles);
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.npcs, alteredContent.gameData.npcs, baseContent.gameData.npcs, NPC.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(NPC.class, writtenFiles);
|
|
writtenFiles = writeDataDeltaForDataType(createdContent.gameData.quests, alteredContent.gameData.quests, baseContent.gameData.quests, Quest.class, tmpJsonDataDir);
|
|
writtenFilesPerDataType.put(Quest.class, writtenFiles);
|
|
|
|
File tmpMapDir = new File(tmpDir, TMXMapSet.DEFAULT_REL_PATH_IN_SOURCE);
|
|
tmpMapDir.mkdirs();
|
|
writtenFiles = new LinkedList<String>();
|
|
for (File createdMapFile : createdContent.gameMaps.mapFolder.listFiles()) {
|
|
if (createdMapFile.getName().equalsIgnoreCase("worldmap.xml")) continue;
|
|
FileUtils.copyFile(createdMapFile, new File(tmpMapDir, createdMapFile.getName()));
|
|
writtenFiles.add(createdMapFile.getName());
|
|
}
|
|
for (File alteredMapFile : alteredContent.gameMaps.mapFolder.listFiles()) {
|
|
if (alteredMapFile.getName().equalsIgnoreCase("worldmap.xml")) continue;
|
|
FileUtils.copyFile(alteredMapFile, new File(tmpMapDir, alteredMapFile.getName()));
|
|
writtenFiles.add(alteredMapFile.getName());
|
|
}
|
|
writtenFilesPerDataType.put(TMXMap.class, writtenFiles);
|
|
|
|
if (sourceSetToUse == ResourceSet.gameData) {
|
|
writeResourceListXml(writtenFilesPerDataType, GameSource.DEFAULT_REL_PATH_FOR_GAME_RESOURCE, baseContent.baseFolder, tmpDir);
|
|
} else if (sourceSetToUse == ResourceSet.debugData) {
|
|
writeResourceListXml(writtenFilesPerDataType, GameSource.DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE, baseContent.baseFolder, tmpDir);
|
|
}
|
|
|
|
|
|
if (!createdContent.worldmap.isEmpty() || !alteredContent.worldmap.isEmpty()) {
|
|
try {
|
|
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
|
doc.setXmlVersion("1.0");
|
|
Element root = doc.createElement("worldmap");
|
|
doc.appendChild(root);
|
|
|
|
for (int i = 0; i < getWorldmapSegmentCount(); i++) {
|
|
root.appendChild(getWorldmapSegment(i).toXmlElement(doc));
|
|
}
|
|
|
|
Worldmap.saveDocToFile(doc, new File(tmpMapDir, "worldmap.xml"));
|
|
} catch (ParserConfigurationException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
return tmpDir;
|
|
}
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
public List<String> writeDataDeltaForDataType(GameDataCategory<? extends JSONElement> created, GameDataCategory<? extends JSONElement> altered, GameDataCategory<? extends JSONElement> source, Class<? extends JSONElement> gdeClass, File targetFolder) {
|
|
List<String> filenamesToWrite = new LinkedList<String>();
|
|
Map<String, List<Map>> dataToWritePerFilename = new LinkedHashMap<String, List<Map>>();
|
|
for (JSONElement gde : altered) {
|
|
filenamesToWrite.add(gde.jsonFile.getName());
|
|
}
|
|
for (JSONElement gde : created) {
|
|
if (!filenamesToWrite.contains(gde.jsonFile.getName())) {
|
|
filenamesToWrite.add(gde.jsonFile.getName());
|
|
}
|
|
}
|
|
for (String fName : filenamesToWrite) {
|
|
for (JSONElement gde : source) {
|
|
if (gde.jsonFile.getName().equals(fName)) {
|
|
if (dataToWritePerFilename.get(fName) == null) {
|
|
dataToWritePerFilename.put(fName, new ArrayList<Map>());
|
|
}
|
|
//Automatically fetches altered element over source element.
|
|
dataToWritePerFilename.get(fName).add(getGameDataElement(gdeClass, gde.id).toJson());
|
|
}
|
|
}
|
|
for (JSONElement gde : created) {
|
|
if (gde.jsonFile.getName().equals(fName)) {
|
|
if (dataToWritePerFilename.get(fName) == null) {
|
|
dataToWritePerFilename.put(fName, new ArrayList<Map>());
|
|
}
|
|
//Add the created elements.
|
|
dataToWritePerFilename.get(fName).add(getGameDataElement(gdeClass, gde.id).toJson());
|
|
}
|
|
}
|
|
}
|
|
for (String fName : dataToWritePerFilename.keySet()) {
|
|
File jsonFile = new File(targetFolder, fName);
|
|
StringWriter writer = new JsonPrettyWriter();
|
|
try {
|
|
JSONArray.writeJSONString(dataToWritePerFilename.get(fName), writer);
|
|
} catch (IOException e) {
|
|
//Impossible with a StringWriter
|
|
}
|
|
String textToWrite = writer.toString();
|
|
try {
|
|
FileWriter w = new FileWriter(jsonFile);
|
|
w.write(textToWrite);
|
|
w.close();
|
|
// Notification.addSuccess("Json file "+jsonFile.getAbsolutePath()+" saved.");
|
|
} catch (IOException e) {
|
|
Notification.addError("Error while writing json file "+jsonFile.getAbsolutePath()+" : "+e.getMessage());
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
return filenamesToWrite;
|
|
}
|
|
|
|
|
|
private void writeResourceListXml(Map<Class<? extends GameDataElement>, List<String>> writtenFilesPerDataType, String xmlFileRelPath, File baseFolder, File tmpDir) {
|
|
File xmlFile = new File(baseFolder, xmlFileRelPath);
|
|
File outputFile = new File(tmpDir, xmlFileRelPath);
|
|
|
|
Map<String, Class<? extends GameDataElement>> classNamesByArrayNames = new HashMap<String, Class<? extends GameDataElement>>();
|
|
classNamesByArrayNames.put("loadresource_itemcategories", ItemCategory.class);
|
|
classNamesByArrayNames.put("loadresource_actorconditions", ActorCondition.class);
|
|
classNamesByArrayNames.put("loadresource_items", Item.class);
|
|
classNamesByArrayNames.put("loadresource_droplists", Droplist.class);
|
|
classNamesByArrayNames.put("loadresource_quests", Quest.class);
|
|
classNamesByArrayNames.put("loadresource_conversationlists", Dialogue.class);
|
|
classNamesByArrayNames.put("loadresource_monsters", NPC.class);
|
|
classNamesByArrayNames.put("loadresource_maps", TMXMap.class);
|
|
|
|
String jsonResPrefix = "@raw/";
|
|
String tmxResPrefix = "@xml/";
|
|
String jsonFileSuffix = ".json";
|
|
String tmxFileSuffix = ".tmx";
|
|
|
|
if (!xmlFile.exists()) return;
|
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
Document doc;
|
|
try {
|
|
factory.setIgnoringElementContentWhitespace(true);
|
|
factory.setExpandEntityReferences(false);
|
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
|
|
|
InputSource insrc = new InputSource(new FileInputStream(xmlFile));
|
|
insrc.setEncoding("UTF-8");
|
|
doc = builder.parse(insrc);
|
|
|
|
Element arrayNode;
|
|
String name, resPrefix, fileSuffix, resName, resToFile, fileToRes;
|
|
Class<? extends GameDataElement> clazz;
|
|
List<String> writtenFiles;
|
|
|
|
Element root = (Element) doc.getElementsByTagName("resources").item(0);
|
|
if (root != null) {
|
|
NodeList arraysList = root.getElementsByTagName("array");
|
|
if (arraysList != null) {
|
|
for (int i = 0; i < arraysList.getLength(); i++) {
|
|
arrayNode = (Element) arraysList.item(i);
|
|
name = arrayNode.getAttribute("name");
|
|
clazz = classNamesByArrayNames.get(name);
|
|
if (clazz == null) continue;
|
|
writtenFiles = writtenFilesPerDataType.get(clazz);
|
|
if (writtenFiles == null) continue;
|
|
if (clazz == TMXMap.class) {
|
|
resPrefix = tmxResPrefix;
|
|
fileSuffix = tmxFileSuffix;
|
|
} else {
|
|
resPrefix = jsonResPrefix;
|
|
fileSuffix = jsonFileSuffix;
|
|
}
|
|
NodeList arrayItems = arrayNode.getElementsByTagName("item");
|
|
if (arrayItems != null) {
|
|
for (int j = 0; j < arrayItems.getLength(); j++) {
|
|
resName = ((Element)arrayItems.item(j)).getTextContent();
|
|
if (resName == null) continue;
|
|
resToFile = resName.replaceFirst("\\A"+resPrefix, "")+fileSuffix;
|
|
writtenFiles.remove(resToFile);
|
|
}
|
|
}
|
|
if (!writtenFiles.isEmpty()) {
|
|
Comment com = doc.createComment("Added by ATCS "+ATContentStudio.APP_VERSION+" for project "+getProject().name);
|
|
arrayNode.appendChild(com);
|
|
Collections.sort(writtenFiles);
|
|
for (String missingRes : writtenFiles) {
|
|
Element item = doc.createElement("item");
|
|
fileToRes = resPrefix+missingRes.replaceFirst(fileSuffix+"\\z", "");
|
|
item.setTextContent(fileToRes);
|
|
arrayNode.appendChild(item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
|
if (!outputFile.getParentFile().exists()) {
|
|
outputFile.getParentFile().mkdirs();
|
|
}
|
|
StringWriter temp = new StringWriter();
|
|
Result output = new StreamResult(temp);
|
|
Source input = new DOMSource(doc);
|
|
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
|
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
|
transformer.transform(input, output);
|
|
|
|
String tempString = temp.toString();
|
|
doc = builder.parse(new ByteArrayInputStream(tempString.getBytes("UTF-8")));
|
|
input = new DOMSource(doc);
|
|
transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader(
|
|
"<?xml version=\"1.0\"?>\r\n" +
|
|
"<xsl:stylesheet version=\"1.0\"\r\n" +
|
|
" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\r\n" +
|
|
" <xsl:strip-space elements=\"*\" />\r\n" +
|
|
" <xsl:output method=\"xml\" indent=\"yes\" />\r\n" +
|
|
"\r\n" +
|
|
" <xsl:template match=\"node() | @*\" name=\"identity\">\r\n" +
|
|
" <xsl:copy>\r\n" +
|
|
" <xsl:apply-templates select=\"node() | @*\" />\r\n" +
|
|
" </xsl:copy>\r\n" +
|
|
" </xsl:template>\r\n" +
|
|
"\r\n" +
|
|
" <xsl:template match=\"array\">\r\n" +
|
|
" <xsl:call-template name=\"identity\"/>\r\n" +
|
|
" <xsl:text>

    </xsl:text>\r\n" +
|
|
" </xsl:template>\r\n" +
|
|
"</xsl:stylesheet>")));
|
|
output = new StreamResult(new FileOutputStream(outputFile));
|
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
|
|
transformer.transform(input, output);
|
|
|
|
|
|
} catch (SAXException e) {
|
|
e.printStackTrace();
|
|
} catch (FileNotFoundException e) {
|
|
e.printStackTrace();
|
|
} catch (ParserConfigurationException e) {
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
} catch (TransformerException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean needsSaving() {
|
|
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
|
|
if (node.needsSaving()) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|