mirror of
https://github.com/AndorsTrailRelease/ATCS.git
synced 2025-10-27 18:44:03 +01:00
handle adding spritesheets. Fixed colorfilters not showing on the worldmap and replacements simulator. Added "display type" (a.k.a rarity) item field in the Items comparator.
1038 lines
34 KiB
Java
1038 lines
34 KiB
Java
package com.gpl.rpg.atcontentstudio.model;
|
|
|
|
import java.awt.Image;
|
|
import java.io.File;
|
|
import java.io.FileWriter;
|
|
import java.io.IOException;
|
|
import java.io.Serializable;
|
|
import java.io.StringWriter;
|
|
import java.util.ArrayList;
|
|
import java.util.Enumeration;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Properties;
|
|
import java.util.Set;
|
|
|
|
import javax.swing.tree.TreeNode;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
|
|
import org.json.simple.JSONArray;
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
|
|
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.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.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 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;
|
|
|
|
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();
|
|
|
|
projectElementListeners = new HashMap<Class<? extends GameDataElement>, List<ProjectElementListener>>();
|
|
}
|
|
|
|
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).parse();
|
|
}
|
|
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).parse();
|
|
}
|
|
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).parse();
|
|
}
|
|
for (ProjectTreeNode node : baseContent.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 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));
|
|
}
|
|
}
|
|
|
|
|
|
@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();
|
|
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 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));
|
|
}
|
|
|
|
|
|
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));
|
|
}
|
|
|
|
|
|
@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 generateExportPackage(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 = 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()));
|
|
}
|
|
writeAltered(alteredContent.gameData.actorConditions, baseContent.gameData.actorConditions, ActorCondition.class, tmpJsonDataDir);
|
|
writeAltered(alteredContent.gameData.dialogues, baseContent.gameData.dialogues, Dialogue.class, tmpJsonDataDir);
|
|
writeAltered(alteredContent.gameData.droplists, baseContent.gameData.droplists, Droplist.class, tmpJsonDataDir);
|
|
writeAltered(alteredContent.gameData.itemCategories, baseContent.gameData.itemCategories, ItemCategory.class, tmpJsonDataDir);
|
|
writeAltered(alteredContent.gameData.items, baseContent.gameData.items, Item.class, tmpJsonDataDir);
|
|
writeAltered(alteredContent.gameData.npcs, baseContent.gameData.npcs, NPC.class, tmpJsonDataDir);
|
|
writeAltered(alteredContent.gameData.quests, baseContent.gameData.quests, Quest.class, tmpJsonDataDir);
|
|
|
|
File tmpMapDir = new File(tmpDir, TMXMapSet.DEFAULT_REL_PATH_IN_SOURCE);
|
|
tmpMapDir.mkdirs();
|
|
for (File createdMapFile : createdContent.gameMaps.mapFolder.listFiles()) {
|
|
FileUtils.copyFile(createdMapFile, new File(tmpMapDir, createdMapFile.getName()));
|
|
}
|
|
for (File alteredMapFile : alteredContent.gameMaps.mapFolder.listFiles()) {
|
|
FileUtils.copyFile(alteredMapFile, new File(tmpMapDir, alteredMapFile.getName()));
|
|
}
|
|
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
FileUtils.writeToZip(tmpDir, target);
|
|
FileUtils.deleteDir(tmpDir);
|
|
Notification.addSuccess("Project \""+name+"\" exported as "+target.getAbsolutePath());
|
|
}
|
|
});
|
|
}
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
public void writeAltered(GameDataCategory<? extends JSONElement> altered, GameDataCategory<? extends JSONElement> source, Class<? extends JSONElement> gdeClass, File targetFolder) {
|
|
Set<String> alteredFileNames = new HashSet<String>();
|
|
Map<String, List<Map>> toWrite = new HashMap<String, List<Map>>();
|
|
for (JSONElement gde : altered) {
|
|
alteredFileNames.add(gde.jsonFile.getName());
|
|
}
|
|
for (String fName : alteredFileNames) {
|
|
for (JSONElement gde : source) {
|
|
if (gde.jsonFile.getName().equals(fName)) {
|
|
if (toWrite.get(fName) == null) {
|
|
toWrite.put(fName, new ArrayList<Map>());
|
|
}
|
|
toWrite.get(fName).add(getGameDataElement(gdeClass, gde.id).toJson());
|
|
}
|
|
}
|
|
}
|
|
for (String fName : toWrite.keySet()) {
|
|
File jsonFile = new File(targetFolder, fName);
|
|
StringWriter writer = new JsonPrettyWriter();
|
|
try {
|
|
JSONArray.writeJSONString(toWrite.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();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|