Compare commits

...

357 Commits

Author SHA1 Message Date
Nut.andor
6ec4cbf83d Merge branch 'pulls/1195352/15'
Miss effect added, add comments to start script
2025-10-03 15:56:10 +02:00
Nut.andor
5b2480920e Version 24 2025-10-03 15:53:37 +02:00
Nut.andor
e6f89b8802 Miss effect 2025-10-03 15:18:15 +02:00
Nut.andor
f2008de3e2 Merge branch 'pulls/1195352/13' 2025-10-03 15:15:35 +02:00
Nut.andor
0df961c8d3 forgotten parameter 2025-10-03 15:12:00 +02:00
Nut.andor
15b98eedcf Added field for Sprite Flip Chance 2025-10-03 14:59:04 +02:00
Nut.andor
c94c5fb41b Pull Request #15: Miss effect 2025-10-02 16:39:45 +02:00
OMGeeky
be040a74bd change miss_effect to HitEffect instead of HitReceivedEffect
(the received effects might have been applied, but the game UI would not display them, so better not show them here too)
2025-10-02 15:57:21 +02:00
OMGeeky
31cbdcabab add clarification comment to package.sh 2025-09-23 20:43:08 +02:00
OMGeeky
7e5c8d05ab improve hints on who is getting what effect on hit / hit-received for npcs 2025-09-23 20:26:58 +02:00
OMGeeky
b2003bfc38 improve create pane content calls with overrides
also fixes a bug where the wrong one was used on accident
2025-09-23 20:10:30 +02:00
OMGeeky
3b99a94654 add comments to start script about min required java version; update nsi script to match standalone start script 2025-09-23 19:29:28 +02:00
OMGeeky
806f0b10e6 miss effect 2025-09-23 18:48:46 +02:00
OMGeeky
29241f18b8 improve EffectPane generics and usage & fix hitReceivedEffect 2025-09-23 18:48:46 +02:00
Nut.andor
7df75482eb Pull Request #13: Added field for Sprite Flip Chance 2025-09-08 14:40:23 +02:00
Raphi
f93d865da7 Add spriteFlipChance as attribute in NPC.java 2025-09-04 21:41:27 +02:00
Raphi
bad86eec93 Add Sprite Flip Chance Field to NPCEditor.java 2025-09-04 21:29:04 +02:00
Nut.andor
ef9a2a628d Pull Request #12: startup performance improvements 2025-09-03 20:51:55 +02:00
Nut.andor
9dfd217a27 Merge branch 'pulls/1195352/12'
Pull Request #12: startup performance improvements
2025-09-03 20:49:57 +02:00
Nut.andor
6f10e5b94a startup performance improvements 2025-09-02 20:55:35 +02:00
Nut.andor
7cbce8e4d7 Pull Request #12: startup performance improvements 2025-08-31 23:40:31 +02:00
OMGeeky
364bf8ee11 cleanup some duplicate code 2025-08-31 23:34:46 +02:00
OMGeeky
e2b0b0e81e remove not double linking 2025-08-31 23:33:52 +02:00
OMGeeky
703b723322 improve GameDataCategory lookup time
by changing it to something backed by a HashMap with
 the id as key things can be found without looping over every element.
 This reduced the startup time on my machine to about half of the original time
2025-08-31 23:33:52 +02:00
Nut.andor
297bff84db Merge branch 'pulls/1195352/11' 2025-08-31 12:58:17 +02:00
Nut.andor
67724f5124 Revert "decrease version to avoid swing issue"
This reverts commit 3ceee2e9e6.
2025-08-31 12:53:33 +02:00
Nut.andor
09d23c8cdf Jide oss update 2025-08-30 15:48:32 +02:00
Nut.andor
749e64e09e version 2025-08-14 21:53:30 +02:00
Nut.andor
998560a6ff Pull Request #11: Jide oss update 2025-08-06 23:20:38 +02:00
OMGeeky
2bf64c417f Merge branch 'master' into jide-oss-update 2025-08-06 23:20:37 +02:00
Nut.andor
120ed02a69 Merge branch 'pulls/1195352/10' workspace + project as json 2025-08-04 21:05:23 +02:00
Nut.andor
f308580deb Json project files 2025-08-04 20:47:39 +02:00
Nut.andor
fd41013ade Merge branch 'pulls/1195352/9' 2025-08-04 20:47:18 +02:00
Nut.andor
114e09597e Pull Request #10: Json project files 2025-08-04 13:39:00 +02:00
Nut.andor
3ceee2e9e6 decrease version to avoid swing issue 2025-07-17 20:49:36 +02:00
OMGeeky
83cc57515d Add .workspace.json and .project.json to .gitignore in createProject.bat 2025-07-17 20:36:56 +02:00
OMGeeky
06d4131582 Add toJsonString method for JsonSerializable objects 2025-07-17 20:33:56 +02:00
OMGeeky
60205d54de Remove AndorsTrainer references and related functionality 2025-07-17 20:33:56 +02:00
OMGeeky
f6fbb0f5a3 Remove unused SavedGame references and related functionality
it didn't really work for a long time anyway and was extremely outdated
2025-07-17 20:33:56 +02:00
OMGeeky
af48341439 fix json project & workspace file paths when migrating from binary 2025-07-17 20:33:56 +02:00
OMGeeky
7b7218ad4e Add error handling for update check timeouts and HTTP status exceptions 2025-07-17 19:45:29 +02:00
OMGeeky
1ddf1c5051 Add notification for error when opening SpritesheetEditor 2025-07-17 18:20:16 +02:00
OMGeeky
f9a9ab97de Sort spritesheets by ID in the Project-Tree 2025-07-17 18:19:31 +02:00
Nut.andor
b37d32b5c2 Deduplicating a lot of stuff 2025-07-16 21:22:01 +02:00
OMGeeky
3c5ed1d6f6 Merge branch 'dedup-1' into json-project-files 2025-07-15 12:54:32 +02:00
OMGeeky
bc3333bd0e improve some checks when switching look and feel 2025-07-15 12:51:49 +02:00
OMGeeky
e6d9d8fbda update jar to version 3.7.15
this should improve compatibility with newer jdk versions
2025-07-15 12:51:24 +02:00
Nut.andor
32ff1b57fa Pull Request #9: Deduplicating a lot of stuff 2025-07-13 02:28:01 +02:00
OMGeeky
090584dbcc add warning about icon 2025-07-13 02:25:01 +02:00
OMGeeky
e858e436c6 Merge remote-tracking branch 'origin/master' into dedup-1
# Conflicts:
#	src/com/gpl/rpg/atcontentstudio/ATContentStudio.java
#	src/com/gpl/rpg/atcontentstudio/model/gamedata/NPC.java
2025-07-13 02:21:49 +02:00
OMGeeky
4b2aa77cb6 refactor to keep compatibility with old java version (openjdk-11 tested) 2025-07-03 20:16:36 +02:00
OMGeeky
24e1e526ce refactor to keep compatibility with old java version (openjdk-11 tested) 2025-07-03 20:05:00 +02:00
Nut.andor
861c4c3bb1 Merge branch 'pulls/1195352/8' 2025-06-28 21:23:39 +02:00
Nut.andor
c18fcfc667 Auto-Package on release 2025-06-28 20:46:50 +02:00
Nut.andor
9b1ac0d3e1 new item sprite (map objects) 2025-06-28 20:45:16 +02:00
OMGeeky
782d436681 Revert "remove saves (temporarily?) since they don't really work"
This reverts commit 7929ffe2a7.
2025-06-25 01:27:34 +02:00
OMGeeky
397d1ded8c make project file to json
same as with .workspace the .project file now saves as .project.json and falls back to .project
2025-06-25 01:24:41 +02:00
OMGeeky
aef6429dbc code style 2025-06-24 23:27:54 +02:00
OMGeeky
c43b8464a2 save .workspace as json
(under .workspace.json)

falls back on old .workspace implementation
2025-06-24 23:27:38 +02:00
OMGeeky
7929ffe2a7 remove saves (temporarily?) since they don't really work 2025-06-24 21:51:41 +02:00
OMGeeky
a3ffecfd23 improve json saving to file 2025-06-24 21:50:52 +02:00
OMGeeky
1cbcd5b661 remove finished todo list 2025-06-24 20:36:59 +02:00
OMGeeky
0eddd25292 delete inspectionProfile 2025-06-24 20:29:43 +02:00
OMGeeky
1c83eedd80 format 2025-06-24 20:10:18 +02:00
OMGeeky
6c296868c0 add null check 2025-06-24 19:50:35 +02:00
OMGeeky
8f5452b487 add myself to Contributor list 2025-06-24 19:11:56 +02:00
OMGeeky
f9f1caafc6 extract some code 2025-06-24 18:57:53 +02:00
OMGeeky
c0e24b4cf5 fix bug, where condition buttons are enabled in readonly mode 2025-06-24 18:45:15 +02:00
OMGeeky
cd36813050 move some things around and make the code sturdier 2025-06-24 18:40:54 +02:00
OMGeeky
358d855eec fix number comparison bugs 2025-06-24 18:11:24 +02:00
OMGeeky
281e314815 extract ConditionEffectEditorPane 2025-06-24 18:00:47 +02:00
OMGeeky
3f19ca959b improve code a bit 2025-06-24 16:51:29 +02:00
OMGeeky
6b74ad5cbe fix bug, where some values were not being updated when switching category to a different action type 2025-06-24 16:40:42 +02:00
OMGeeky
93e44a2b50 improve *EffectPane initialisation 2025-06-24 16:39:46 +02:00
OMGeeky
652da07cc8 change warning message when no action type can be determined for an item when writing 2025-06-24 16:30:49 +02:00
OMGeeky
2dbe881dd7 change ItemEditor to use *EffectPane classes 2025-06-24 16:25:13 +02:00
OMGeeky
b7e9bf0582 move ListModels to CommonEditor for re-use 2025-06-24 16:07:50 +02:00
OMGeeky
6dcd8599b3 reformat CommonEditor 2025-06-24 15:38:55 +02:00
OMGeeky
62ed795fed add codeStyle to git 2025-06-24 15:38:41 +02:00
OMGeeky
ec04b810d9 fix bug 2025-06-24 15:23:44 +02:00
OMGeeky
18b92a3921 add valueChanged override for HitRecievedEffectPane 2025-06-24 15:16:36 +02:00
OMGeeky
127ed76006 improve isNull check 2025-06-24 14:53:59 +02:00
OMGeeky
56242e85f2 check TODOs 2025-06-24 14:44:45 +02:00
OMGeeky
de2b47821b add TODOs that need to be done before finishing. 2025-06-23 22:12:16 +02:00
OMGeeky
7eb60117c4 fix bug in writeMinMaxToMap 2025-06-23 22:09:45 +02:00
OMGeeky
0c69438a33 move the hitReceivedEffect fields to the correct position 2025-06-23 21:55:08 +02:00
OMGeeky
380bb1de17 improve DeathEffectPane generics & inheritance 2025-06-23 21:47:36 +02:00
OMGeeky
9ae9914dde cleanup 2025-06-23 21:29:09 +02:00
OMGeeky
c78fcde633 extract hitReceivedEffect stuff into HitReceivedEffectPane 2025-06-23 21:29:02 +02:00
OMGeeky
270c613f66 add applyToTargetHint to HitEffectPanel 2025-06-23 21:17:44 +02:00
OMGeeky
ebafae7503 extract some valueChanged stuff for DeathEffectPane & HitEffectPane 2025-06-23 21:03:04 +02:00
OMGeeky
572c658b43 change some constructor stuff for it and switch the deathEffectPane to the new DeathEffectPane class 2025-06-23 20:41:40 +02:00
OMGeeky
5031fa3c72 rename some stuff 2025-06-23 19:58:22 +02:00
OMGeeky
7f0b55a71c add possibility for hint where the effect is applied to 2025-06-23 18:57:59 +02:00
OMGeeky
ab91d330bd extract parts of HitEffectPane into DeathEffectPane for better usage 2025-06-23 18:51:04 +02:00
OMGeeky
27a86ee654 continue to extract HitEffectPane 2025-06-23 18:43:54 +02:00
OMGeeky
ad15063dcc start to extract HitEffectPane 2025-06-23 18:23:54 +02:00
OMGeeky
2ea425dda6 use isImmunity & isClear & isInfinite more 2025-06-23 18:20:52 +02:00
OMGeeky
f22052525c change wrong ConditionsCellRenderer to TimedConditionsCellRenderer 2025-06-23 17:37:13 +02:00
OMGeeky
63e381a804 move ConditionsCellRenderer to CommonEditor 2025-06-23 17:35:46 +02:00
OMGeeky
488dd92893 extract actorConditionElementChanged + some parse stuff 2025-06-23 17:25:39 +02:00
OMGeeky
f04f062723 extract some more toJson stuff to reduce duplication 2025-06-23 16:24:47 +02:00
OMGeeky
e91f770975 extract some toJson stuff to reduce duplication 2025-06-23 16:08:21 +02:00
OMGeeky
7018703ba6 extract linkIcon 2025-06-23 15:15:16 +02:00
OMGeeky
93f0a902ba extract linkEffects 2025-06-23 15:09:52 +02:00
OMGeeky
1ca2b9068e extract isImmunity & isClear & isInfinite 2025-06-23 15:09:41 +02:00
OMGeeky
a7f214a1cb extract TimedConditionsCellRenderer into CommonEditor 2025-06-23 14:35:27 +02:00
OMGeeky
b2c05037e5 use BasicEffect for HitReceivedEffect values to reuse logic 2025-06-23 14:31:50 +02:00
OMGeeky
517a798b6f extract BasicEffect and rename TimedConditionEffect to TimedActorConditionEffect 2025-06-23 14:31:06 +02:00
OMGeeky
e9fecee876 extract some code into updateConditionEffect (ITEM & NPC) 2025-06-23 14:03:13 +02:00
OMGeeky
967bbf918b extract some more CollapsibleItemLists (in ItemEditor) 2025-06-23 13:21:07 +02:00
OMGeeky
5ce84dc1b1 extract some CollapsibleItemLists (in ItemEditor) 2025-06-23 13:02:03 +02:00
OMGeeky
0a18309bfe remove some leftover code 2025-06-23 12:36:54 +02:00
OMGeeky
edc4634cbe extract some CollapsibleItemLists (in QUEST & NPC) 2025-06-22 20:03:18 +02:00
OMGeeky
1e25eabb50 fix deprecated warnings 2025-06-22 19:13:58 +02:00
OMGeeky
1c7de2b97f misc 2025-06-22 18:57:44 +02:00
OMGeeky
e40fe058dd fix oversight, where changes would call the wrong event 2025-06-22 18:57:37 +02:00
OMGeeky
919e65187f improve addNumberField 2025-06-22 18:55:05 +02:00
OMGeeky
7b780462ea handle wrong values passed to addNumberField better 2025-06-22 17:48:12 +02:00
OMGeeky
00147c2708 extract one CollapsibleItemList defs in ItemEditor 2025-06-21 21:07:45 +02:00
OMGeeky
70cc945010 misc 2025-06-21 20:24:33 +02:00
OMGeeky
21005f1ba6 improve bounds check in getElementAt 2025-06-21 20:16:57 +02:00
OMGeeky
b5a6aa6706 rename some stuff and be more specific on some usages 2025-06-21 20:16:05 +02:00
OMGeeky
3cc6eb9edb enable buttons to move up and down on all (extracted) list panels 2025-06-21 20:01:01 +02:00
OMGeeky
d166e49f4d extract common stuff of addIntegerField & addDoubleField 2025-06-21 19:25:44 +02:00
OMGeeky
d1568cd2ed extract common stuff of addTextField & addTextArea 2025-06-21 19:10:03 +02:00
OMGeeky
685ce223da extract refresh button creation 2025-06-21 19:09:35 +02:00
OMGeeky
18cb73385f remove Unnecessary semicolons 2025-06-21 18:37:54 +02:00
OMGeeky
90359bf285 reformat all code 2025-06-21 18:36:37 +02:00
OMGeeky
bb187621b7 remove a bunch of unused assignments 2025-06-21 18:19:25 +02:00
OMGeeky
a4b431efdd remove some commented out code from earlier 2025-06-21 17:59:59 +02:00
OMGeeky
cffbf973e1 change more ListModel implementations to more specific implementations
like ListenerListModel, ListenerCollectionModel or OrderedListenerListModel
2025-06-21 17:59:59 +02:00
OMGeeky
979a7bc43f add interface ListenerCollectionModel and use it in the OrderedListenerListModel 2025-06-21 17:59:59 +02:00
OMGeeky
6b049d3b7b rename CustomListModel to OrderedListenerListModel 2025-06-21 17:59:59 +02:00
OMGeeky
edd0160c9d extract some code into ListenerListModel interface 2025-06-21 17:59:59 +02:00
OMGeeky
fdcc4fab55 extract some code 2025-06-21 17:59:59 +02:00
OMGeeky
d030e11019 change more ListModel implementations to CustomListModel 2025-06-21 17:59:59 +02:00
OMGeeky
333100b19b add more ListModel to CustomListModel changes 2025-06-21 17:59:59 +02:00
OMGeeky
cfb906736d extract into sub-methods 2025-06-21 17:59:59 +02:00
OMGeeky
cf8c0497bc add navigation to getCollapsibleItemList 2025-06-21 17:59:59 +02:00
OMGeeky
355bb2bc54 extract collapsibleItemList with buttons into method
this is currently done for
- items in a droplist
- replies
- rewards

others should follow
2025-06-21 17:59:59 +02:00
OMGeeky
e1e85d7a90 extract into CustomListModel 2025-06-01 20:26:18 +02:00
OMGeeky
9ed9393b16 extract wordWrap to TextUtils helper-class 2025-06-01 19:24:24 +02:00
OMGeeky
8c42b498b0 rename needsToBeLinked to linkCheck and continue dedupe 2025-06-01 19:16:59 +02:00
OMGeeky
8561415574 dedup link check 2025-06-01 19:01:35 +02:00
OMGeeky
185f168b19 misc 2025-06-01 18:52:12 +02:00
OMGeeky
70055be6d2 improve usings 2025-05-03 20:16:57 +02:00
OMGeeky
286d95d83d improve imports 2025-05-03 20:14:45 +02:00
OMGeeky
04b704daf0 more de-duplication 2025-05-03 20:10:36 +02:00
OMGeeky
3f1f988808 fix missed null check 2025-05-03 20:07:28 +02:00
OMGeeky
e232c33339 more de-duplication 2025-05-03 20:07:28 +02:00
OMGeeky
4239beb825 de-dupe code 2025-05-03 20:07:28 +02:00
Nut.andor
eb6377a983 Adding better error message in TMX input 2025-03-16 20:17:57 +01:00
Nut.andor
2fb16c9213 missing JDK in misc.xml 2025-03-16 20:17:32 +01:00
Nut.andor
6741100a4f Pull Request #8: Auto-Package on release 2025-02-18 23:52:51 +01:00
OMGeeky
dbff7fb571 Refactor version handling to read APP_VERSION from ATCS_latest file
(cherry picked from commit c9cccf9eb29f90e9a90d1609023f4f47c19d2969)
2025-02-18 23:34:08 +01:00
OMGeeky
dfb3e31a7a Update package.sh to copy version file from VERSION_FILE variable
(cherry picked from commit 5ff45746d887110c707090a70e14b2163fc69e40)
2025-02-18 23:33:48 +01:00
OMGeeky
022c9ad229 Update release workflow to read version from the correct file path
(cherry picked from commit f14d21e322d4f214ec19bb297b6b9eaecf09c374)
2025-02-18 23:33:27 +01:00
OMGeeky
38a3d4082b Update package.sh to reference ATCS_latest from the source directory and copy it to the temporary packaging directory
(cherry picked from commit 5191f56a01dda021b284f794366fba60c7d7b8d2)
2025-02-18 23:31:20 +01:00
OMGeeky
cd78ee3ad0 Add .gitattributes to normalize line endings and enforce LF for bash scripts
(cherry picked from commit a71e8fe0a40bae529e818d559eccfd2897509255)
2025-02-18 23:29:00 +01:00
OMGeeky
7b30cc6355 Remove unnecessary exit command from ATCS.sh
(cherry picked from commit a76d425ab7aba953458b72781a2d702f77ba41e5)
2025-02-18 23:29:00 +01:00
OMGeeky
9a6c5ecf6e delete obsolete Linux folder 2025-02-18 22:34:29 +01:00
OMGeeky
ed81c2382f Fix some issues with the linux ATCS.sh when the current path has spaces etc. 2025-02-18 22:33:08 +01:00
OMGeeky
ed2ad56b76 cleanup some packaging stuff 2025-02-18 18:08:02 +01:00
OMGeeky
becf45f249 Refactor release workflow to consolidate asset uploads 2025-02-16 01:19:20 +01:00
OMGeeky
c950324cd9 Reorder NSIS installation step in release workflow 2025-02-16 01:10:25 +01:00
OMGeeky
b58d080f4d Update installer script and release workflow to improve version handling 2025-02-16 01:07:44 +01:00
OMGeeky
a2640c2da0 Update installer script and release workflow to use dynamic versioning 2025-02-16 00:57:27 +01:00
OMGeeky
4fe7e71a43 Refactor GitHub Actions workflow to streamline version retrieval process 2025-02-16 00:39:10 +01:00
OMGeeky
9a162ac58d Refactor release workflow to improve directory navigation and version handling 2025-02-16 00:36:02 +01:00
OMGeeky
93718230a5 Merge pull request #1 from OMGeeky/package-improvements
Package improvements
2025-02-16 00:27:35 +01:00
OMGeeky
4fbf7de85a Merge remote-tracking branch 'omgeeky/package-improvements' into package-improvements
# Conflicts:
#	packaging/Windows/ATCS_Installer.nsi
2025-02-16 00:26:03 +01:00
OMGeeky
f0be1a8135 Add GitHub Actions workflow for automated release builds 2025-02-16 00:24:50 +01:00
OMGeeky
104d3db5ad Update ATCS_Installer.nsi to change ATCS_SOURCE_DIR path for improved directory structure and allow github actions 2025-02-16 00:24:47 +01:00
OMGeeky
f154efcecc Update ATCS_Installer.nsi to dynamically set VERSION from ATCS_latest file 2025-02-16 00:24:05 +01:00
OMGeeky
00e9e3b2a7 Enhance package.sh to support platform-specific archive creation using PowerShell on Windows 2025-02-16 00:23:52 +01:00
OMGeeky
92436d3ce9 Update package.sh to switch from tar.gz to zip for archive creation 2025-02-16 00:23:52 +01:00
OMGeeky
b6cfe349c0 Add GitHub Actions workflow for automated release builds 2025-02-16 00:21:42 +01:00
OMGeeky
1e2daa56a4 Update ATCS_Installer.nsi to change ATCS_SOURCE_DIR path for improved directory structure and allow github actions 2025-02-16 00:21:05 +01:00
OMGeeky
2caaaeb474 Update ATCS_Installer.nsi to dynamically set VERSION from ATCS_latest file 2025-02-16 00:20:21 +01:00
OMGeeky
0e8ed1a25d Enhance package.sh to support platform-specific archive creation using PowerShell on Windows 2025-02-16 00:01:27 +01:00
Nut.andor
e2fdf08fec new spritesheets index 2025-02-15 23:48:39 +01:00
OMGeeky
b5dceb9fd1 Update package.sh to switch from tar.gz to zip for archive creation 2025-02-15 23:32:36 +01:00
Nut.andor
1555bd63db Version with actor condition description is 21 2025-02-15 17:04:23 +01:00
Nut.andor
56fff8a730 nsi 2025-02-15 16:53:27 +01:00
Nut.andor
dd7b3d5300 version nbr 2025-02-15 16:44:40 +01:00
Nut.andor
68affdde8c misc 2025-02-15 16:44:13 +01:00
Nut.andor
6cec8b835e nsi 2025-02-15 16:36:45 +01:00
Nut.andor
aa43382296 Merge branch 'pulls/1195352/7' 2025-02-15 16:34:58 +01:00
Nut.andor
ec346e9c98 command parameters 2025-02-15 16:33:12 +01:00
Nut.andor
61d5af822c Build scripts 2025-02-15 16:12:38 +01:00
Nut.andor
c2d05b2bff Pull Request #7: Build scripts 2025-02-15 16:03:43 +01:00
OMGeeky
e60378ab64 Refactor package.sh to simplify JAR creation and improve directory structure 2025-02-15 16:03:36 +01:00
Nut.andor
6578236775 Merge branch 'pulls/1195352/6' 2025-02-15 14:38:30 +01:00
OMGeeky
4fa2409c24 Update .gitignore to include /out and ATCS.jar, and adjust patterns for ATCS_v*.tar.gz 2025-02-15 02:03:22 +01:00
OMGeeky
b5aa453fd6 cleanup package.sh 2025-02-15 02:03:08 +01:00
OMGeeky
42f1c87278 re-enable XML validation in TMXMapReader and update package script to copy resources recursively 2025-02-15 01:47:11 +01:00
OMGeeky
9097b97316 Disable XML validation and external DTD loading in TMXMapReader
This is because of a weird error, that only happens, when the jar is built manually somehow...
2025-02-15 01:17:59 +01:00
OMGeeky
7965ecb4f1 Update ATContentStudio_jar.xml to replace library elements with extracted-dir elements for JAR files and modify misc.xml to set default project JDK 2025-02-15 01:11:51 +01:00
OMGeeky
01963517ba Update .gitignore to exclude ATCS_v*.tar.gz and old.sh files 2025-02-15 00:31:47 +01:00
OMGeeky
30bef443d5 Refactor package script to extract library files directly to TEMP_DIR and simplify classpath 2025-02-15 00:28:16 +01:00
OMGeeky
8d01716d93 Refactor package script to simplify JAR creation and archive process 2025-02-15 00:09:21 +01:00
OMGeeky
fce5cd71ff Fix package script to construct source path and compile all Java files from specified directories 2025-02-14 23:49:00 +01:00
OMGeeky
0cddbb04e9 Enhance build script to include additional source code folders for compilation 2025-02-14 23:44:39 +01:00
OMGeeky
00ec5fe49f Update build script to include all Java files in the compilation process 2025-02-14 23:25:39 +01:00
OMGeeky
5cdb42ae07 clean up script 2025-02-14 20:30:57 +01:00
OMGeeky
c98f51744b Add initial project configuration files and setup for ATContentStudio 2025-02-14 20:04:44 +01:00
Nut.andor
5550b257ca add description field to actor conditions 2024-12-28 14:53:02 +01:00
Nut.andor
619aa1075f Pull Request #6: add description field to actor conditions 2024-12-27 13:05:53 +01:00
OMGeeky
38a3ad85c8 add description field to actor conditions 2024-12-27 10:12:48 +01:00
OMGeeky
89f764b62b Merge branch 'AndorsTrailRelease:master' into master 2024-12-27 10:10:35 +01:00
Nut.andor
d81233d470 createProject 2024-08-26 23:23:14 +02:00
Nut.andor
e1685aa625 createProject 2024-08-26 23:23:06 +02:00
OMGeeky
ae3ca5d50a fix typo & improve path safety (space in path should now be allowed) 2024-06-16 17:17:07 +02:00
OMGeeky
a00b8fbc66 fix typo 2024-06-16 17:00:32 +02:00
OMGeeky
4d03c15e08 Improve some error messages 2024-02-08 18:38:11 +00:00
OMGeeky
4571bea429 fix missing " 2024-01-09 00:18:36 +01:00
OMGeeky
ecc9a35c69 Allow it to be ran on windows
(via Git-Bash)
2024-01-01 10:47:50 -08:00
OMGeeky
c4d71df4b1 Create a packaging script
This should create the zip file to distribute it
2023-12-31 14:06:31 +01:00
Nut.andor
a13dac467a Merge branch 'v0.6.20' 2023-12-26 00:43:43 +01:00
Nut.andor
e305dfd7bf new cats sprite 2023-12-26 00:35:59 +01:00
Nut.andor
80984a43af new Sprites (engine PR 59) 2023-10-03 21:20:32 +02:00
Nut.andor
2bc8b65264 version nbr 6.20
new requirements: date, dateEquals, time, timeEquals
new rewards: mapchange
2023-10-03 21:20:32 +02:00
Nut.andor
b2584a24cc export default 2023-09-24 00:25:29 +02:00
Nut.andor
1626a8340f Merge branch 'v0.6.19' 2023-09-10 19:32:25 +02:00
Nut.andor
5fe2dfe148 Merge branch 'pulls/1195352/4' into v0.6.19
Remove empty sprites from selection panel
2023-09-10 19:28:14 +02:00
Nut.andor
abc1e7c912 Ignore empty sprites in SpriteChooser 2023-09-10 19:23:30 +02:00
Nut.andor
317d6d4216 Let console open on start 2023-09-10 19:22:18 +02:00
Nut.andor
3628386019 Pull Request #4: Ignore empty sprites in SpriteChooser 2023-09-10 17:25:03 +02:00
OMGeeky
ada352a02c implement ignoring fully transparent sprites 2023-09-10 17:15:28 +02:00
OMGeeky
fc0d97aa2f reformat file & optimize usings 2023-09-10 16:11:02 +02:00
Nut.andor
7451f582ce bugfix sprite 2023-09-09 22:51:21 +02:00
Nut.andor
7b80bf5768 new png 2023-09-01 00:08:33 +02:00
Nut
ddd98c5a8f respawnspeed (originally spawnchance) renamed & added to UI
respawnspeed (originally spawnchance) renamed & added to UI
2023-08-31 23:55:14 +02:00
OMGeeky
0ef703d82e Merge remote-tracking branch 'omgeeky/spawnchance' into spawnchance 2023-08-31 23:50:15 +02:00
OMGeeky
2339a9307c respawnspeed (originally spawnchance) renamed & added to UI 2023-08-31 23:49:03 +02:00
Nut.andor
7dcdb90750 new version 2023-08-31 23:28:32 +02:00
OMGeeky
b638c31ebe update latest 2023-08-30 15:01:04 +02:00
OMGeeky
862f4b7366 respawnspeed (originally spawnchance) renamed & added to UI 2023-08-30 14:40:50 +02:00
Nut.andor
693de98212 Revert "v0.6.19"
This reverts commit 3f4bf58375.
2023-02-04 20:41:21 +01:00
Nut.andor
3f4bf58375 v0.6.19
png names
2023-02-04 03:09:18 +01:00
Nut.andor
7ae4d9d3f6 v0.6.18:
- https:
2022-09-03 23:16:48 +02:00
Nut.andor
0f20f0cd6d Sprites sorted
Missing sprites added (actorconditions, items, monster, effect)
monsters_warrior1 too much

monsters_arulir   makes ATCS crash??

and I omitted fatboy73 this time, because the png has so many holes that would be in ATCS at the beginning of NPCs
2022-02-05 03:53:59 +01:00
Nut.andor
481956cfa5 I probably didn't understand the concept of the nsi compiler, so instead of using relative or variable paths I only got it with a fix path 2022-01-30 00:24:39 +01:00
Nut.andor
7c282aae53 Missing sprites added (actorconditions, items, monster, effect)
and sorted
2022-01-29 02:16:38 +01:00
Nut.andor
1fd3e6253e Increased version number for the upcoming release 2022-01-28 23:50:07 +01:00
Gonk
70f61f0281 Prevent crash when creating a new replace area 2022-01-25 21:33:27 +01:00
Nut
2f82fd13a6 Merge pull request #2 from atsymboldot/worldmap-label-fix
Fix disappearing worldmap labels bug
2021-12-26 14:08:16 +01:00
Nut
f7e5785970 Merge pull request #1 from atsymboldot/master
Add spore immunity skill for Fungi Panic
2021-12-26 14:07:26 +01:00
Nut
084b23f641 helpful error message added 2021-12-26 14:02:14 +01:00
Nathan Watson
ff4d8a6b6c Fix disappearing worldmap labels bug
The "worldmap.labels" map is keyed by namedarea.id (corresponding to map.area), while the "mapLocations" map is keyed by map.id. This causes worldmap labels to be marked for removal when there's a namedarea.id that does not match any map.id, which happens to be true for all namedareas except crossglen and crossroads.

This logic is unnecessary anyway, because WorldMapView.pushToModel is only invoked by WorldmapSegment.pushToModel, which only triggers when maps are added or moved, but not deleted. Deletions are instead handled by WorldmapSegment.elementChanged. As such, it should never be the case that a label is removable in a pushToModel call.
2021-01-04 01:07:57 -08:00
Nathan Watson
45aff3d25b Add spore immunity skill for Fungi Panic 2020-10-11 13:49:22 -07:00
Nut
28a1d0b09e bosses 2020-10-04 22:09:43 +02:00
Gonk
b96568049f Added spritesheets 2020-08-09 20:23:22 +02:00
Gonk
e125b0339c Added the giant basilisk spritesheet. that also prevents errors during compression 2020-06-08 20:16:17 +02:00
Gonk
65456a110b Increased version number for the upcoming release 2020-05-01 20:37:07 +02:00
Gonk
a9bd84b9f2 Merged all changes from my fork. They are needed to work on AT v0.7.10 2020-05-01 20:30:17 +02:00
Gonk
1bab8dc42f Fix for ResourcesCompactor 2020-05-01 20:17:29 +02:00
Gonk
7863b73eda fixed missing png extension 2020-04-12 21:12:19 +02:00
Gonk
32e1b87e09 Corrected linking of spritesheets in tmx
- added or altered spritesheets are now linked with relative paths so that they can be committed to an ATCS project and don't have any unwanted path infomation included
- when exporting the project all links to spritesheets are now changed to ../drawable/FILENAME.PNG
2020-04-05 20:46:03 +02:00
Gonk
4b6be99d98 Changed damage modifier default value to 100% 2020-02-25 20:24:26 +01:00
Gonk
13847bb8cd Merge branch 'weapondamagemodifier' into jar20200220 2020-02-20 21:59:02 +01:00
Gonk
2d92a97689 Named the damage modifier according to the AT sources 2020-02-20 21:57:35 +01:00
Gonk
9c21c7cd02 Merge branch 'weapondamagemodifier' into jar20200121 2020-01-21 22:24:59 +01:00
Gonk
f4fd8ad5bb Merge branch 'wearremoverequirement' into jar20200121
# Conflicts:
#	src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java
#	src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java
#	src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java
2020-01-21 22:24:42 +01:00
Gonk
63acc5bf2c Merge branch 'factionscoreequals' into jar20200121 2020-01-21 22:22:13 +01:00
Gonk
4c51353e93 Merge branch 'pofileencoding' into jar20200121 2020-01-21 22:21:58 +01:00
Gonk
7bf6bbfcd1 Merge branch 'poleweapon' into jar20200121 2020-01-21 22:21:21 +01:00
Gonk
7d40d56430 The damage modifier can now be edited, also added "on hit received" columns to the items comparator 2019-12-26 21:05:39 +01:00
Gonk
d7e83575e3 wearRemove requirement
wear and wearRemove behave similar and wear now also requires the value property
2019-11-11 21:53:25 +01:00
Gonk
811870184b factionscoreEquals 2019-10-13 17:57:41 +02:00
Gonk
7297f47b67 read and write po files using utf 8 encoding
until now the system default was used, which is especially on windows not utf 8
2019-09-04 23:33:41 +02:00
Gonk
20877f7850 Changed the order for the pole weapon proficency 2019-07-11 21:21:10 +02:00
Gonk
b3c8879be1 added pole weapon proficiency 2019-07-08 22:27:23 +02:00
Zukero
ac68006a69 v0.6.15 released.
Includes a way to view which tileset a tile is from on a map. It is
shown in the tooltip from the "Testing" tab of the map editor.
2019-05-31 10:28:16 +02:00
Zukero
92e07e76d2 Added Gonk to the contributors. 2019-05-31 09:55:17 +02:00
Gonk
5a3315da1a Added random requirement and a null pointer fix for the droplist editor
- used in conversations and replace areas
- using the droplist chance editor
2019-05-12 11:45:48 +02:00
Zukero
e12c6bcc25 Overhaul of the droplist's drop chance editor, planning to use it for
the random requirement type' chance too.
2019-04-24 00:45:57 +02:00
Zukero
44c4e1f998 Merge pull request #9 from Chriz76/maprefresh 2019-04-23 20:52:44 +02:00
Gonk
450b0de02a Adjusted external map change detection
On some systems changes by tiled were not detected and therefore the refresh button was greyed. The reason might have been that tiled recreates the files instead of changing them.
2019-04-20 21:35:59 +02:00
Zukero
57702a3a4a Lib updated. 2018-11-28 15:14:08 +01:00
Zukero
3e5f732f82 Added Minify.java license 2018-09-28 09:42:50 +02:00
Zukero
b497493853 Fixed issues in i18n tools. Added beanshell worker indicator.
Added resources compression tools too.
2018-09-21 18:51:12 +02:00
Zukero
00c05e7507 Fixed Dialogue Tree bug and spacing issues.
v0.6.14 released.
Dialogue Tree bug caused by copy-pasting code created NPEs when not
activating translator mode. Made Dialogue Tree node spacing double when
activating translator mode.
2018-09-17 20:55:18 +02:00
Zukero
1b01ecd37d Version number missing in that file.... 2018-09-15 15:05:53 +02:00
Zukero
da5b686672 v0.6.13 2018-09-15 14:39:56 +02:00
Zukero
0a3da17d47 First implementation of a bookmarks system.
Not persistent yet, so you lose them all when you close ATCS.
2018-09-13 13:34:04 +02:00
Zukero
bf42f86408 Made dialogue-tree translations loading asynchronous.
Fixed quote escaping issue in english.pot generation tool.
2018-09-13 09:39:42 +02:00
Zukero
aa543bc111 Merge pull request #6 from zizkin/master
Translations
2018-09-10 10:07:27 +02:00
Jiri Zizkin Zizka
f4041ee2c7 Add myself to contributors 2018-09-10 10:02:16 +02:00
Zukero
3e8d578474 Enhanced translation-related tools.
No UI, because there's limited interest for typical users, so it's a
beanshell-only tool for now.
2018-09-08 15:37:29 +02:00
Jiri Zizkin Zizka
67b8acd20b Code more human readable 2018-09-06 22:16:33 +02:00
Jiri Zizkin Zizka
d1612269c0 Update to translation in DialogueGraphView 2018-09-06 16:12:58 +02:00
Jiri Zizkin Zizka
f95327bd12 Show translated text from Weblate in DialogueGraphView 2018-08-29 20:45:47 +02:00
Jiri Zizkin Zizka
e0425e335d Bugfix: Add missing listener in WorkspaceSettingsEditor for more intuitive behaviour of translator mode 2018-08-29 20:33:37 +02:00
Zukero
3800bf8ff0 Added code to generate new english.pot file and some tools to ease
transition of existing translations towards the new content.
2018-08-10 23:45:50 +02:00
Zukero
84e46ffd20 v0.6.12 released 2018-07-13 19:06:12 +02:00
Zukero
9f5666ea6d Fixed bugs affecting Dialogue's replies, Key Areas and Replace areas
where requirements' negation where lost upon alteration or loading.
2018-07-13 19:03:08 +02:00
Zukero
ae5822703a Fixed harmless NPE in Dialogue editor. 2018-03-26 17:41:42 +02:00
Zukero
9b68ef6679 Added missing "Faction" field to the NPC UI. 2018-03-26 17:14:10 +02:00
Zukero
75d6f8e98f v0.6.11 released. 2018-03-04 15:43:45 +01:00
Zukero
38c206cbaf TMX Maps editor's "Replacement" tab is now called "Testing" and has more
tools.
2018-03-04 15:39:30 +01:00
Zukero
b12ed1802f Added hero sprite rendering to help debug layering issues in
"Replacements" tab of TMX Map editor.
2018-03-04 12:19:56 +01:00
Zukero
0b8bc8448a Fixed memory leaks.
Closed projects were held in memory because the Map folder watcher
threads were still alive.
2018-02-28 16:25:28 +01:00
Zukero
221a031c2b Added support for new spawn area property: ignoreAreas. 2018-02-22 16:25:38 +01:00
Zukero
f2e4767eb0 Fixed export bug multiplying the data. 2018-02-18 11:28:03 +01:00
Zukero
78ceacb0ce Warnings hunt. 2018-02-13 15:26:13 +01:00
Zukero
1604373e6c Fixed icons alignment. 2018-02-13 14:11:42 +01:00
Zukero
6e2ee13da7 Fixed issue where worldmap.xml was unduely included in the generated
loadresources.xml
2018-02-12 14:18:02 +01:00
Zukero
ea28b7475a Fixed non-critical NPE. 2018-02-12 11:40:36 +01:00
Zukero
ffe6a14cd9 v0.6.10 released. 2018-02-11 13:19:28 +01:00
Zukero
3ab233761f Merge branch 'master' of https://github.com/Zukero/ATCS.git 2018-02-10 14:45:50 +01:00
Zukero
e5bb59b876 Added support for the"alignmentSet" dialogue reward type 2018-02-10 14:43:22 +01:00
Zukero
1fb22ab73f Completed formatting of loadresources.xml files generating by project
export.
2018-02-08 17:19:25 +01:00
Zukero
6b834e0f0e Added sadly convoluted way of pretty-printing loadresources.xml
Still not perfect.
2018-02-05 23:39:07 +01:00
Zukero
9e6e1d936d Fixed a bug in loadresources.xml generation.
Enhanced custom command handling for desktop tools integration.
2018-02-05 18:15:18 +01:00
Zukero
c3144db751 Fixed bug in "Npc->Effect on every hit->Actor conditions applied to the
target". Widget state wasn't updated correctly upon using the radio
buttons.
2018-02-04 11:50:32 +01:00
Zukero
daeb394373 Fixed dialogue reward editor. giveItem reward type now allows negative
amounts.
Added Nut's spritesheets to spritesheet.properties
2018-01-16 23:37:58 +01:00
Zukero
e697f93cf5 Fixed export issue zhere the loadresources.xml file couldn't be created
because its parent folder do not exist.
2017-12-18 19:04:51 +01:00
Zukero
407d50a01e Added Wizard for export project settings. Added export to game source
folder directly. Untested...
2017-12-18 18:58:09 +01:00
Zukero
a475180bb5 Fixed unwanted link following in project deletion that led to deleting
the game source's drawable folder. First steps towards enhancements of
export package generation.
2017-12-17 22:40:46 +01:00
Zukero
259442710b Merge branch 'master' of https://github.com/Zukero/ATCS.git 2017-12-09 15:51:26 +01:00
Zukero
3c63ace6c1 v0.6.9 released. 2017-12-09 15:51:03 +01:00
Zukero
1786860a3b Buf fixes for worldmaps upon contained map deletion. 2017-10-31 15:50:04 +01:00
Zukero
cbc101b3b1 Fixed parsing issue in ActorCondition.
The full round effect's visual effect was not read from the correct
field, causing NPEs.
2017-10-24 11:38:47 +02:00
Zukero
33260137d9 Bug fix in Worldmaps when a composing map is deleted. 2017-10-22 18:21:48 +02:00
Zukero
5a1d8637f9 v0.6.8 released. 2017-10-20 13:36:47 +02:00
Zukero
97119b7101 Fixed copy-pasting bug and made wording more consistent. 2017-10-09 18:52:08 +02:00
Zukero
104029124b Added support for the "revenge strike" feature in NPCs and Items.
Untested yet, and error-prone, because it was made with a LOT of
copy-paste-replacing.
2017-10-09 18:36:41 +02:00
Zukero
2aad37549c Bug fixes and added icon overlay for immunity management. 2017-08-28 13:30:08 +02:00
Zukero
8dc05bd26a Updated UI and model to support Actor Condition Immunity.
Overall, a much better UI to tune Actor Condition-based effects on
Dialogues, Items and NPCs.
2017-08-28 01:05:19 +02:00
Zukero
de0274a5be Updated version number in main class to v0.6.7. 2017-08-25 11:13:02 +02:00
Zukero
3d2dbb9f51 v0.6.7 released! 2017-08-24 20:26:43 +02:00
Zukero
f53302cb18 Font scaling is now also scaling icons, and works in most of the UI. 2017-08-24 18:37:30 +02:00
Zukero
8d6a40eb13 Added font scaling support. It's nowhere near perfect, and some look and
feels don't support it. To set it up, add the -DFONT_SCALE=1.0 (or other
float number) in the JAVA_OPTS environment variables in the startup
scripts.
2017-08-24 18:04:56 +02:00
Zukero
0199bcfb4c Small bug fixes and UI improvements. 2017-08-23 18:17:55 +02:00
Zukero
3fe895a668 Icon for alignmentChange rewards and factionScore requirements 2017-08-22 17:36:46 +02:00
Zukero
025a63af28 Visual effect widget is now a combo box, as the data is an Enum in the
game.
2017-08-21 18:32:11 +02:00
Zukero
528ac7a7e3 Added support for the new "factionScore" requirement type. 2017-08-20 11:19:54 +02:00
Zukero
506afb95ed Simple UI improvements.
Combo box to select skill ID in skill level requirement.
Icons for most requirements types in requirements list in dialogue
editor.
More verbose description of requirement in requirement list.
2017-08-19 11:47:30 +02:00
Zukero
5d802ed0e3 v0.6.6 released. 2017-08-18 22:19:29 +02:00
Zukero
33cbd059ec More bug fixes in Requirement management for Key and Replace areas.
Much better handling of the old school form, and smooth, automatic
transitionning from old school to new school, but only when necessary!
2017-08-18 17:22:06 +02:00
Zukero
6cb0941ca6 Replace areas can now use any type of requirement.
Many bug fix in Key Areas and Replace Areas, especially for the
requirements management.
2017-08-18 16:20:25 +02:00
Zukero
cfb38c33d6 Fixed bug preventing Quests with no quest stages from loading. 2017-08-18 11:51:48 +02:00
Zukero
ec3afaaf36 v0.6.5 released! 2017-08-11 22:32:54 +02:00
Zukero
9f978591ff Fixed XML-refreshing bug in TMX Map editor, and added area name editor
for key areas.
2017-08-11 22:16:08 +02:00
Zukero
7fff58d8f9 Merge branch 'master' of https://github.com/Zukero/ATCS.git 2017-08-11 21:31:57 +02:00
Zukero
6192bd8dce Fixed issue with symlinks creatipon in windows for paths containing
spaces.
2017-08-11 21:31:34 +02:00
Zukero
be43a2a5d4 Fixed display of incorrect default values when the underlying datais
null. Fixed KeyArea initialization.
2017-08-11 18:43:44 +02:00
Zukero
99524bf043 Introducing the help panel for Dialogue Sketches' editor's shortcuts. 2017-08-09 18:04:30 +02:00
Zukero
f2144ab446 Modified marker (*) handled for Dialogue Sketches too.
Typo fixed too, now displays "Dialogue sketches" instead of "Dialogue
sketchs"
2017-08-08 18:43:15 +02:00
Zukero
ada045a13b Fixed JSON import of existing element.
When an imported item was already present in the game sources, it wasnt
associated with the correct file, leading to trouble.
2017-08-08 18:25:01 +02:00
Zukero
4c4f7e5b92 Better management of scrolling in TMX Maps editor's Replacement
simulator.
2017-07-30 17:38:50 +02:00
Zukero
ef521207de v0.6.4 released. 2017-07-28 13:15:42 +02:00
Zukero
3ef0f7e0f1 Update checker now honors the "Use internet" setting. Another setting,
"check for updates" also controls this behavior.
2017-07-28 13:11:30 +02:00
Zukero
74808cdd3a Fixed a bug improperly restoring the state of WriteModeData (Dialogue
sketches) after loading it from disk. This created a risk of data loss
upon subsequent edition of dialogue sketches.
2017-07-27 20:50:10 +02:00
Zukero
1e8d08ee3a Added online version check, to warn of availability of a new version. 2017-07-27 01:07:01 +02:00
183 changed files with 32296 additions and 28939 deletions

View File

@@ -1,18 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="res"/>
<classpathentry kind="src" path="hacked-libtiled"/>
<classpathentry kind="src" path="siphash-zackehh/src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/jide-oss.jar"/>
<classpathentry kind="lib" path="lib/json_simple-1.1.jar"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<classpathentry kind="lib" path="lib/prefuse.jar"/>
<classpathentry kind="lib" path="lib/rsyntaxtextarea.jar"/>
<classpathentry kind="lib" path="lib/ui.jar"/>
<classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
<classpathentry kind="lib" path="lib/jsoup-1.10.2.jar" sourcepath="lib/jsoup-1.10.2-sources.jar"/>
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.4.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="res"/>
<classpathentry kind="src" path="hacked-libtiled"/>
<classpathentry kind="src" path="siphash-zackehh/src/main/java"/>
<classpathentry kind="src" path="minify"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/jide-oss.jar"/>
<classpathentry kind="lib" path="lib/json_simple-1.1.jar"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<classpathentry kind="lib" path="lib/prefuse.jar"/>
<classpathentry kind="lib" path="lib/rsyntaxtextarea.jar"/>
<classpathentry kind="lib" path="lib/ui.jar"/>
<classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
<classpathentry kind="lib" path="lib/jsoup-1.10.2.jar" sourcepath="lib/jsoup-1.10.2-sources.jar"/>
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.5.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
# Set default behavior to automatically normalize line endings.
* text=auto
# Force bash scripts to always use LF line endings so that if a repo is accessed
# in Unix via a file share from Windows, the scripts will work.
*.sh text eol=lf

56
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: Release Build
on:
release:
types: [created]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Get Version
id: get_version
shell: bash
run: |
echo "Reading version from file:"
cat res/ATCS_latest
echo ""
VERSION=$(tr -d '[:space:]' < "res/ATCS_latest")
echo "Processed version: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "Environment variable set to: $VERSION"
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
- name: Build JAR
shell: bash
run: |
cd packaging
chmod +x package.sh
echo "Building JAR and ZIP for version: ${{ env.VERSION }}"
./package.sh -windows
echo "Created artifacts:"
ls -la common/ATCS.jar
ls -la ATCS_${{ env.VERSION }}.zip
- name: Install NSIS
uses: joncloud/makensis-action@v4
with:
script-file: packaging/Windows/ATCS_Installer.nsi
arguments: /DVERSION="${{ env.VERSION }}"
- name: Upload Release Assets
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: |
./packaging/ATCS_${{ env.VERSION }}.zip
./packaging/ATCS_${{ env.VERSION }}_Setup.exe

10
.gitignore vendored
View File

@@ -1,3 +1,13 @@
/ATCS_v*.jar
/Project
/bin
/packaging/tmp/
/out
packaging/common/lib
packaging/common/ATCS.jar
packaging/ATCS_*.zip
ATCS_v*.tar.gz
ATCS.jar
/packaging/common/ATCS.env.bat
/packaging/common/ATCS.env
/packaging/common/ATCS_v*.zip

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

17
.idea/artifacts/ATContentStudio_jar.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<component name="ArtifactManager">
<artifact name="ATContentStudio:jar">
<output-path>$PROJECT_DIR$/out/artifacts/ATContentStudio_jar</output-path>
<root id="root">
<element id="archive" name="ATContentStudio.jar">
<element id="module-output" name="ATContentStudio" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/bsh-2.0b4.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/rsyntaxtextarea.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/prefuse.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jsoup-1.10.2.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/json_simple-1.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/ui.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jide-oss.jar" path-in-jar="/" />
</element>
</root>
</artifact>
</component>

19
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,19 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JavaCodeStyleSettings>
<option name="JD_P_AT_EMPTY_LINES" value="false" />
</JavaCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="200" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="SOFT_MARGINS" value="120" />
</codeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

4
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/ATContentStudio.iml" filepath="$PROJECT_DIR$/ATContentStudio.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jardesc>
<jar path="ATCS/ATCS_v0.6.3.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ATCS/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<jar path="ATContentStudio/ATCS_v0.6.20.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ATContentStudio/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/>
<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
@@ -11,9 +11,9 @@
</sealing>
</manifest>
<selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false">
<javaElement handleIdentifier="=ATCS/res"/>
<javaElement handleIdentifier="=ATCS/src"/>
<javaElement handleIdentifier="=ATCS/siphash-zackehh\/src\/main\/java"/>
<javaElement handleIdentifier="=ATCS/hacked-libtiled"/>
<javaElement handleIdentifier="=ATContentStudio/hacked-libtiled"/>
<javaElement handleIdentifier="=ATContentStudio/siphash-zackehh\/src\/main\/java"/>
<javaElement handleIdentifier="=ATContentStudio/src"/>
<javaElement handleIdentifier="=ATContentStudio/res"/>
</selectedElements>
</jardesc>

117
ATContentStudio.iml Normal file
View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="EclipseModuleManager">
<libelement value="jar://$MODULE_DIR$/lib/jide-oss.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/json_simple-1.1.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/junit-4.10.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/prefuse.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/rsyntaxtextarea.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/ui.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/bsh-2.0b4.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/jsoup-1.10.2.jar!/" />
<libelement value="jar://$MODULE_DIR$/lib/AndorsTrainer_v0.1.5.jar!/" />
<src_description expected_position="0">
<src_folder value="file://$MODULE_DIR$/src" expected_position="0" />
<src_folder value="file://$MODULE_DIR$/res" expected_position="1" />
<src_folder value="file://$MODULE_DIR$/hacked-libtiled" expected_position="2" />
<src_folder value="file://$MODULE_DIR$/siphash-zackehh/src/main/java" expected_position="3" />
<src_folder value="file://$MODULE_DIR$/minify" expected_position="4" />
</src_description>
</component>
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/bin" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/hacked-libtiled" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/minify" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/res" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/siphash-zackehh/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="inheritedJdk" />
<orderEntry type="module-library">
<library name="jide-oss.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/jide-oss.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="json_simple-1.1.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/json_simple-1.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="junit-4.10.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/junit-4.10.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="prefuse.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/prefuse.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="rsyntaxtextarea.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/rsyntaxtextarea.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="ui.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/ui.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="bsh-2.0b4.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/bsh-2.0b4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="jsoup-1.10.2.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/jsoup-1.10.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/lib/jsoup-1.10.2-sources.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="AndorsTrainer_v0.1.5.jar">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/AndorsTrainer_v0.1.5.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

129
createProject.bat Normal file
View File

@@ -0,0 +1,129 @@
@echo off
echo.
echo ***
echo *** createProject v1.0 (2024-08-24)
echo ***
echo *** This script will help to setup an ATCS project
echo *** and connect it to a repo on Github
echo ***
echo.
rem Save this script anywhere on your PC (e.g. C:\AT\createProject.bat)
rem Then open a command shell: CMD
rem and call the script in the shell.
if "%1"=="" goto :noParamError
echo You have entered:
echo.
echo ATCS-project: %1
echo in Directory: %2
echo Github user: %3
echo.
pause
if "%3"=="" goto :help
if not "%4"=="" goto :help
if not exist %2 md %2
rem --- Create ATCS project (if not already done)
:atcs
if not exist %2\%1\created\drawable\char_hero.png (
echo.
echo Do the following steps:
echo.
echo 1. Start ATCS
echo 2. Create your ATCS workspace in %2
echo 3. Add the new project %1
echo 4. Exit ATCS
echo.
pause
goto :atcs
) else (
echo ATCS Project exists
)
rem --- Create git repository
rem This is the really important part :)
rem -- go into project dir (even if we do not need to create the git repo)
echo cd %2\%1
cd %2\%1
if not exist %2\%1\readme.md (
echo creating readme
echo # %1 > readme.md
) else (
echo readme already exists
)
if not exist %2\%1\.gitignore (
echo creating gitignore
echo .workspace > .gitignore
echo .project >> .gitignore
echo .workspace.json >> .gitignore
echo .project.json >> .gitignore
echo altered/drawable >> .gitignore
echo altered/drawable/* >> .gitignore
echo created/drawable >> .gitignore
echo created/drawable/* >> .gitignore
echo tmp/res/values/loadresources.xml >> .gitignore
) else (
echo gitignore already existed
)
:git
if not exist %2\%1\.git (
echo Initializing git
git init -b main || (
echo "failed to init git. Please make sure it is installed"
pause
goto :git
)
:git_commit
git add readme.md
git add .gitignore
git commit -m "Init project" || (
echo "failed to create the initial commit."
pause
goto :git_commit
)
echo Done initializing git
) else (
echo git was already initialized
)
echo.
echo Now create your repo %1 on https://github.com/%3 (if not already done)
echo.
pause
echo pushing to git repo https://github.com/%3/%1.git
git remote add origin https://github.com/%3/%1.git
git push -u origin main
echo.
echo At last you have to find the repo in your git client:
echo - In Smartgit: Menu option: Repository / Search for repository
echo.
goto :end
:noParamError
echo.
echo You have given no parameter.
echo Maybe you have just double clicked it? That won't work.
echo I have opened a CMD shell for you. Enter the command in that shell.
start cmd
echo Please switch to the CMD shell
:help
echo.
echo Enter the command with 3 parameters:
echo %0 project path git-user
echo.
echo Example: %0 feygard_1 c:\AT\ATCS NutAndor
echo.
:end
echo.
echo *** End ***
pause

Binary file not shown.

View File

@@ -43,7 +43,7 @@ public class MapObject implements Cloneable
{
private Properties properties = new Properties();
private ObjectGroup objectGroup;
private Rectangle bounds = new Rectangle();
private Rectangle bounds;
private String name = "Object";
private String type = "";
private String imageSource = "";

View File

@@ -57,7 +57,7 @@ public class Sprite
private String name = null;
private int id = -1;
private int flags = KEY_LOOP;
private int flags;
private float frameRate = 1.0f; //one fps
private Tile[] frames;

View File

@@ -98,27 +98,46 @@ public class TileSet implements Iterable<Tile>
File f = new File(imgFilename);
Image image = ImageIO.read(f.getCanonicalFile());
BufferedImage image;
try {
image = ImageIO.read(f.getCanonicalFile());
} catch (IOException e) { throw new IOException("Failed to load " + imgFilename);
}
if (image == null) {
throw new IOException("Failed to load " + tilebmpFile);
throw new IOException("Failed to load " + imgFilename);
}
Toolkit tk = Toolkit.getDefaultToolkit();
tilebmpFile = f;
tileDimensions = new Rectangle(cutter.getTileDimensions());
// Toolkit tk = Toolkit.getDefaultToolkit();
//
// if (transparentColor != null) {
// int rgb = transparentColor.getRGB();
// image = tk.createImage(
// new FilteredImageSource(image.getSource(),
// new TransparentImageFilter(rgb)));
// }
//
// BufferedImage buffered = new BufferedImage(
// image.getWidth(null),
// image.getHeight(null),
// BufferedImage.TYPE_INT_ARGB);
// buffered.getGraphics().drawImage(image, 0, 0, null);
if (transparentColor != null) {
int rgb = transparentColor.getRGB();
image = tk.createImage(
new FilteredImageSource(image.getSource(),
new TransparentImageFilter(rgb)));
}
importTileBitmap(image, cutter);
}
public void weakImportTileBitmap(String imgFilename, TileCutter cutter)
throws IOException
{
setTilesetImageFilename(imgFilename);
File f = new File(imgFilename);
BufferedImage buffered = new BufferedImage(
image.getWidth(null),
image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
buffered.getGraphics().drawImage(image, 0, 0, null);
tilebmpFile = f;
tileDimensions = new Rectangle(cutter.getTileDimensions());
importTileBitmap(buffered, cutter);
}
public void loadFromProject(String name, TMXMap tmxMap, int tileWidth, int tileHeight) {

View File

@@ -913,7 +913,8 @@ public class TMXMapReader
private class MapEntityResolver implements EntityResolver
{
public InputSource resolveEntity(String publicId, String systemId) {
if (systemId.equals("http://mapeditor.org/dtd/1.0/map.dtd")) {
if (systemId.equals("http://mapeditor.org/dtd/1.0/map.dtd") ||
systemId.equals("https://mapeditor.org/dtd/1.0/map.dtd")) {
return new InputSource(TMXMapReader.class.getResourceAsStream(
"resources/map.dtd"));
}

View File

@@ -47,6 +47,9 @@ import java.util.Vector;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
import tiled.core.AnimatedTile;
import tiled.core.Map;
import tiled.core.MapLayer;
@@ -150,7 +153,7 @@ public class TMXMapWriter
}
private void writeMap(Map map, XMLWriter w, String wp) throws IOException {
w.writeDocType("map", null, "http://mapeditor.org/dtd/1.0/map.dtd");
w.writeDocType("map", null, "https://mapeditor.org/dtd/1.0/map.dtd");
w.startElement("map");
w.writeAttribute("version", "1.0");
@@ -238,7 +241,15 @@ public class TMXMapWriter
} else {
w.startElement("tileset");
w.writeAttribute("firstgid", getFirstGidForTileset(set));
w.writeAttribute("source", getRelativePath(wp, source));
if (set.sheet != null && set.sheet.parent.getDataType() == Type.source) {
String fileName = set.getName();
if (fileName.length() > 3 && !(fileName.substring(fileName.length() - 4).equalsIgnoreCase(".png"))) {
fileName += ".png";
}
w.writeAttribute("source", (TMXMapSet.DEFAULT_REL_PATH_TO_DRAWABLE + fileName).replace("\\", "/"));
} else {
w.writeAttribute("source", getRelativePath(wp, source));
}
if (set.getBaseDir() != null) {
w.writeAttribute("basedir", set.getBaseDir());
}
@@ -279,7 +290,15 @@ public class TMXMapWriter
if (tileBitmapFile != null) {
w.startElement("image");
w.writeAttribute("source", getRelativePath(wp, tileBitmapFile));
if (set.sheet != null && set.sheet.parent.getDataType() == Type.source) {
String fileName = set.getName();
if (fileName.length() > 3 && !(fileName.substring(fileName.length() - 4).equalsIgnoreCase(".png"))) {
fileName += ".png";
}
w.writeAttribute("source", (TMXMapSet.DEFAULT_REL_PATH_TO_DRAWABLE + fileName).replace("\\", "/"));
} else {
w.writeAttribute("source", getRelativePath(wp, tileBitmapFile));
}
if (set.sheetDimensions != null) {
w.writeAttribute("width", set.sheetDimensions.width);
w.writeAttribute("height", set.sheetDimensions.height);
@@ -569,7 +588,7 @@ public class TMXMapWriter
}
// Iterate while parents are the same
int shared = 0;
int shared;
int maxShared = Math.min(fromParents.size(), toParents.size());
for (shared = 0; shared < maxShared; shared++) {
String fromParent = fromParents.get(shared);

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,405 @@
/**
* ----------------------
* Minify.java 2015-10-04
* ----------------------
*
* Copyright (c) 2015 Charles Bihis (www.whoischarles.com)
*
* This work is an adaptation of JSMin.java published by John Reilly which is a translation from C to Java of jsmin.c
* published by Douglas Crockford. Permission is hereby granted to use this Java version under the same conditions as
* the original jsmin.c on which all of these derivatives are based.
*
*
*
* ---------------------
* JSMin.java 2006-02-13
* ---------------------
*
* Copyright (c) 2006 John Reilly (www.inconspicuous.org)
*
* This work is a translation from C to Java of jsmin.c published by Douglas Crockford. Permission is hereby granted to
* use the Java version under the same conditions as the jsmin.c on which it is based.
*
*
*
* ------------------
* jsmin.c 2003-04-21
* ------------------
*
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* The Software shall be used for Good, not Evil.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.whoischarles.util.json;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.nio.charset.StandardCharsets;
/**
* Minify.java is written by Charles Bihis (www.whoischarles.com) and is adapted from JSMin.java written by John Reilly
* (www.inconspicuous.org) which is itself a translation of jsmin.c written by Douglas Crockford (www.crockford.com).
*
* @see <a href="http://www.unl.edu/ucomm/templatedependents/JSMin.java">http://www.unl.edu/ucomm/templatedependents/JSMin.java</a>
* @see <a href="http://www.crockford.com/javascript/jsmin.c">http://www.crockford.com/javascript/jsmin.c</a>
*/
public class Minify {
private static final int EOF = -1;
private PushbackInputStream in;
private OutputStream out;
private int currChar;
private int nextChar;
private int line;
private int column;
public static enum Action {
OUTPUT_CURR, DELETE_CURR, DELETE_NEXT
}
public Minify() {
this.in = null;
this.out = null;
}
/**
* Minifies the input JSON string.
*
* Takes the input JSON string and deletes the characters which are insignificant to JavaScipt. Comments will be
* removed, tabs will be replaced with spaces, carriage returns will be replaced with line feeds, and most spaces
* and line feeds will be removed. The result will be returned.
*
* @param json The JSON string for which to minify
* @return A minified, yet functionally identical, version of the input JSON string
*/
public String minify(String json) {
InputStream in = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
minify(in, out);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return out.toString().trim();
}
/**
* Takes an input stream to a JSON string and outputs minified JSON to the output stream.
*
* Takes the input JSON via the input stream and deletes the characters which are insignificant to JavaScript.
* Comments will be removed, tabs will be replaced with spaaces, carriage returns will be replaced with line feeds,
* and most spaces and line feeds will be removed. The result is streamed to the output stream.
*
* @param in The <code>InputStream</code> from which to get the un-minified JSON
* @param out The <code>OutputStream</code> where the resulting minified JSON will be streamed to
* @throws IOException
* @throws UnterminatedRegExpLiteralException
* @throws UnterminatedCommentException
* @throws UnterminatedStringLiteralException
*/
public void minify(InputStream in, OutputStream out) throws IOException, UnterminatedRegExpLiteralException,
UnterminatedCommentException,
UnterminatedStringLiteralException {
// Initialize
this.in = new PushbackInputStream(in);
this.out = out;
this.line = 0;
this.column = 0;
// currChar = '\n';
// action(Action.DELETE_NEXT);
currChar = get();
nextChar = peek();
// Process input
while (currChar != EOF) {
switch (currChar) {
case ' ':
if (isAlphanum(nextChar)) {
action(Action.OUTPUT_CURR);
} else {
action(Action.DELETE_CURR);
}
break;
case '\n':
switch (nextChar) {
case '{':
case '[':
case '(':
case '+':
case '-':
action(Action.OUTPUT_CURR);
break;
case ' ':
action(Action.DELETE_NEXT);
break;
default:
if (isAlphanum(nextChar)) {
action(Action.OUTPUT_CURR);
} else {
action(Action.DELETE_CURR);
}
}
break;
default:
switch (nextChar) {
case ' ':
if (isAlphanum(currChar)) {
action(Action.OUTPUT_CURR);
break;
}
action(Action.DELETE_NEXT);
break;
case '\n':
switch (currChar) {
case '}':
case ']':
case ')':
case '+':
case '-':
case '"':
case '\'':
action(Action.OUTPUT_CURR);
break;
default:
if (isAlphanum(currChar)) {
action(Action.OUTPUT_CURR);
} else {
action(Action.DELETE_NEXT);
}
}
break;
default:
action(Action.OUTPUT_CURR);
break;
}
}
}
out.flush();
}
/**
* Process the current character with an appropriate action.
*
* The action that occurs is determined by the current character. The options are:
*
* 1. Output currChar: output currChar, copy nextChar to currChar, get the next character and save it to nextChar
* 2. Delete currChar: copy nextChar to currChar, get the next character and save it to nextChar
* 3. Delete nextChar: get the next character and save it to nextChar
*
* This method essentially treats a string as a single character. Also recognizes regular expressions if they are
* preceded by '(', ',', or '='.
*
* @param action The action to perform
* @throws IOException
* @throws UnterminatedRegExpLiteralException
* @throws UnterminatedCommentException
* @throws UnterminatedStringLiteralException
*/
private void action(Action action) throws IOException, UnterminatedRegExpLiteralException, UnterminatedCommentException,
UnterminatedStringLiteralException {
// Process action
switch (action) {
case OUTPUT_CURR:
out.write(currChar);
case DELETE_CURR:
currChar = nextChar;
if (currChar == '\'' || currChar == '"') {
for ( ; ; ) {
out.write(currChar);
currChar = get();
if (currChar == nextChar) {
break;
}
if (currChar <= '\n') {
throw new UnterminatedStringLiteralException(line,
column);
}
if (currChar == '\\') {
out.write(currChar);
currChar = get();
}
}
}
case DELETE_NEXT:
nextChar = next();
if (nextChar == '/'
&& (currChar == '(' || currChar == ',' || currChar == '=' || currChar == ':')) {
out.write(currChar);
out.write(nextChar);
for ( ; ; ) {
currChar = get();
if (currChar == '/') {
break;
} else if (currChar == '\\') {
out.write(currChar);
currChar = get();
} else if (currChar <= '\n') {
throw new UnterminatedRegExpLiteralException(line,
column);
}
out.write(currChar);
}
nextChar = next();
}
}
}
/**
* Determines whether a given character is a letter, digit, underscore, dollar sign, or non-ASCII character.
*
* @param c The character to compare
* @return True if the character is a letter, digit, underscore, dollar sign, or non-ASCII character. False otherwise.
*/
private boolean isAlphanum(int c) {
return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
|| c == '_' || c == '$' || c == '\\' || c > 126);
}
/**
* Returns the next character from the input stream.
*
* Will pop the next character from the input stack. If the character is a control character, translate it to a space
* or line feed.
*
* @return The next character from the input stream
* @throws IOException
*/
private int get() throws IOException {
int c = in.read();
if (c == '\n') {
line++;
column = 0;
} else {
column++;
}
if (c >= ' ' || c == '\n' || c == EOF) {
return c;
}
if (c == '\r') {
column = 0;
return '\n';
}
return ' ';
}
/**
* Returns the next character from the input stream without popping it from the stack.
*
* @return The next character from the input stream
* @throws IOException
*/
private int peek() throws IOException {
int lookaheadChar = in.read();
in.unread(lookaheadChar);
return lookaheadChar;
}
/**
* Get the next character from the input stream, excluding comments.
*
* Will read from the input stream via the <code>get()</code> method. Will exclude characters that are part of
* comments. <code>peek()</code> is used to se if a '/' is followed by a '/' or a '*' for the purpose of identifying
* comments.
*
* @return The next character from the input stream, excluding characters from comments
* @throws IOException
* @throws UnterminatedCommentException
*/
private int next() throws IOException, UnterminatedCommentException {
int c = get();
if (c == '/') {
switch (peek()) {
case '/':
for ( ; ; ) {
c = get();
if (c <= '\n') {
return c;
}
}
case '*':
get();
for ( ; ; ) {
switch (get()) {
case '*':
if (peek() == '/') {
get();
return ' ';
}
break;
case EOF:
throw new UnterminatedCommentException(line, column);
}
}
default:
return c;
}
}
return c;
}
/**
* Exception to be thrown when an unterminated comment appears in the input.
*/
public static class UnterminatedCommentException extends Exception {
public UnterminatedCommentException(int line, int column) {
super("Unterminated comment at line " + line + " and column " + column);
}
}
/**
* Exception to be thrown when an unterminated string literal appears in the input.
*/
public static class UnterminatedStringLiteralException extends Exception {
public UnterminatedStringLiteralException(int line, int column) {
super("Unterminated string literal at line " + line + " and column " + column);
}
}
/**
* Exception to be thrown when an unterminated regular expression literal appears in the input.
*/
public static class UnterminatedRegExpLiteralException extends Exception {
public UnterminatedRegExpLiteralException(int line, int column) {
super("Unterminated regular expression at line " + line + " and column " + column);
}
}
}

View File

@@ -1,2 +0,0 @@
/ATCS_v*.zip
/ATCS_v*.zip.rename

View File

@@ -1,22 +0,0 @@
#!/bin/bash
ATCS_DIR=$(dirname $(readlink -f "$0" || greadlink -f "$0" || stat -f "$0"))
MAX_MEM=512M
CP=$(find ${ATCS_DIR}/lib/ -name '*.jar' | paste -sd: -)
JAVA=java
JAVA_OPTS=
ENV_FILE=${ATCS_DIR}/ATCS.env
MAIN_CLASS=com.gpl.rpg.atcontentstudio.ATContentStudio
if [ -f ${ENV_FILE} ]
then
source ${ENV_FILE}
else
echo "#MAX_MEM=${MAX_MEM}" > ${ENV_FILE}
echo "#JAVA=${JAVA}" >> ${ENV_FILE}
echo "#JAVA_OPTS=${JAVA_OPTS}" >> ${ENV_FILE}
echo "" >> ${ENV_FILE}
fi
export ENV_FILE
$JAVA ${JAVA_OPTS} -Xmx${MAX_MEM} -cp ${CP} ${MAIN_CLASS}

View File

@@ -1 +0,0 @@
/*.jar

2
packaging/Manifest.txt Normal file
View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0
Main-Class: com.gpl.rpg.atcontentstudio.ATContentStudio

View File

@@ -4,7 +4,7 @@ set "ATCS_DIR=%~dp0"
set "MAX_MEM=512M"
set "CP=%ATCS_DIR%lib\*"
set "JAVA=javaw.exe"
set "JAVA_OPTS="
set "JAVA_OPTS=-DFONT_SCALE=1.0 -Dswing.aatext=true"
set "ENV_FILE=%ATCS_DIR%ATCS.env.bat"
set "MAIN_CLASS=com.gpl.rpg.atcontentstudio.ATContentStudio"

View File

@@ -1,11 +1,12 @@
!include MUI2.nsh
!define VERSION "0.6.3"
!define TRAINER_VERSION "0.1.4"
!define JAVA_BIN "javaw"
; Version will be passed as /DVERSION=vx.x.x
!define TRAINER_VERSION "0.1.5"
!define JAVA_BIN "java"
!define ATCS_SOURCE_DIR "..\..\"
Name "Andor's Trail Content Studio v${VERSION}"
OutFile "ATCS_v${VERSION}_Setup.exe"
Name "Andor's Trail Content Studio ${VERSION}"
OutFile "..\ATCS_${VERSION}_Setup.exe"
InstallDir "$PROGRAMFILES\ATCS\"
;SetCompressor /SOLID /FINAL lzma
@@ -13,10 +14,10 @@ InstallDir "$PROGRAMFILES\ATCS\"
Var StartMenuFolder
!define MUI_WELCOMEPAGE_TITLE "Welcome to Andor's Trail Content Studio installer"
!define MUI_WELCOMEPAGE_TEXT "This will install Andor's Trail Content Studio v${VERSION} installer"
!define MUI_FINISHPAGE_TEXT "Andor's Trail Content Studio v${VERSION} install completed !"
!define MUI_WELCOMEPAGE_TEXT "This will install Andor's Trail Content Studio ${VERSION}"
!define MUI_FINISHPAGE_TEXT "Andor's Trail Content Studio ${VERSION} - Install completed !"
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "Andor's Trail Content Studio"
!define MUI_PAGE_HEADER_TEXT "Installing Andor's Trail Content Studio v${VERSION}"
!define MUI_PAGE_HEADER_TEXT "Installing Andor's Trail Content Studio ${VERSION}"
;Start Menu Folder Page Configuration
@@ -46,130 +47,120 @@ Var StartMenuFolder
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
;------------------------------------------------------------------------------------
Section install
;--- Create in ...\packaging\common\ ATCS.cmd ATCT.ico ATCS.jar
SetOutPath $INSTDIR
file "ATCS.ico"
Delete "$INSTDIR\lib\*"
file "${ATCS_SOURCE_DIR}\packaging\common\ATCS.jar"
Call GetJRE
Pop $R0
; file "${ATCS_SOURCE_DIR}\packaging\common\ATCS.cmd"
; !insertmacro _ReplaceInFile "ATCS.cmd" "java.exe" "$R0" (It was too much work this way)
FileOpen $9 "ATCS.cmd" w
FileWrite $9 '@echo off$\r$\n'
FileWrite $9 '$\r$\n'
FileWrite $9 'set "ATCS_DIR=%~dp0"$\r$\n'
FileWrite $9 'set "MAX_MEM=512M"$\r$\n'
FileWrite $9 'set "CP=%ATCS_DIR%lib\*"$\r$\n'
FileWrite $9 'set "MAX_MEM=1024M"$\r$\n'
FileWrite $9 'REM required minimum java version is 11$\r$\n'
FileWrite $9 'set "JAVA=$R0"$\r$\n'
FileWrite $9 'set "JAVA_OPTS="$\r$\n'
FileWrite $9 'set "JAVA_OPTS=-DFONT_SCALE=1.0 -Dswing.aatext=true"$\r$\n'
FileWrite $9 'set "ENV_FILE=%ATCS_DIR%ATCS.env.bat"$\r$\n'
FileWrite $9 'set "MAIN_CLASS=com.gpl.rpg.atcontentstudio.ATContentStudio"$\r$\n'
FileWrite $9 '$\r$\n'
FileWrite $9 'if exist "%ENV_FILE%" ($\r$\n'
FileWrite $9 'if exist "%ENV_FILE%" ($\r$\n'
FileWrite $9 ' call "%ENV_FILE%"$\r$\n'
FileWrite $9 ') else ($\r$\n'
FileWrite $9 ' echo REM set "MAX_MEM=%MAX_MEM%">"%ENV_FILE%"$\r$\n'
FileWrite $9 ' echo REM required minimum java version is 11$\r$\n'
FileWrite $9 ' echo REM set "JAVA=%JAVA%">>"%ENV_FILE%"$\r$\n'
FileWrite $9 ' echo REM set "JAVA_OPTS=%JAVA_OPTS%">>"%ENV_FILE%"$\r$\n'
FileWrite $9 ' echo.>>"%ENV_FILE%"$\r$\n'
FileWrite $9 ')$\r$\n'
FileWrite $9 '$\r$\n'
FileWrite $9 'start "" "%JAVA%" %JAVA_OPTS% -Xmx%MAX_MEM% -cp "%CP%" %MAIN_CLASS%$\r$\n'
FileWrite $9 'start "" "%JAVA%" %JAVA_OPTS% -Xmx%MAX_MEM% -jar "%ATCS_DIR%\ATCS.jar"$\r$\n'
FileClose $9
SetOutPath "$INSTDIR\lib\"
file "jide-oss.jar"
file "ui.jar"
file "AndorsTrainer_v${TRAINER_VERSION}.jar"
file "junit-4.10.jar"
file "json_simple-1.1.jar"
file "ATCS_v${VERSION}.jar"
file "rsyntaxtextarea.jar"
file "prefuse.jar"
file "bsh-2.0b4.jar"
file "jsoup-1.10.2.jar"
SetOutPath $INSTDIR
WriteUninstaller "$INSTDIR\Uninstall.exe"
!insertmacro MUI_STARTMENU_WRITE_BEGIN "ATCS"
;Create shortcuts
;--- Create shortcuts
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Andor's Trail Content Studio.lnk" "$INSTDIR\ATCS.cmd" "" "$INSTDIR\ATCS.ico"
CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd
;------------------------------------------------------------------------------------
Section uninstall
Delete "$INSTDIR\lib\jide-oss.jar"
Delete "$INSTDIR\lib\ui.jar"
Delete "$INSTDIR\lib\junit-4.10.jar"
Delete "$INSTDIR\lib\json_simple-1.1.jar"
Delete "$INSTDIR\lib\AndorsTrainer_v${TRAINER_VERSION}.jar"
Delete "$INSTDIR\lib\ATCS_v${VERSION}.jar"
Delete "$INSTDIR\lib\rsyntaxtextarea.jar"
Delete "$INSTDIR\lib\prefuse.jar"
Delete "$INSTDIR\lib\bsh-2.0b4.jar"
Delete "$INSTDIR\lib\jsoup-1.10.2.jar"
RMDir "$INSTDIR\lib\"
Delete "$INSTDIR\ATCS.ico"
Delete "$INSTDIR\ATCS.cmd"
Delete "$INSTDIR\ATCS.env.bat"
Delete "$INSTDIR\ATCS.jar"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR"
!insertmacro MUI_STARTMENU_GETFOLDER "ATCS" $StartMenuFolder
Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk"
Delete "$SMPROGRAMS\$StartMenuFolder\Andor's Trail Content Studio.lnk"
RMDir "$SMPROGRAMS\$StartMenuFolder"
SectionEnd
;------------------------------------------------------------------------------------
Function GetJRE
;
; Find JRE (javaw.exe)
; Find JRE (java.exe)
; DISABLED 1 - in .\jre directory (JRE Installed with application)
; 2 - in JAVA_HOME environment variable
; 3 - in the registry
; 4 - assume javaw.exe in current dir or PATH
; 4 - assume java.exe in current dir or PATH
Push $R0
Push $R1
;ClearErrors
;StrCpy $R0 "$EXEDIR\jre\bin\javaw.exe"
;StrCpy $R0 "$EXEDIR\jre\bin\java.exe"
;IfFileExists $R0 JreFound
;StrCpy $R0 ""
ClearErrors
ReadEnvStr $R0 "JAVA_HOME"
StrCpy $R0 "$R0\bin\${JAVA_BIN}.exe"
IfErrors 0 JreFound
ClearErrors
ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome"
StrCpy $R0 "$R0\bin\${JAVA_BIN}.exe"
IfErrors 0 JreFound
StrCpy $R0 "${JAVA_BIN}.exe"
JreFound:
Pop $R1
Exch $R0
FunctionEnd
FunctionEnd

View File

@@ -1,20 +1,20 @@
@echo off
set "ATCS_DIR=%~dp0"
set "MAX_MEM=512M"
set "CP=%ATCS_DIR%lib\*"
set "JAVA=javaw.exe"
set "JAVA_OPTS="
set "MAX_MEM=1024M"
REM required minimum java version is 11
set "JAVA=java.exe"
set "JAVA_OPTS=-DFONT_SCALE=1.0 -Dswing.aatext=true"
set "ENV_FILE=%ATCS_DIR%ATCS.env.bat"
set "MAIN_CLASS=com.gpl.rpg.atcontentstudio.ATContentStudio"
if exist "%ENV_FILE%" (
call "%ENV_FILE%"
) else (
echo REM set "MAX_MEM=%MAX_MEM%">"%ENV_FILE%"
echo REM required minimum java version is 11
echo REM set "JAVA=%JAVA%">>"%ENV_FILE%"
echo REM set "JAVA_OPTS=%JAVA_OPTS%">>"%ENV_FILE%"
echo.>>"%ENV_FILE%"
)
start "" "%JAVA%" %JAVA_OPTS% -Xmx%MAX_MEM% -cp "%CP%" %MAIN_CLASS%
start "" "%JAVA%" %JAVA_OPTS% -Xmx%MAX_MEM% -jar "%ATCS_DIR%\ATCS.jar"

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

28
packaging/common/ATCS.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# get the directory of this script
ATCS_DIR="$(dirname "$(readlink -f "$0" || greadlink -f "$0" || stat -f "$0")")"
echo "ATCS_DIR: '${ATCS_DIR}'"
MAX_MEM="512M"
JAVA="java" # minimum required version is Java 11
JAVA_OPTS='-DFONT_SCALE=1.0 -Dswing.aatext=true'
ENV_FILE="${ATCS_DIR}/ATCS.env"
if [ -f "${ENV_FILE}" ]; then
source "${ENV_FILE}"
else
{
echo "#MAX_MEM=\"${MAX_MEM}\""
echo "#JAVA=\"${JAVA}\" # minimum required version is Java 11"
echo "#JAVA_OPTS=\"${JAVA_OPTS}\""
echo ""
}>"${ENV_FILE}"
fi
export ENV_FILE
# shellcheck disable=SC2086
# (spellchecker is disabled for this line, because we want it to be split into multiple arguments)
$JAVA ${JAVA_OPTS} -Xmx${MAX_MEM} -jar "${ATCS_DIR}/ATCS.jar"

View File

@@ -0,0 +1 @@
sh ./package.sh -windows

125
packaging/package.sh Executable file
View File

@@ -0,0 +1,125 @@
#!/bin/bash
# Script to build ATCS.jar, replicating IntelliJ artifact definition
# Linux and Windows compatible
# --- Platform Detection ---
if [ "$1" = "-windows" ]; then
echo "Got '-windows' flag. Running Windows version"
PLATFORM="WINDOWS"
else
echo "No '-windows' flag. Running Linux version"
PLATFORM="LINUX"
fi
# --- Configuration ---
PACKAGING_DIR=$(dirname "$(readlink -f "$0" || greadlink -f "$0" || stat -f "$0")") # Directory of this script
ATCS_SOURCE_DIR=$(dirname "${PACKAGING_DIR}") # Parent directory of this script, assumed to be ATCS source root
TEMP_DIR="${PACKAGING_DIR}/tmp"
JAR_LOCATION="${PACKAGING_DIR}/ATCS.jar" # Output JAR location as per script
MANIFEST_LOCATION="${PACKAGING_DIR}/Manifest.txt"
VERSION_FILE="${ATCS_SOURCE_DIR}/res/ATCS_latest"
SOURCE_BASE_DIR="${ATCS_SOURCE_DIR}/src" # Base directory for standard source code
LIB_BASE_DIR="${ATCS_SOURCE_DIR}/lib" # Base directory for libraries
# --- **ADDITIONAL SOURCE CODE FOLDERS** ---
EXTRA_SOURCE_DIRS=(
"hacked-libtiled"
"minify"
"siphash-zackehh/src/main/java"
)
# --- Libraries to include ---
LIBRARIES=(
"bsh-2.0b4.jar"
"jide-oss.jar"
"json_simple-1.1.jar"
"jsoup-1.10.2.jar"
"junit-4.10.jar"
"prefuse.jar"
"rsyntaxtextarea.jar"
"ui.jar"
)
# --- Get version ---
echo "Getting version"
VERSION=$(tr -d '[:space:]' < "${VERSION_FILE}")
echo "Got version ${VERSION}"
# --- Prepare temporary directory ---
echo "Removing tmp folder"
rm -rf "${TEMP_DIR}"
echo "Recreating tmp folder"
mkdir -p "${TEMP_DIR}"
# --- **EXTRACT lib files directly to TEMP_DIR** ---
echo 'Extracting lib files to TEMP_DIR'
for LIB in "${LIBRARIES[@]}"; do
echo "Extracting library: ${LIB}"
unzip -qo "${LIB_BASE_DIR}/${LIB}" -d "${TEMP_DIR}" # Extract JAR contents to TEMP_DIR root
done
# --- Set ClassPath ---
echo "Getting source files"
# Find all java files in source directories
SOURCE_FILES=$(find "${SOURCE_BASE_DIR}" "${EXTRA_SOURCE_DIRS[@]/#/${ATCS_SOURCE_DIR}/}" -name "*.java" -print)
#echo "SourceFiles: ${SOURCE_FILES}"
echo ""
# --- Build Java classes ---
echo 'Building java classes'
# shellcheck disable=SC2086
# (we need word splitting here to pass multiple files)
javac -cp "${TEMP_DIR}" -d "${TEMP_DIR}" ${SOURCE_FILES}
if [ $? -ne 0 ]; then
echo "Compilation failed. Please check errors above."
exit 1
fi
echo "Compilation successful"
# --- Copy res stuff to temp folder ---
echo "Copying some stuff to temp folder"
cp -r "${ATCS_SOURCE_DIR}"/res/* "${TEMP_DIR}/"
mkdir -p "${TEMP_DIR}/com/gpl/rpg/atcontentstudio/img"
mkdir -p "${TEMP_DIR}/tiled/io/resources/"
cp -r "${ATCS_SOURCE_DIR}"/src/com/gpl/rpg/atcontentstudio/img/* "${TEMP_DIR}/com/gpl/rpg/atcontentstudio/img/" # some icons
cp -r "${ATCS_SOURCE_DIR}"/hacked-libtiled/tiled/io/resources/* "${TEMP_DIR}/tiled/io/resources/" # dtd file for tmx maps
cp "${VERSION_FILE}" "${TEMP_DIR}/" # Copy version file
# --- Create JAR file ---
echo ""
echo "Creating jar at location: ${JAR_LOCATION}"
cd "${TEMP_DIR}" || exit # Change to temp dir for JAR command
# JAR command WITHOUT lib directory
jar cfm "${JAR_LOCATION}" "${MANIFEST_LOCATION}" -C . .
if [ $? -ne 0 ]; then
echo "JAR creation failed."
exit 1
fi
cd "${PACKAGING_DIR}" || exit # Go back to packaging dir
echo ''
echo "Done creating jar at ${JAR_LOCATION}"
cp -f "${JAR_LOCATION}" "${PACKAGING_DIR}/common/ATCS.jar" # Copy JAR to versioned name
# --- Create archive ---
cd "${PACKAGING_DIR}" || exit
echo "Creating archive"
if [ "$PLATFORM" = "WINDOWS" ]; then
# Use PowerShell's Compress-Archive which is available by default on Windows
powershell.exe -Command "Compress-Archive -Path './common/*' -DestinationPath './ATCS_${VERSION}.zip' -Force"
else
# Use zip command on Linux
zip -r "ATCS_${VERSION}.zip" common/* # archive the 'common' folder which now contains the JAR and libs
fi
if [ $? -ne 0 ]; then
echo "Archive creation failed."
exit 1
fi
echo "Created archive at ${PACKAGING_DIR}/ATCS_${VERSION}.zip"
echo "Script finished."

1
res/ATCS_latest Normal file
View File

@@ -0,0 +1 @@
v0.6.24

43
res/LICENSE.minify.txt Normal file
View File

@@ -0,0 +1,43 @@
----------------------
Minify.java 2015-10-04
----------------------
Copyright (c) 2015 Charles Bihis (www.whoischarles.com)
This work is an adaptation of JSMin.java published by John Reilly which is a translation from C to Java of jsmin.c
published by Douglas Crockford. Permission is hereby granted to use this Java version under the same conditions as
the original jsmin.c on which all of these derivatives are based.
---------------------
JSMin.java 2006-02-13
---------------------
Copyright (c) 2006 John Reilly (www.inconspicuous.org)
This work is a translation from C to Java of jsmin.c published by Douglas Crockford. Permission is hereby granted to
use the Java version under the same conditions as the jsmin.c on which it is based.
------------------
jsmin.c 2003-04-21
------------------
Copyright (c) 2002 Douglas Crockford (www.crockford.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,64 +1,94 @@
atcs.spritesheet.actorconditions_1.category=actorcondition
atcs.spritesheet.actorconditions_2.category=actorcondition
atcs.spritesheet.actorconditions_japozero.category=actorcondition
atcs.spritesheet.actorconditions_newb.category=actorcondition
atcs.spritesheet.actorconditions_omi1.category=actorcondition
atcs.spritesheet.actorconditions_omi2.category=actorcondition
atcs.spritesheet.effect_blood3.animate=true
atcs.spritesheet.effect_blood4.animate=true
atcs.spritesheet.effect_bluetentacle.animate=true
atcs.spritesheet.effect_heal2.animate=true
atcs.spritesheet.effect_miss1.animate=true
atcs.spritesheet.effect_poison1.animate=true
atcs.spritesheet.effect_tometik1.animate=true
atcs.spritesheet.effect_tometik2.animate=true
atcs.spritesheet.items_armours.category=item
atcs.spritesheet.items_armours_2.category=item
atcs.spritesheet.items_armours_3.category=item
atcs.spritesheet.items_weapons.category=item
atcs.spritesheet.items_weapons_2.category=item
atcs.spritesheet.items_weapons_3.category=item
atcs.spritesheet.items_jewelry.category=item
atcs.spritesheet.items_rings_1.category=item
atcs.spritesheet.items_necklaces_1.category=item
atcs.spritesheet.items_consumables.category=item
atcs.spritesheet.items_japozero.category=item
atcs.spritesheet.items_books.category=item
atcs.spritesheet.items_consumables.category=item
atcs.spritesheet.items_consumables_omi1.category=item
atcs.spritesheet.items_feygard1.category=item
atcs.spritesheet.items_g03_package_omi1.category=item
atcs.spritesheet.items_japozero.category=item
atcs.spritesheet.items_jewelry.category=item
atcs.spritesheet.items_misc.category=item
atcs.spritesheet.items_misc_2.category=item
atcs.spritesheet.items_misc_3.category=item
atcs.spritesheet.items_misc_4.category=item
atcs.spritesheet.items_misc_5.category=item
atcs.spritesheet.items_misc_6.category=item
atcs.spritesheet.items_necklaces_1.category=item
atcs.spritesheet.items_newb.category=item
atcs.spritesheet.items_omgeeky.category=item
atcs.spritesheet.items_omi2.category=item
atcs.spritesheet.items_phoenix01.category=item
atcs.spritesheet.items_reterski_1.category=item
atcs.spritesheet.items_rijackson_1.category=item
atcs.spritesheet.items_rings_1.category=item
atcs.spritesheet.items_tometik1.category=item
atcs.spritesheet.items_tometik2.category=item
atcs.spritesheet.items_tometik3.category=item
atcs.spritesheet.items_weapons.category=item
atcs.spritesheet.items_weapons_2.category=item
atcs.spritesheet.items_weapons_3.category=item
atcs.spritesheet.monsters_armor1.category=monster
atcs.spritesheet.monsters_arulirs.category=monster
atcs.spritesheet.monsters_cats.category=monster
atcs.spritesheet.monsters_dogs.category=monster
atcs.spritesheet.monsters_eye1.category=monster
atcs.spritesheet.monsters_eye2.category=monster
atcs.spritesheet.monsters_eye3.category=monster
atcs.spritesheet.monsters_eye4.category=monster
atcs.spritesheet.monsters_fatboy73.category=monster
atcs.spritesheet.monsters_ghost1.category=monster
atcs.spritesheet.monsters_hydra1.category=monster
atcs.spritesheet.monsters_hydra1.sizex=64
atcs.spritesheet.monsters_hydra1.sizey=64
atcs.spritesheet.monsters_gisons.category=monster
atcs.spritesheet.monsters_guynmart.category=monster
atcs.spritesheet.monsters_insects.category=monster
atcs.spritesheet.monsters_johny.category=monster
atcs.spritesheet.monsters_karvis1.category=monster
atcs.spritesheet.monsters_karvis2.category=monster
atcs.spritesheet.monsters_ld1.category=monster
atcs.spritesheet.monsters_ld2.category=monster
atcs.spritesheet.monsters_liches.category=monster
atcs.spritesheet.monsters_mage.category=monster
atcs.spritesheet.monsters_mage2.category=monster
atcs.spritesheet.monsters_maksiu1.category=monster
atcs.spritesheet.monsters_man1.category=monster
atcs.spritesheet.monsters_men.category=monster
atcs.spritesheet.monsters_men2.category=monster
atcs.spritesheet.monsters_misc.category=monster
atcs.spritesheet.monsters_newb_1.category=monster
atcs.spritesheet.monsters_omi1.category=monster
atcs.spritesheet.monsters_omi1_b.category=monster
atcs.spritesheet.monsters_omi2.category=monster
atcs.spritesheet.monsters_phoenix01.category=monster
atcs.spritesheet.monsters_rats.category=monster
atcs.spritesheet.monsters_rogue1.category=monster
atcs.spritesheet.monsters_skeleton1.category=monster
atcs.spritesheet.monsters_skeleton2.category=monster
atcs.spritesheet.monsters_snakes.category=monster
atcs.spritesheet.monsters_warrior1.category=monster
atcs.spritesheet.monsters_wraiths.category=monster
atcs.spritesheet.monsters_zombie1.category=monster
atcs.spritesheet.monsters_zombie2.category=monster
atcs.spritesheet.monsters_karvis1.category=monster
atcs.spritesheet.monsters_karvis2.category=monster
atcs.spritesheet.monsters_redshrike1.category=monster
atcs.spritesheet.monsters_rltiles1.category=monster
atcs.spritesheet.monsters_rltiles2.category=monster
atcs.spritesheet.monsters_rltiles3.category=monster
atcs.spritesheet.monsters_rltiles4.category=monster
atcs.spritesheet.monsters_redshrike1.category=monster
atcs.spritesheet.monsters_ld1.category=monster
atcs.spritesheet.monsters_ld2.category=monster
atcs.spritesheet.monsters_rogue1.category=monster
atcs.spritesheet.monsters_skeleton1.category=monster
atcs.spritesheet.monsters_skeleton2.category=monster
atcs.spritesheet.monsters_snakes.category=monster
atcs.spritesheet.monsters_tometik1.category=monster
atcs.spritesheet.monsters_tometik2.category=monster
atcs.spritesheet.monsters_tometik3.category=monster
@@ -69,19 +99,36 @@ atcs.spritesheet.monsters_tometik7.category=monster
atcs.spritesheet.monsters_tometik8.category=monster
atcs.spritesheet.monsters_tometik9.category=monster
atcs.spritesheet.monsters_tometik10.category=monster
atcs.spritesheet.monsters_warrior1.category=monster
atcs.spritesheet.monsters_unknown.category=monster
atcs.spritesheet.monsters_wraiths.category=monster
atcs.spritesheet.monsters_zombie1.category=monster
atcs.spritesheet.monsters_zombie2.category=monster
atcs.spritesheet.monsters_bosses_2x2.category=monster
atcs.spritesheet.monsters_bosses_2x2.sizex=64
atcs.spritesheet.monsters_bosses_2x2.sizey=64
atcs.spritesheet.monsters_cyclops.category=monster
atcs.spritesheet.monsters_cyclops.sizex=64
atcs.spritesheet.monsters_cyclops.sizey=96
atcs.spritesheet.monsters_demon1.category=monster
atcs.spritesheet.monsters_demon1.sizex=64
atcs.spritesheet.monsters_demon1.sizey=64
atcs.spritesheet.monsters_demon2.category=monster
atcs.spritesheet.monsters_demon2.sizex=64
atcs.spritesheet.monsters_demon2.sizey=64
atcs.spritesheet.monsters_cyclops.category=monster
atcs.spritesheet.monsters_cyclops.sizex=64
atcs.spritesheet.monsters_cyclops.sizey=96
atcs.spritesheet.effect_blood3.animate=true
atcs.spritesheet.effect_blood4.animate=true
atcs.spritesheet.effect_bluetentacle.animate=true
atcs.spritesheet.effect_heal2.animate=true
atcs.spritesheet.effect_poison1.animate=true
atcs.spritesheet.effect_tometik1.animate=true
atcs.spritesheet.effect_tometik2.animate=true
atcs.spritesheet.monsters_giantbasilisk.category=monster
atcs.spritesheet.monsters_giantbasilisk.sizex=64
atcs.spritesheet.monsters_giantbasilisk.sizey=64
atcs.spritesheet.monsters_hydra1.category=monster
atcs.spritesheet.monsters_hydra1.sizex=64
atcs.spritesheet.monsters_hydra1.sizey=64
atcs.spritesheet.monsters_newb_2.category=monster
atcs.spritesheet.monsters_newb_2.sizex=64
atcs.spritesheet.monsters_newb_2.sizey=32
atcs.spritesheet.monsters_newb_3.category=monster
atcs.spritesheet.monsters_newb_3.sizex=64
atcs.spritesheet.monsters_newb_3.sizey=64
atcs.spritesheet.monsters_newb_4.category=monster
atcs.spritesheet.monsters_newb_4.sizex=32
atcs.spritesheet.monsters_newb_4.sizey=64

View File

@@ -1,6 +1,11 @@
package com.zackehh.siphash;
import static com.zackehh.siphash.SipHashConstants.*;
import static com.zackehh.siphash.SipHashConstants.DEFAULT_C;
import static com.zackehh.siphash.SipHashConstants.DEFAULT_D;
import static com.zackehh.siphash.SipHashConstants.INITIAL_V0;
import static com.zackehh.siphash.SipHashConstants.INITIAL_V1;
import static com.zackehh.siphash.SipHashConstants.INITIAL_V2;
import static com.zackehh.siphash.SipHashConstants.INITIAL_V3;
/**
* Main entry point for SipHash, providing a basic hash

6
src/META-INF/MANIFEST.MF Normal file
View File

@@ -0,0 +1,6 @@
Manifest-Version: 1.0
Main-Class: com.gpl.rpg.atcontentstudio.ATContentStudio
Class-Path: jide-oss.jar jsoup-1.10.2.jar ui.jar junit-4.10.jar AndorsTr
ainer_v0.1.5.jar prefuse.jar rsyntaxtextarea.jar bsh-2.0b4.jar json_sim
ple-1.1.jar

View File

@@ -1,98 +1,254 @@
package com.gpl.rpg.atcontentstudio;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import prefuse.data.expression.parser.ExpressionParser;
import com.gpl.rpg.atcontentstudio.model.Workspace;
import com.gpl.rpg.atcontentstudio.ui.StudioFrame;
import com.gpl.rpg.atcontentstudio.ui.WorkerDialog;
import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector;
public class ATContentStudio {
public static final String APP_NAME = "Andor's Trail Content Studio";
public static final String APP_VERSION = "v0.6.3";
public static boolean STARTED = false;
public static StudioFrame frame = null;
//Need to keep a strong reference to it, to avoid garbage collection that'll reset these loggers.
public static final List<Logger> configuredLoggers = new LinkedList<Logger>();
/**
* @param args
*/
public static void main(String[] args) {
ConfigCache.init();
try {
String laf = ConfigCache.getFavoriteLaFClassName();
if (laf == null) laf = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(laf);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
//Need to keep a strong reference to it, to avoid garbage collection that'll reset this setting.
Logger l = Logger.getLogger(ExpressionParser.class.getName());
l.setLevel(Level.OFF);
configuredLoggers.add(l);
final WorkspaceSelector wsSelect = new WorkspaceSelector();
wsSelect.pack();
Dimension sdim = Toolkit.getDefaultToolkit().getScreenSize();
Dimension wdim = wsSelect.getSize();
wsSelect.setLocation((sdim.width - wdim.width)/2, (sdim.height - wdim.height)/2);
wsSelect.setVisible(true);
wsSelect.addWindowListener(new WindowAdapter() {
@Override
public synchronized void windowClosed(WindowEvent e) {
if (wsSelect.selected != null && !STARTED) {
ATContentStudio.STARTED = true;
final File workspaceRoot = new File(wsSelect.selected);
WorkerDialog.showTaskMessage("Loading your workspace...", null, new Runnable(){
public void run() {
Workspace.setActive(workspaceRoot);
frame = new StudioFrame(APP_NAME+" "+APP_VERSION);
frame.setVisible(true);
frame.setDefaultCloseOperation(StudioFrame.DO_NOTHING_ON_CLOSE);
};
});
for (File f : ConfigCache.getKnownWorkspaces()) {
if (workspaceRoot.equals(f)) {
if (!workspaceRoot.equals(ConfigCache.getLatestWorkspace())) {
ConfigCache.setLatestWorkspace(f);
}
return;
}
}
ConfigCache.addWorkspace(workspaceRoot);
ConfigCache.setLatestWorkspace(workspaceRoot);
}
}
});
}
}
package com.gpl.rpg.atcontentstudio;
import com.gpl.rpg.atcontentstudio.model.Workspace;
import com.gpl.rpg.atcontentstudio.ui.StudioFrame;
import com.gpl.rpg.atcontentstudio.ui.WorkerDialog;
import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector;
import prefuse.data.expression.parser.ExpressionParser;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.plaf.FontUIResource;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.http.HttpTimeoutException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ATContentStudio {
public static final String APP_NAME = "Andor's Trail Content Studio";
public static final String APP_VERSION = readVersionFromFile();
public static final String CHECK_UPDATE_URL = "https://andorstrail.com/static/ATCS_latest";
public static final String DOWNLOAD_URL = "https://andorstrail.com/viewtopic.php?f=6&t=4806";
public static final String FONT_SCALE_ENV_VAR_NAME = "FONT_SCALE";
public static boolean STARTED = false;
public static float SCALING = 1.0f;
public static StudioFrame frame = null;
// Need to keep a strong reference to it, to avoid garbage collection that'll
// reset these loggers.
public static final List<Logger> configuredLoggers = new LinkedList<Logger>();
/**
* @param args
*/
public static void main(String[] args) {
String fontScaling = System.getProperty(FONT_SCALE_ENV_VAR_NAME);
Float fontScale;
if (fontScaling != null) {
try {
fontScale = Float.parseFloat(fontScaling);
SCALING = fontScale;
} catch (NumberFormatException e) {
System.err.println("Failed to parse font scaling parameter. Using default.");
e.printStackTrace();
}
}
ConfigCache.init();
String laf = ConfigCache.getFavoriteLaFClassName();
setLookAndFeel(laf);
// Need to keep a strong reference to it, to avoid garbage collection that'll
// reset this setting.
Logger l = Logger.getLogger(ExpressionParser.class.getName());
l.setLevel(Level.OFF);
configuredLoggers.add(l);
final WorkspaceSelector wsSelect = new WorkspaceSelector();
wsSelect.pack();
Dimension sdim = Toolkit.getDefaultToolkit().getScreenSize();
Dimension wdim = wsSelect.getSize();
wsSelect.setLocation((sdim.width - wdim.width) / 2, (sdim.height - wdim.height) / 2);
wsSelect.setVisible(true);
wsSelect.addWindowListener(new WindowAdapter() {
@Override
public synchronized void windowClosed(WindowEvent e) {
if (wsSelect.selected != null && !STARTED) {
ATContentStudio.STARTED = true;
final File workspaceRoot = new File(wsSelect.selected);
WorkerDialog.showTaskMessage("Loading your workspace...", null, new Runnable() {
public void run() {
Workspace.setActive(workspaceRoot);
if (Workspace.activeWorkspace.settings.useInternet.getCurrentValue()
&& Workspace.activeWorkspace.settings.checkUpdates.getCurrentValue()) {
new Thread() {
public void run() {
checkUpdate();
}
}.start();
}
frame = new StudioFrame(APP_NAME + " " + APP_VERSION);
frame.setVisible(true);
frame.setDefaultCloseOperation(StudioFrame.DO_NOTHING_ON_CLOSE);
}
});
for (File f : ConfigCache.getKnownWorkspaces()) {
if (workspaceRoot.equals(f)) {
if (!workspaceRoot.equals(ConfigCache.getLatestWorkspace())) {
ConfigCache.setLatestWorkspace(f);
}
return;
}
}
ConfigCache.addWorkspace(workspaceRoot);
ConfigCache.setLatestWorkspace(workspaceRoot);
}
}
});
}
public static void setLookAndFeel(String laf) {
if (laf == null)
{
System.out.println("No look and feel specified, using system default.");
laf = UIManager.getSystemLookAndFeelClassName();
}
System.out.println("Info: Setting look and feel to: " + laf);
try {
UIManager.setLookAndFeel(laf);
} catch (ClassNotFoundException e) {
System.err.println("Failed to load system look and feel. ");
System.err.println("Installed look and feel classes: ");
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
System.err.println(" " + info.getName() + " (" + info.getClassName() + ")");
}
System.err.println("Tried to load: " + laf + " but got this error:");
e.printStackTrace();
} catch (InstantiationException | UnsupportedLookAndFeelException | IllegalAccessException e) {
e.printStackTrace();
}
var newLaF = UIManager.getLookAndFeel();
System.out.println("Using look and feel: " + newLaF.getName() + " (" + newLaF.getClass().getName() + ")");
scaleUIFont();
}
private static void checkUpdate() {
BufferedReader in = null;
try {
URL url = new URL(CHECK_UPDATE_URL);
in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine, lastLine = null;
while ((inputLine = in.readLine()) != null) {
lastLine = inputLine;
}
if (lastLine != null && !lastLine.equals(APP_VERSION)) {
// for copying style
JLabel label = new JLabel();
Font font = label.getFont();
Color color = label.getBackground();
// create some css from the label's font
StringBuffer style = new StringBuffer("font-family:" + font.getFamily() + ";");
style.append("font-weight:" + (font.isBold() ? "bold" : "normal") + ";");
style.append("font-size:" + font.getSize() + "pt;");
style.append("background-color: rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue()
+ ");");
JEditorPane ep = new JEditorPane("text/html",
"<html><body style=\"" + style + "\">" + "You are not running the latest ATCS version.<br/>"
+ "You can get the latest version (" + lastLine + ") by clicking the link below.<br/>"
+ "<a href=\"" + DOWNLOAD_URL + "\">" + DOWNLOAD_URL + "</a><br/>" + "<br/>"
+ "</body></html>");
ep.setEditable(false);
ep.setBorder(null);
ep.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
try {
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
Desktop.getDesktop().browse(e.getURL().toURI());
}
} catch (IOException e1) {
e1.printStackTrace();
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
}
});
JOptionPane.showMessageDialog(null, ep, "Update available", JOptionPane.INFORMATION_MESSAGE);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (HttpTimeoutException e) {
System.out.println("Could not connect to url to check for updates (timeout): " + CHECK_UPDATE_URL);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Server returned HTTP response code:")) {
System.out.println("Could not fetch current version from server to check for updates (non-success-status): " + e.getMessage());
} else {
System.out.println("Could not check for updates: '" + CHECK_UPDATE_URL + "' - " + e.getMessage());
}
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void scaleUIFont() {
if (SCALING != 1.0f) {
System.out.println("Scaling fonts to " + SCALING);
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
Map<Object, Object> newDefaults = new HashMap<Object, Object>();
for (Enumeration<Object> e = defaults.keys(); e.hasMoreElements(); ) {
Object key = e.nextElement();
Object value = defaults.get(key);
if (value instanceof Font) {
Font font = (Font) value;
int newSize = (int) (font.getSize() * SCALING);
if (value instanceof FontUIResource) {
newDefaults.put(key, new FontUIResource(font.getName(), font.getStyle(), newSize));
} else {
newDefaults.put(key, new Font(font.getName(), font.getStyle(), newSize));
}
}
}
for (Object key : newDefaults.keySet()) {
defaults.put(key, newDefaults.get(key));
}
}
}
private static String readVersionFromFile() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
Objects.requireNonNull(ATContentStudio.class.getResourceAsStream("/ATCS_latest"))))) {
return reader.readLine();
} catch (IOException e) {
e.printStackTrace();
return "unknown";
}
}
}

View File

@@ -1,103 +1,104 @@
package com.gpl.rpg.atcontentstudio;
import com.gpl.rpg.atcontentstudio.io.SettingsSave;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.gpl.rpg.atcontentstudio.io.SettingsSave;
public class ConfigCache implements Serializable {
private static final long serialVersionUID = 4584324644282843961L;
private static final File CONFIG_CACHE_STORAGE;
private static ConfigCache instance = null;
private static final long serialVersionUID = 4584324644282843961L;
private static final File CONFIG_CACHE_STORAGE;
private static ConfigCache instance = null;
static {
if (System.getenv("APPDATA") != null) {
CONFIG_CACHE_STORAGE = new File(System.getenv("APPDATA")+File.separator+ATContentStudio.APP_NAME+File.separator+"configCache" );
} else {
CONFIG_CACHE_STORAGE = new File(System.getenv("HOME")+File.separator+"."+ATContentStudio.APP_NAME+File.separator+"configCache" );
}
CONFIG_CACHE_STORAGE.getParentFile().mkdirs();
if (CONFIG_CACHE_STORAGE.exists()) {
ConfigCache.instance = (ConfigCache) SettingsSave.loadInstance(CONFIG_CACHE_STORAGE, "Configuration cache");
if (ConfigCache.instance == null) {
ConfigCache.instance = new ConfigCache();
}
} else {
ConfigCache.instance = new ConfigCache();
}
}
static {
if (System.getenv("APPDATA") != null) {
CONFIG_CACHE_STORAGE = new File(System.getenv("APPDATA") + File.separator + ATContentStudio.APP_NAME + File.separator + "configCache");
} else {
CONFIG_CACHE_STORAGE = new File(System.getenv("HOME") + File.separator + "." + ATContentStudio.APP_NAME + File.separator + "configCache");
}
CONFIG_CACHE_STORAGE.getParentFile().mkdirs();
if (CONFIG_CACHE_STORAGE.exists()) {
ConfigCache.instance = (ConfigCache) SettingsSave.loadInstance(CONFIG_CACHE_STORAGE, "Configuration cache");
if (ConfigCache.instance == null) {
ConfigCache.instance = new ConfigCache();
}
} else {
ConfigCache.instance = new ConfigCache();
}
}
private void save() {
SettingsSave.saveInstance(instance, ConfigCache.CONFIG_CACHE_STORAGE, "Configuration cache");
}
private void save() {
SettingsSave.saveInstance(instance, ConfigCache.CONFIG_CACHE_STORAGE, "Configuration cache");
}
private List<File> knownWorkspaces = new ArrayList<File>();
private File latestWorkspace = null;
private String favoriteLaFClassName = null;
private boolean[] notifConfig = new boolean[]{true, true, true, true};
private List<File> knownWorkspaces = new ArrayList<File>();
private File latestWorkspace = null;
private String favoriteLaFClassName = null;
private boolean[] notifConfig = new boolean[]{true, true, true, true};
public static List<File> getKnownWorkspaces() {
return instance.knownWorkspaces;
}
public static void addWorkspace(File w) {
instance.knownWorkspaces.add(w);
instance.save();
}
public static void removeWorkspace(File w) {
instance.knownWorkspaces.remove(w);
instance.save();
}
public static File getLatestWorkspace() {
return instance.latestWorkspace;
}
public static void setLatestWorkspace(File latestWorkspace) {
instance.latestWorkspace = latestWorkspace;
instance.save();
}
public static List<File> getKnownWorkspaces() {
return instance.knownWorkspaces;
}
public static String getFavoriteLaFClassName() {
return instance.favoriteLaFClassName;
}
public static void setFavoriteLaFClassName(String favoriteLaFClassName) {
instance.favoriteLaFClassName = favoriteLaFClassName;
instance.save();
}
public static void addWorkspace(File w) {
instance.knownWorkspaces.add(w);
instance.save();
}
public static void putNotifViewConfig(boolean[] view) {
for (int i=instance.notifConfig.length; i<0; --i) {
instance.notifConfig[i] = view[i];
}
instance.save();
}
public static void removeWorkspace(File w) {
instance.knownWorkspaces.remove(w);
instance.save();
}
public static boolean[] getNotifViewConfig() {
if (instance == null || instance.notifConfig == null) {
//Not yet initialized. All flags on to help corner out init issues.
return new boolean[]{true, true, true, true};
}
return instance.notifConfig;
}
public static File getLatestWorkspace() {
return instance.latestWorkspace;
}
public static void init() {}
public static void setLatestWorkspace(File latestWorkspace) {
instance.latestWorkspace = latestWorkspace;
instance.save();
}
public static void clear() {
instance.knownWorkspaces.clear();
setFavoriteLaFClassName(null);
instance.notifConfig = new boolean[]{true, true, true, true};
instance.save();
}
public static String getFavoriteLaFClassName() {
return instance.favoriteLaFClassName;
}
public static void setFavoriteLaFClassName(String favoriteLaFClassName) {
instance.favoriteLaFClassName = favoriteLaFClassName;
instance.save();
}
public static void putNotifViewConfig(boolean[] view) {
for (int i = instance.notifConfig.length; i < 0; --i) {
instance.notifConfig[i] = view[i];
}
instance.save();
}
public static boolean[] getNotifViewConfig() {
if (instance == null || instance.notifConfig == null) {
//Not yet initialized. All flags on to help corner out init issues.
return new boolean[]{true, true, true, true};
}
return instance.notifConfig;
}
public static void init() {
}
public static void clear() {
instance.knownWorkspaces.clear();
setFavoriteLaFClassName(null);
instance.notifConfig = new boolean[]{true, true, true, true};
instance.save();
}
}

View File

@@ -6,87 +6,87 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class Notification {
public static List<Notification> notifs = new ArrayList<Notification>();
private static List<NotificationListener> listeners = new CopyOnWriteArrayList<NotificationListener>();
public static boolean showS = true, showI = true, showW = true, showE = true;
static {
boolean[] config = ConfigCache.getNotifViewConfig();
showS = config[0];
showI = config[1];
showW = config[2];
showE = config[3];
}
public static enum Type {
SUCCESS,
INFO,
WARN,
ERROR
}
public Type type;
public String text;
public Notification(Type type, String text) {
this.type = type;
this.text = text;
}
public String toString() {
return "["+type.toString()+"] "+text;
}
public static void clear() {
int i = notifs.size();
notifs.clear();
for (NotificationListener l : listeners) {
l.onListCleared(i);
}
}
public static List<Notification> notifs = new ArrayList<Notification>();
private static List<NotificationListener> listeners = new CopyOnWriteArrayList<NotificationListener>();
public static boolean showS, showI, showW, showE;
static {
boolean[] config = ConfigCache.getNotifViewConfig();
showS = config[0];
showI = config[1];
showW = config[2];
showE = config[3];
}
public static enum Type {
SUCCESS,
INFO,
WARN,
ERROR
}
public Type type;
public String text;
public Notification(Type type, String text) {
this.type = type;
this.text = text;
}
public String toString() {
return "[" + type.toString() + "] " + text;
}
public static void clear() {
int i = notifs.size();
notifs.clear();
for (NotificationListener l : listeners) {
l.onListCleared(i);
}
}
public static void addSuccess(String text) {
if (!showS) return;
Notification n = new Notification(Notification.Type.SUCCESS, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addInfo(String text) {
if (!showI) return;
Notification n = new Notification(Notification.Type.INFO, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addWarn(String text) {
if (!showW) return;
Notification n = new Notification(Notification.Type.WARN, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addError(String text) {
if (!showE) return;
Notification n = new Notification(Notification.Type.ERROR, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addNotificationListener(NotificationListener l) {
listeners.add(l);
}
public static void removeNotificationListener(NotificationListener l) {
listeners.remove(l);
}
public static void addSuccess(String text) {
if (!showS) return;
Notification n = new Notification(Notification.Type.SUCCESS, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addInfo(String text) {
if (!showI) return;
Notification n = new Notification(Notification.Type.INFO, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addWarn(String text) {
if (!showW) return;
Notification n = new Notification(Notification.Type.WARN, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addError(String text) {
if (!showE) return;
Notification n = new Notification(Notification.Type.ERROR, text);
notifs.add(n);
for (NotificationListener l : listeners) {
l.onNewNotification(n);
}
}
public static void addNotificationListener(NotificationListener l) {
listeners.add(l);
}
public static void removeNotificationListener(NotificationListener l) {
listeners.remove(l);
}
}

View File

@@ -2,7 +2,8 @@ package com.gpl.rpg.atcontentstudio;
public interface NotificationListener {
public void onNewNotification(Notification n);
public void onListCleared(int i);
public void onNewNotification(Notification n);
public void onListCleared(int i);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -4,50 +4,50 @@ import java.io.StringWriter;
public class JsonPrettyWriter extends StringWriter {
private int indentLevel = 0;
private String indentText = " ";
public JsonPrettyWriter() {
super();
}
public JsonPrettyWriter(String indent) {
super();
this.indentText = indent;
}
private int indentLevel = 0;
private String indentText = " ";
@Override
public void write(int c) {
if (((char) c) == '[' || ((char) c) == '{') {
super.write(c);
super.write('\n');
indentLevel++;
writeIndentation();
} else if (((char) c) == ',') {
super.write(c);
super.write('\n');
writeIndentation();
} else if (((char) c) == ']' || ((char) c) == '}') {
super.write('\n');
indentLevel--;
writeIndentation();
super.write(c);
} else {
super.write(c);
}
public JsonPrettyWriter() {
super();
}
}
//Horrible hack to remove the horrible escaping of slashes in json-simple....
@Override
public void write(String str) {
super.write(str.replaceAll("\\\\/", "/"));
}
public JsonPrettyWriter(String indent) {
super();
this.indentText = indent;
}
private void writeIndentation() {
for (int i = 0; i < indentLevel; i++) {
super.write(indentText);
}
}
@Override
public void write(int c) {
if (((char) c) == '[' || ((char) c) == '{') {
super.write(c);
super.write('\n');
indentLevel++;
writeIndentation();
} else if (((char) c) == ',') {
super.write(c);
super.write('\n');
writeIndentation();
} else if (((char) c) == ']' || ((char) c) == '}') {
super.write('\n');
indentLevel--;
writeIndentation();
super.write(c);
} else {
super.write(c);
}
}
//Horrible hack to remove the horrible escaping of slashes in json-simple....
@Override
public void write(String str) {
super.write(str.replaceAll("\\\\/", "/"));
}
private void writeIndentation() {
for (int i = 0; i < indentLevel; i++) {
super.write(indentText);
}
}
}

View File

@@ -0,0 +1,8 @@
package com.gpl.rpg.atcontentstudio.io;
import java.util.Map;
public interface JsonSerializable {
Map toMap();
void fromMap(Map map);
}

View File

@@ -1,76 +1,70 @@
package com.gpl.rpg.atcontentstudio.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import com.gpl.rpg.atcontentstudio.Notification;
import java.io.*;
public class SettingsSave {
public static void saveInstance(Object obj, File f, String type) {
try {
FileOutputStream fos = new FileOutputStream(f);
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.flush();
oos.close();
Notification.addSuccess(type+" successfully saved.");
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type+" saving error: "+e.getMessage());
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type+" saving error: "+e.getMessage());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Notification.addError(type+" saving error: "+e.getMessage());
}
}
public static Object loadInstance(File f, String type) {
FileInputStream fis;
Object result = null;
try {
fis = new FileInputStream(f);
ObjectInputStream ois;
try {
ois = new ObjectInputStream(fis);
try {
result = ois.readObject();
Notification.addSuccess(type+" successfully loaded.");
} catch (ClassNotFoundException e) {
e.printStackTrace();
Notification.addError(type+" loading error: "+e.getMessage());
} finally {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type+" loading error: "+e.getMessage());
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type+" loading error: "+e.getMessage());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Notification.addError(type+" loading error: "+e.getMessage());
}
return result;
}
public static void saveInstance(Object obj, File f, String type) {
try {
FileOutputStream fos = new FileOutputStream(f);
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.flush();
oos.close();
Notification.addSuccess(type + " successfully saved.");
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type + " saving error: " + e.getMessage());
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type + " saving error: " + e.getMessage());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Notification.addError(type + " saving error: " + e.getMessage());
}
}
public static Object loadInstance(File f, String type) {
FileInputStream fis;
Object result = null;
try {
fis = new FileInputStream(f);
ObjectInputStream ois;
try {
ois = new ObjectInputStream(fis);
try {
result = ois.readObject();
Notification.addSuccess(type + " successfully loaded.");
} catch (ClassNotFoundException e) {
e.printStackTrace();
Notification.addError(type + " loading error: " + e.getMessage());
} finally {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type + " loading error: " + e.getMessage());
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
Notification.addError(type + " loading error: " + e.getMessage());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
Notification.addError(type + " loading error: " + e.getMessage());
}
return result;
}
}

View File

@@ -1,124 +1,135 @@
package com.gpl.rpg.atcontentstudio.model;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class ClosedProject implements ProjectTreeNode {
String name;
Workspace parent;
public ClosedProject(Workspace w, String name) {
this.parent = w;
this.name = name;
}
String name;
Workspace parent;
@Override
public TreeNode getChildAt(int childIndex) {
return null;
}
@Override
public int getChildCount() {
return 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public int getIndex(TreeNode node) {
return 0;
}
@Override
public boolean getAllowsChildren() {
return false;
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@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>());
}
public ClosedProject(Workspace w, String name) {
this.parent = w;
this.name = name;
}
@Override
public String getDesc() {
return name+" [closed]";
}
@Override
public Project getProject() {
return null;
}
@Override
public TreeNode getChildAt(int childIndex) {
return null;
}
@Override
public int getChildCount() {
return 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public int getIndex(TreeNode node) {
return 0;
}
@Override
public boolean getAllowsChildren() {
return false;
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@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>());
}
@Override
public String getDesc() {
return name + " [closed]";
}
@Override
public Project getProject() {
return null;
}
@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();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@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();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean needsSaving() {
return false;
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean needsSaving() {
return false;
}
}

View File

@@ -1,189 +1,237 @@
package com.gpl.rpg.atcontentstudio.model;
import java.awt.Image;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.gpl.rpg.atcontentstudio.model.bookmarks.BookmarkEntry;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.io.Serializable;
import java.util.List;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public abstract class GameDataElement implements ProjectTreeNode, Serializable {
private static final long serialVersionUID = 2028934451226743389L;
public static enum State {
init, // We know the object exists, and have its key/ID.
parsed, // We know the object's properties, but related objects are referenced by ID only.
linked, // We know the object fully, and all links to related objects point to objects in the parsed state at least.
created, // This is an object we are creating
modified, // Whether altered or created, this item has been modified since creation from scratch or from JSON.
saved // Whether altered or created, this item has been saved since last modification.
}
public State state = State.init;
//Available from state init.
public ProjectTreeNode parent;
public boolean writable = false;
//List of objects whose transition to "linked" state made them point to this instance.
private Map<GameDataElement, Integer> backlinks = new ConcurrentHashMap<GameDataElement, Integer>();
private static final long serialVersionUID = 2028934451226743389L;
public String id = null;
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@Override
public boolean getAllowsChildren() {
return false;
}
@Override
public TreeNode getChildAt(int arg0) {
return null;
}
@Override
public int getChildCount() {
return 0;
}
@Override
public int getIndex(TreeNode arg0) {
return 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenAdded(path);
}
public static enum State {
init, // We know the object exists, and have its key/ID.
parsed, // We know the object's properties, but related objects are referenced by ID only.
linked, // We know the object fully, and all links to related objects point to objects in the parsed state at least.
created, // This is an object we are creating
modified, // Whether altered or created, this item has been modified since creation from scratch or from JSON.
saved // Whether altered or created, this item has been saved since last modification.
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenChanged(path);
}
public State state = State.init;
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenRemoved(path);
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public abstract String getDesc();
public static String getStaticDesc() {
return "GameDataElements";
}
public abstract void parse();
public abstract void link();
@Override
public Project getProject() {
return parent == null ? null : parent.getProject();
}
public Image getIcon() {
return null;
}
@Override
public Image getClosedIcon() {return null;}
@Override
public Image getOpenIcon() {return null;}
@Override
public Image getLeafIcon() {
return getIcon();
}
public abstract GameDataElement clone();
public abstract void elementChanged(GameDataElement oldOne, GameDataElement newOne);
//Available from state init.
public ProjectTreeNode parent;
@Override
public GameSource.Type getDataType() {
if (parent == null) {
System.out.println("blerf.");
}
return parent.getDataType();
}
public List<BacklinksListener> backlinkListeners = new ArrayList<GameDataElement.BacklinksListener>();
public void addBacklinkListener(BacklinksListener l) {
backlinkListeners.add(l);
}
public boolean writable = false;
public void removeBacklinkListener(BacklinksListener l) {
backlinkListeners.remove(l);
}
public void addBacklink(GameDataElement gde) {
if (!backlinks.containsKey(gde)) {
backlinks.put(gde, 1);
for (BacklinksListener l : backlinkListeners) {
l.backlinkAdded(gde);
}
} else {
backlinks.put(gde, backlinks.get(gde) + 1);
}
}
public BookmarkEntry bookmark = null;
public void removeBacklink(GameDataElement gde) {
if (backlinks.get(gde) == null) return;
backlinks.put(gde, backlinks.get(gde) - 1);
if (backlinks.get(gde) == 0) {
backlinks.remove(gde);
for (BacklinksListener l : backlinkListeners) {
l.backlinkRemoved(gde);
}
}
}
//List of objects whose transition to "linked" state made them point to this instance.
private Map<GameDataElement, Integer> backlinks = new ConcurrentHashMap<GameDataElement, Integer>();
public Set<GameDataElement> getBacklinks() {
return backlinks.keySet();
}
public static interface BacklinksListener {
public void backlinkAdded(GameDataElement gde);
public void backlinkRemoved(GameDataElement gde);
}
@Override
public boolean isEmpty() {
return false;
}
public boolean needsSaving() {
return this.state == State.modified || this.state == State.created;
}
public abstract String getProjectFilename();
public abstract void save();
public abstract List<SaveEvent> attemptSave();
public String id = null;
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@Override
public boolean getAllowsChildren() {
return false;
}
@Override
public TreeNode getChildAt(int arg0) {
return null;
}
@Override
public int getChildCount() {
return 0;
}
@Override
public int getIndex(TreeNode arg0) {
return 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return true;
}
@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>());
}
@Override
public abstract String getDesc();
public static String getStaticDesc() {
return "GameDataElements";
}
public abstract void parse();
public abstract void link();
@Override
public Project getProject() {
return parent == null ? null : parent.getProject();
}
public Image getIcon() {
return null;
}
@Override
public Image getClosedIcon() {
return null;
}
@Override
public Image getOpenIcon() {
return null;
}
@Override
public Image getLeafIcon() {
return getIcon();
}
public abstract GameDataElement clone();
public abstract void elementChanged(GameDataElement oldOne, GameDataElement newOne);
@Override
public GameSource.Type getDataType() {
if (parent == null) {
System.out.println("blerf.");
}
return parent.getDataType();
}
public List<BacklinksListener> backlinkListeners = new ArrayList<GameDataElement.BacklinksListener>();
public void addBacklinkListener(BacklinksListener l) {
backlinkListeners.add(l);
}
public void removeBacklinkListener(BacklinksListener l) {
backlinkListeners.remove(l);
}
public void addBacklink(GameDataElement gde) {
if (!backlinks.containsKey(gde)) {
backlinks.put(gde, 1);
for (BacklinksListener l : backlinkListeners) {
l.backlinkAdded(gde);
}
} else {
backlinks.put(gde, backlinks.get(gde) + 1);
}
}
public void removeBacklink(GameDataElement gde) {
if (backlinks.get(gde) == null) return;
backlinks.put(gde, backlinks.get(gde) - 1);
if (backlinks.get(gde) == 0) {
backlinks.remove(gde);
for (BacklinksListener l : backlinkListeners) {
l.backlinkRemoved(gde);
}
}
}
public Set<GameDataElement> getBacklinks() {
return backlinks.keySet();
}
public static interface BacklinksListener {
public void backlinkAdded(GameDataElement gde);
public void backlinkRemoved(GameDataElement gde);
}
@Override
public boolean isEmpty() {
return false;
}
public boolean needsSaving() {
return this.state == State.modified || this.state == State.created;
}
public abstract String getProjectFilename();
public abstract void save();
public abstract List<SaveEvent> attemptSave();
/**
* Checks if the current state indicates that parsing/linking should be skipped.
*
* @return true if the operation should be skipped, false otherwise
*/
protected boolean shouldSkipParseOrLink() {
if (shouldSkipParse()) return true;
if (this.state == State.linked) {
//Already linked.
return true;
}
return false;
}
protected boolean shouldSkipParse() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return true;
}
return false;
}
/**
* Ensures the element is parsed if needed based on its current state.
*/
protected void ensureParseIfNeeded() {
if (this.state == State.init) {
//Not parsed yet.
this.parse();
}
}
}

View File

@@ -1,28 +1,6 @@
package com.gpl.rpg.atcontentstudio.model;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.io.JsonSerializable;
import com.gpl.rpg.atcontentstudio.model.Project.ResourceSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
@@ -32,263 +10,317 @@ import com.gpl.rpg.atcontentstudio.model.sprites.SpriteSheetSet;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.model.tools.writermode.WriterModeDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
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;
public class GameSource implements ProjectTreeNode, Serializable {
import javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.io.*;
import java.util.List;
import java.util.*;
private static final long serialVersionUID = -1512979360971918158L;
public static final String DEFAULT_REL_PATH_FOR_GAME_RESOURCE = "res"+File.separator+"values"+File.separator+"loadresources.xml";
public static final String DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE = "res"+File.separator+"values"+File.separator+"loadresources_debug.xml";
public transient GameDataSet gameData;
public transient TMXMapSet gameMaps;
public transient SpriteSheetSet gameSprites;
public transient Worldmap worldmap;
public transient WriterModeDataSet writerModeDataSet;
private transient SavedSlotCollection v;
public static enum Type {
source,
referenced,
altered,
created
}
public File baseFolder;
public Type type;
public transient Project parent = null;
public transient Map<String, List<String>> referencedSourceFiles = null;
public GameSource(File folder, Project parent) {
this.parent = parent;
this.baseFolder = folder;
this.type = Type.source;
initData();
}
public GameSource(Project parent, Type type) {
this.parent = parent;
this.baseFolder = new File(parent.baseFolder, type.toString());
this.type = type;
initData();
}
public void refreshTransients(Project p) {
parent = p;
initData();
}
public class GameSource implements ProjectTreeNode, Serializable, JsonSerializable {
public void initData() {
if (type == Type.source) {
if (parent.sourceSetToUse == ResourceSet.gameData || parent.sourceSetToUse == ResourceSet.debugData) {
referencedSourceFiles = new LinkedHashMap<String, List<String>>();
readResourceList();
}
}
if (type == Type.created) {
this.writerModeDataSet = new WriterModeDataSet(this);
}
this.gameData = new GameDataSet(this);
this.gameMaps = new TMXMapSet(this);
this.gameSprites = new SpriteSheetSet(this);
this.worldmap = new Worldmap(this);
v = new SavedSlotCollection();
v.add(gameData);
v.add(gameMaps);
v.add(gameSprites);
v.add(worldmap);
if (type == Type.created) {
v.add(writerModeDataSet);
}
}
public void readResourceList() {
File xmlFile = null;
if (parent.sourceSetToUse == ResourceSet.gameData) {
xmlFile = new File(baseFolder, DEFAULT_REL_PATH_FOR_GAME_RESOURCE);
} else if (parent.sourceSetToUse == ResourceSet.debugData) {
xmlFile = new File(baseFolder, DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE);
} else {
return;
}
if (!xmlFile.exists()) return;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc;
try {
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource insrc = new InputSource(new FileInputStream(xmlFile));
private static final long serialVersionUID = -1512979360971918158L;
public static final String DEFAULT_REL_PATH_FOR_GAME_RESOURCE = "res" + File.separator + "values" + File.separator + "loadresources.xml";
public static final String DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE = "res" + File.separator + "values" + File.separator + "loadresources_debug.xml";
public transient GameDataSet gameData;
public transient TMXMapSet gameMaps;
public transient SpriteSheetSet gameSprites;
public transient Worldmap worldmap;
public transient WriterModeDataSet writerModeDataSet;
private transient SavedSlotCollection v;
@Override
public Map toMap() {
Map map = new HashMap();
map.put("type", type.toString());
map.put("baseFolder", baseFolder.getPath());
return map;
}
@Override
public void fromMap(Map map) {
if(map==null)return;
type = Enum.valueOf(Type.class, (String)map.get("type"));
baseFolder = new File((String) map.get("baseFolder"));
}
public static enum Type {
source,
referenced,
altered,
created
}
public File baseFolder;
public Type type;
public transient Project parent;
public transient Map<String, List<String>> referencedSourceFiles = null;
public GameSource(Map json, Project parent) {
fromMap(json);
refreshTransients(parent);
}
public GameSource(File folder, Project parent) {
this.parent = parent;
this.baseFolder = folder;
this.type = Type.source;
initData();
}
public GameSource(Project parent, Type type) {
this.parent = parent;
this.baseFolder = new File(parent.baseFolder, type.toString());
this.type = type;
initData();
}
public void refreshTransients(Project p) {
parent = p;
initData();
}
public void initData() {
if (type == Type.source) {
if (parent.sourceSetToUse == ResourceSet.gameData || parent.sourceSetToUse == ResourceSet.debugData) {
referencedSourceFiles = new LinkedHashMap<String, List<String>>();
readResourceList();
}
}
if (type == Type.created) {
this.writerModeDataSet = new WriterModeDataSet(this);
}
this.gameData = new GameDataSet(this);
this.gameMaps = new TMXMapSet(this);
this.gameSprites = new SpriteSheetSet(this);
this.worldmap = new Worldmap(this);
v = new SavedSlotCollection();
v.add(gameData);
v.add(gameMaps);
v.add(gameSprites);
v.add(worldmap);
if (type == Type.created) {
v.add(writerModeDataSet);
}
}
public void readResourceList() {
File xmlFile;
if (parent.sourceSetToUse == ResourceSet.gameData) {
xmlFile = new File(baseFolder, DEFAULT_REL_PATH_FOR_GAME_RESOURCE);
} else if (parent.sourceSetToUse == ResourceSet.debugData) {
xmlFile = new File(baseFolder, DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE);
} else {
return;
}
if (!xmlFile.exists()) return;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc;
try {
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource insrc = new InputSource(new FileInputStream(xmlFile));
// insrc.setSystemId("http://worldmap/");
insrc.setEncoding("UTF-8");
doc = builder.parse(insrc);
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++) {
Element arrayNode = (Element) arraysList.item(i);
String name = arrayNode.getAttribute("name");
List<String> arrayContents = new ArrayList<String>();
NodeList arrayItems = arrayNode.getElementsByTagName("item");
if (arrayItems != null) {
for (int j = 0; j < arrayItems.getLength(); j++) {
arrayContents.add(((Element)arrayItems.item(j)).getTextContent());
}
referencedSourceFiles.put(name, arrayContents);
}
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return v.getNonEmptyElementAt(arg0);
}
@Override
public int getChildCount() {
return v.getNonEmptySize();
}
@Override
public int getIndex(TreeNode arg0) {
return v.getNonEmptyIndexOf((ProjectTreeNode) arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.v.getNonEmptySize() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
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() {
switch(type) {
case altered: return (needsSaving() ? "*" : "")+"Altered data";
case created: return (needsSaving() ? "*" : "")+"Created data";
case referenced: return (needsSaving() ? "*" : "")+"Referenced data";
case source: return (needsSaving() ? "*" : "")+"AT Source"; //The fact that it is from "source" is already mentionned by its parent.
default: return (needsSaving() ? "*" : "")+"Game data";
}
}
@Override
public Project getProject() {
return parent == null ? null : parent.getProject();
}
insrc.setEncoding("UTF-8");
doc = builder.parse(insrc);
public Image getIcon(String iconId) {
String[] data = iconId.split(":");
for (Spritesheet sheet : gameSprites.spritesheets) {
if (sheet.id.equals(data[0])) {
return sheet.getIcon(Integer.parseInt(data[1]));
}
}
return null;
}
public Image getImage(String iconId) {
String[] data = iconId.split(":");
for (Spritesheet sheet : gameSprites.spritesheets) {
if (sheet.id.equals(data[0])) {
return sheet.getImage(Integer.parseInt(data[1]));
}
}
return null;
}
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++) {
Element arrayNode = (Element) arraysList.item(i);
String name = arrayNode.getAttribute("name");
List<String> arrayContents = new ArrayList<String>();
NodeList arrayItems = arrayNode.getElementsByTagName("item");
if (arrayItems != null) {
for (int j = 0; j < arrayItems.getLength(); j++) {
arrayContents.add(((Element) arrayItems.item(j)).getTextContent());
}
referencedSourceFiles.put(name, arrayContents);
}
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getATClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getATClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getATOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();
}
@Override
public Type getDataType() {
return type;
}
@Override
public boolean isEmpty() {
return v.isEmpty();
}
@Override
public boolean getAllowsChildren() {
return true;
}
public WorldmapSegment getWorldmapSegment(String id) {
return worldmap.getWorldmapSegment(id);
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
if (node.needsSaving()) return true;
}
return false;
}
@Override
public TreeNode getChildAt(int arg0) {
return v.getNonEmptyElementAt(arg0);
}
@Override
public int getChildCount() {
return v.getNonEmptySize();
}
@Override
public int getIndex(TreeNode arg0) {
return v.getNonEmptyIndexOf((ProjectTreeNode) arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.v.getNonEmptySize() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
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() {
switch (type) {
case altered:
return (needsSaving() ? "*" : "") + "Altered data";
case created:
return (needsSaving() ? "*" : "") + "Created data";
case referenced:
return (needsSaving() ? "*" : "") + "Referenced data";
case source:
return (needsSaving() ? "*" : "") + "AT Source"; //The fact that it is from "source" is already mentionned by its parent.
default:
return (needsSaving() ? "*" : "") + "Game data";
}
}
@Override
public Project getProject() {
return parent == null ? null : parent.getProject();
}
public Image getIcon(String iconId) {
String[] data = iconId.split(":");
for (Spritesheet sheet : gameSprites.spritesheets) {
if (sheet.id.equals(data[0])) {
return sheet.getIcon(Integer.parseInt(data[1]));
}
}
return null;
}
public Image getImage(String iconId) {
String[] data = iconId.split(":");
for (Spritesheet sheet : gameSprites.spritesheets) {
if (sheet.id.equals(data[0])) {
return sheet.getImage(Integer.parseInt(data[1]));
}
}
return null;
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getATClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getATClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getATOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return type;
}
@Override
public boolean isEmpty() {
return v.isEmpty();
}
public WorldmapSegment getWorldmapSegment(String id) {
return worldmap.getWorldmapSegment(id);
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
if (node.needsSaving()) return true;
}
return false;
}
}

View File

@@ -1,19 +1,53 @@
package com.gpl.rpg.atcontentstudio.model;
import java.awt.Dimension;
import com.gpl.rpg.atcontentstudio.io.JsonSerializable;
import java.awt.*;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class Preferences implements Serializable {
public class Preferences implements Serializable, JsonSerializable {
private static final long serialVersionUID = 2455802658424031276L;
public Dimension windowSize = null;
public Map<String, Integer> splittersPositions = new HashMap<String, Integer>();
public Preferences() {
private static final long serialVersionUID = 2455802658424031276L;
}
public Dimension windowSize = null;
public Map<String, Integer> splittersPositions = new HashMap<>();
public Preferences() {
}
@Override
public Map toMap() {
Map map = new HashMap();
if(windowSize!= null){
Map windowSizeMap = new HashMap<>();
windowSizeMap.put("width", windowSize.width);
windowSizeMap.put("height", windowSize.height);
map.put("windowSize", windowSizeMap);
}
map.put("splittersPositions", splittersPositions);
return map;
}
@Override
public void fromMap(Map map) {
if(map == null) return;
Map windowSize1 = (Map) map.get("windowSize");
if(windowSize1 != null){
windowSize = new Dimension(((Number) windowSize1.get("width")).intValue(), ((Number) windowSize1.get("height")).intValue());
}
Map<String, Number> splitters = (Map<String, Number>) map.get("splittersPositions");
Map<String, Integer> splittersInt = new HashMap<>(splitters.size());
for (Map.Entry<String, Number> entry : splitters. entrySet()){
splittersInt.put(entry.getKey(), entry.getValue().intValue());
}
splittersPositions = splittersInt;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,10 +2,10 @@ package com.gpl.rpg.atcontentstudio.model;
public interface ProjectElementListener {
public void elementAdded(GameDataElement added, int index);
public void elementRemoved(GameDataElement removed, int index);
public Class<? extends GameDataElement> getDataType();
public void elementAdded(GameDataElement added, int index);
public void elementRemoved(GameDataElement removed, int index);
public Class<? extends GameDataElement> getDataType();
}

View File

@@ -1,59 +1,64 @@
package com.gpl.rpg.atcontentstudio.model;
import java.awt.Image;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.util.List;
public interface ProjectTreeNode extends TreeNode {
public void childrenAdded(List<ProjectTreeNode> path);
public void childrenChanged(List<ProjectTreeNode> path);
public void childrenRemoved(List<ProjectTreeNode> path);
public void notifyCreated();
public String getDesc();
/**
* Unnecessary for anything not below a Project. Can return null.
* @return the parent Project or null.
*/
public Project getProject();
public void childrenAdded(List<ProjectTreeNode> path);
/**
* Unnecessary for anything not below a GameDataSet. Can return null.
* @return the parent GameDataSet or null.
*/
public GameDataSet getDataSet();
public Image getIcon();
/**
*
* @return The icon depicting this node when it is an open folder. Can be null for leaves.
*/
public Image getOpenIcon();
/**
*
* @return The icon depicting this node when it is a closed folder. Can be null for leaves.
*/
public Image getClosedIcon();
/**
*
* @return The icon depicting this node when it is a leaf. Should return the closed one for empty folders.
*/
public Image getLeafIcon();
/**
* Unnecessary for anything not below a GameSource. Can return null.
* @return the parent GameSource or null.
*/
public GameSource.Type getDataType();
public boolean isEmpty();
public boolean needsSaving();
public void childrenChanged(List<ProjectTreeNode> path);
public void childrenRemoved(List<ProjectTreeNode> path);
public void notifyCreated();
public String getDesc();
/**
* Unnecessary for anything not below a Project. Can return null.
*
* @return the parent Project or null.
*/
public Project getProject();
/**
* Unnecessary for anything not below a GameDataSet. Can return null.
*
* @return the parent GameDataSet or null.
*/
public GameDataSet getDataSet();
public Image getIcon();
/**
* @return The icon depicting this node when it is an open folder. Can be null for leaves.
*/
public Image getOpenIcon();
/**
* @return The icon depicting this node when it is a closed folder. Can be null for leaves.
*/
public Image getClosedIcon();
/**
* @return The icon depicting this node when it is a leaf. Should return the closed one for empty folders.
*/
public Image getLeafIcon();
/**
* Unnecessary for anything not below a GameSource. Can return null.
*
* @return the parent GameSource or null.
*/
public GameSource.Type getDataType();
public boolean isEmpty();
public boolean needsSaving();
}

View File

@@ -1,35 +1,35 @@
package com.gpl.rpg.atcontentstudio.model;
public class SaveEvent {
public enum Type {
moveToAltered,
moveToCreated,
alsoSave
}
public Type type;
public GameDataElement target;
public boolean error = false;
public String errorText;
public SaveEvent(SaveEvent.Type type, GameDataElement target) {
this.type = type;
this.target = target;
}
public SaveEvent(SaveEvent.Type type, GameDataElement target, boolean error, String errorText) {
this.type = type;
this.target = target;
this.error = error;
this.errorText = errorText;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SaveEvent)) return false;
else return (((SaveEvent)obj).type == this.type) && (((SaveEvent)obj).target == this.target);
}
public enum Type {
moveToAltered,
moveToCreated,
alsoSave
}
public Type type;
public GameDataElement target;
public boolean error = false;
public String errorText;
public SaveEvent(SaveEvent.Type type, GameDataElement target) {
this.type = type;
this.target = target;
}
public SaveEvent(SaveEvent.Type type, GameDataElement target, boolean error, String errorText) {
this.type = type;
this.target = target;
this.error = error;
this.errorText = errorText;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SaveEvent)) return false;
else return (((SaveEvent) obj).type == this.type) && (((SaveEvent) obj).target == this.target);
}
}

View File

@@ -5,67 +5,67 @@ import java.util.Vector;
public class SavedSlotCollection {
Vector<ProjectTreeNode> contents = new Vector<ProjectTreeNode>();
public void add(ProjectTreeNode node) {
contents.add(node);
}
public int getNonEmptySize() {
Vector<ProjectTreeNode> contents = new Vector<ProjectTreeNode>();
public void add(ProjectTreeNode node) {
contents.add(node);
}
public int getNonEmptySize() {
// return contents.size();
int size = 0;
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) size++;
}
return size;
}
public Enumeration<ProjectTreeNode> getNonEmptyElements() {
int size = 0;
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) size++;
}
return size;
}
public Enumeration<ProjectTreeNode> getNonEmptyElements() {
// return contents.elements();
Vector<ProjectTreeNode> v = new Vector<ProjectTreeNode>();
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) v.add(node);
}
return v.elements();
}
public ProjectTreeNode getNonEmptyElementAt(int index) {
Vector<ProjectTreeNode> v = new Vector<ProjectTreeNode>();
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) v.add(node);
}
return v.elements();
}
public ProjectTreeNode getNonEmptyElementAt(int index) {
// return contents.get(index);
int i = 0;
while (i < contents.size()) {
if (!contents.get(i).isEmpty()) index--;
if (index == -1) return contents.get(i);
i++;
}
return null;
}
int i = 0;
while (i < contents.size()) {
if (!contents.get(i).isEmpty()) index--;
if (index == -1) return contents.get(i);
i++;
}
return null;
}
public int getNonEmptyIndexOf(ProjectTreeNode node) {
public int getNonEmptyIndexOf(ProjectTreeNode node) {
// return contents.indexOf(node);
int index = contents.indexOf(node);
int trueIndex = index;
for (int i = 0; i < trueIndex; i++) {
if (contents.get(i).isEmpty()) index--;
}
return index;
}
int index = contents.indexOf(node);
int trueIndex = index;
for (int i = 0; i < trueIndex; i++) {
if (contents.get(i).isEmpty()) index--;
}
return index;
}
public Vector<ProjectTreeNode> getNonEmptyIterable() {
public Vector<ProjectTreeNode> getNonEmptyIterable() {
// return contents;
Vector<ProjectTreeNode> v = new Vector<ProjectTreeNode>();
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) v.add(node);
}
return v;
}
public boolean isEmpty() {
Vector<ProjectTreeNode> v = new Vector<ProjectTreeNode>();
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) v.add(node);
}
return v;
}
public boolean isEmpty() {
// return contents.isEmpty();
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) return false;
}
return true;
}
for (ProjectTreeNode node : contents) {
if (!node.isEmpty()) return false;
}
return true;
}
}

View File

@@ -1,366 +1,423 @@
package com.gpl.rpg.atcontentstudio.model;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.io.JsonSerializable;
import com.gpl.rpg.atcontentstudio.io.SettingsSave;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.ProjectsTree.ProjectsTreeModel;
import com.gpl.rpg.atcontentstudio.ui.WorkerDialog;
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
import org.jsoup.SerializationException;
public class Workspace implements ProjectTreeNode, Serializable {
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.io.*;
import java.nio.file.Files;
import java.util.List;
import java.util.*;
private static final long serialVersionUID = 7938633033601384956L;
public class Workspace implements ProjectTreeNode, Serializable, JsonSerializable {
public static final String WS_SETTINGS_FILE = ".workspace";
private static final long serialVersionUID = 7938633033601384956L;
public static Workspace activeWorkspace;
public static final String WS_SETTINGS_FILE = ".workspace";
public static final String WS_SETTINGS_FILE_JSON = ".workspace.json";
public Preferences preferences = new Preferences();
public File baseFolder;
public File settingsFile;
public transient WorkspaceSettings settings;
public transient List<ProjectTreeNode> projects = new ArrayList<ProjectTreeNode>();
public Set<String> projectsName = new HashSet<String>();
public Map<String, Boolean> projectsOpenByName = new HashMap<String, Boolean>();
public Set<File> knownMapSourcesFolders = new HashSet<File>();
public static Workspace activeWorkspace;
public transient ProjectsTreeModel projectsTreeModel = null;
public Preferences preferences = new Preferences();
public File baseFolder;
public File settingsFile;
public transient WorkspaceSettings settings;
public transient List<ProjectTreeNode> projects = new ArrayList<ProjectTreeNode>();
public Set<String> projectsName = new HashSet<String>();
public Map<String, Boolean> projectsOpenByName = new HashMap<String, Boolean>();
public Set<File> knownMapSourcesFolders = new HashSet<File>();
public Workspace(File workspaceRoot) {
baseFolder = workspaceRoot;
if (!workspaceRoot.exists()) {
try {
workspaceRoot.mkdir();
} catch (SecurityException e) {
Notification.addError("Error creating workspace directory: "
+ e.getMessage());
e.printStackTrace();
}
}
settings = new WorkspaceSettings(this);
settingsFile = new File(workspaceRoot, WS_SETTINGS_FILE);
if (!settingsFile.exists()) {
try {
settingsFile.createNewFile();
} catch (IOException e) {
Notification.addError("Error creating workspace datafile: "
+ e.getMessage());
e.printStackTrace();
}
}
Notification.addSuccess("New workspace created: "
+ workspaceRoot.getAbsolutePath());
save();
}
public transient ProjectsTreeModel projectsTreeModel = null;
public static void setActive(File workspaceRoot) {
Workspace w = null;
File f = new File(workspaceRoot, WS_SETTINGS_FILE);
if (!workspaceRoot.exists() || !f.exists()) {
w = new Workspace(workspaceRoot);
} else {
w = (Workspace) SettingsSave.loadInstance(f, "Workspace");
if (w == null) {
w = new Workspace(workspaceRoot);
} else {
w.refreshTransients();
}
}
activeWorkspace = w;
}
public Workspace(File workspaceRoot) {
boolean freshWorkspace = false;
baseFolder = workspaceRoot;
if (!workspaceRoot.exists()) {
try {
workspaceRoot.mkdir();
} catch (SecurityException e) {
Notification.addError("Error creating workspace directory: "
+ e.getMessage());
e.printStackTrace();
}
}
settings = new WorkspaceSettings(this);
settingsFile = new File(workspaceRoot, WS_SETTINGS_FILE_JSON);
if (!settingsFile.exists()) {
try {
settingsFile.createNewFile();
freshWorkspace = true;
} catch (IOException e) {
Notification.addError("Error creating workspace datafile: "
+ e.getMessage());
e.printStackTrace();
}
Notification.addSuccess("New workspace created: "
+ workspaceRoot.getAbsolutePath());
}
if (freshWorkspace)
save();
}
public static void saveActive() {
activeWorkspace.save();
}
@Override
public Map toMap() {
Map map = new HashMap();
map.put("serialVersionUID", serialVersionUID);
map.put("preferences", preferences.toMap());
map.put("projectsName", (new ArrayList<String>(projectsName)));
map.put("projectsOpenByName", projectsOpenByName);
List<String> l = new ArrayList<>(knownMapSourcesFolders.size());
for (File f: knownMapSourcesFolders){
l.add(f.getPath());
}
map.put("knownMapSourcesFolders", l);
return map;
}
public void save() {
settings.save();
SettingsSave.saveInstance(this, settingsFile, "Workspace");
}
@Override
public void fromMap(Map map) {
if(serialVersionUID != (long) map.get("serialVersionUID")){
throw new SerializationException("wrong seriaVersionUID");
}
@Override
public Enumeration<ProjectTreeNode> children() {
return Collections.enumeration(projects);
}
preferences.fromMap((Map) map.get("preferences"));
@Override
public boolean getAllowsChildren() {
return true;
}
projectsName = new HashSet<>((List<String>) map.getOrDefault("projectsName", new HashSet<String>()));
@Override
public TreeNode getChildAt(int arg0) {
return projects.get(arg0);
}
projectsOpenByName = (Map<String, Boolean>) map.getOrDefault("projectsOpenByName", new HashMap<String, Boolean>() );
@Override
public int getChildCount() {
return projects.size();
}
List<String> knownMapSourcesFolders1 = (List<String>) map.getOrDefault("knownMapSourcesFolders", new ArrayList<String>());
knownMapSourcesFolders = new HashSet<>();
if (knownMapSourcesFolders1 != null){
int size = knownMapSourcesFolders1.size();
for (String path: knownMapSourcesFolders1) {
//TODO: catch invalid paths...?
knownMapSourcesFolders.add(new File(path));
}
}
@Override
public int getIndex(TreeNode arg0) {
return projects.indexOf(arg0);
}
}
@Override
public TreeNode getParent() {
return null;
}
public static void setActive(File workspaceRoot) {
Workspace w;
File f2 = new File(workspaceRoot, WS_SETTINGS_FILE_JSON);
if (f2.exists()) {
w = loadWorkspaceFromJson(workspaceRoot, f2);
w.refreshTransients();
} else {
Notification.addInfo("Could not find json workspace file. Checking for binary file");
File f = new File(workspaceRoot, WS_SETTINGS_FILE);
if (!workspaceRoot.exists() || !f.exists()) {
w = new Workspace(workspaceRoot);
} else {
w = (Workspace) SettingsSave.loadInstance(f, "Workspace");
if (w == null) {
w = new Workspace(workspaceRoot);
} else {
w.settingsFile = f2;
w.baseFolder = workspaceRoot;
Notification.addInfo("Switched workspace to json format.");
w.refreshTransients();
}
w.save();
}
}
activeWorkspace = w;
}
@Override
public boolean isLeaf() {
return false;
}
private static Workspace loadWorkspaceFromJson(File workspaceRoot, File settingsFile) {
Workspace w = w = new Workspace(workspaceRoot);
Map json = FileUtils.mapFromJsonFile(settingsFile);
if (json!= null) {
w.fromMap(json);
}
return w;
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0, this);
if (projectsTreeModel != null)
projectsTreeModel.insertNode(new TreePath(path.toArray()));
}
public static void saveActive() {
activeWorkspace.save();
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0, this);
ProjectTreeNode last = path.get(path.size() - 1);
if (projectsTreeModel != null) {
while (path.size() > 1) {
projectsTreeModel.changeNode(new TreePath(path.toArray()));
path.remove(path.size()-1);
}
}
ATContentStudio.frame.editorChanged(last);
}
public void save() {
settings.save();
FileUtils.writeStringToFile(FileUtils.toJsonString(this), settingsFile, "Workspace");
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
path.add(0, this);
if (projectsTreeModel != null)
projectsTreeModel.removeNode(new TreePath(path.toArray()));
}
@Override
public Enumeration<ProjectTreeNode> children() {
return Collections.enumeration(projects);
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (ProjectTreeNode node : projects) {
if (node != null)
node.notifyCreated();
}
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public String getDesc() {
return "Workspace: " + baseFolder.getAbsolutePath();
}
@Override
public TreeNode getChildAt(int arg0) {
return projects.get(arg0);
}
public static void createProject(final String projectName,
final File gameSourceFolder, final Project.ResourceSet sourceSet) {
WorkerDialog.showTaskMessage("Creating project " + projectName + "...",
ATContentStudio.frame, new Runnable() {
@Override
public void run() {
if (activeWorkspace.projectsName.contains(projectName)) {
Notification.addError("A project named "
+ projectName
+ " already exists in this workspace.");
return;
}
Project p = new Project(activeWorkspace, projectName,
gameSourceFolder, sourceSet);
activeWorkspace.projects.add(p);
activeWorkspace.projectsName.add(projectName);
activeWorkspace.projectsOpenByName.put(projectName,
p.open);
activeWorkspace.knownMapSourcesFolders
.add(gameSourceFolder);
p.notifyCreated();
Notification.addSuccess("Project " + projectName
+ " successfully created");
saveActive();
}
});
}
@Override
public int getChildCount() {
return projects.size();
}
public static void closeProject(Project p) {
int index = activeWorkspace.projects.indexOf(p);
if (index < 0) {
Notification.addError("Cannot close unknown project " + p.name);
return;
}
p.close();
ClosedProject cp = new ClosedProject(activeWorkspace, p.name);
activeWorkspace.projects.set(index, cp);
activeWorkspace.projectsOpenByName.put(p.name, false);
cp.notifyCreated();
saveActive();
}
@Override
public int getIndex(TreeNode arg0) {
return projects.indexOf(arg0);
}
public static void openProject(final ClosedProject cp) {
WorkerDialog.showTaskMessage("Opening project " + cp.name + "...",
ATContentStudio.frame, new Runnable() {
@Override
public void run() {
int index = activeWorkspace.projects.indexOf(cp);
if (index < 0) {
Notification
.addError("Cannot open unknown project "
+ cp.name);
return;
}
cp.childrenRemoved(new ArrayList<ProjectTreeNode>());
Project p = Project.fromFolder(activeWorkspace,
new File(activeWorkspace.baseFolder, cp.name));
p.open();
activeWorkspace.projects.set(index, p);
activeWorkspace.projectsOpenByName.put(p.name, true);
p.notifyCreated();
saveActive();
}
});
}
@Override
public TreeNode getParent() {
return null;
}
public void refreshTransients() {
this.settings = new WorkspaceSettings(this);
this.projects = new ArrayList<ProjectTreeNode>();
Set<String> projectsFailed = new HashSet<String>();
for (String projectName : projectsName) {
if (projectsOpenByName.get(projectName)) {
File projRoot = new File(this.baseFolder, projectName);
if (projRoot.exists()) {
Project p = Project.fromFolder(this, projRoot);
if (p != null) {
projects.add(p);
} else {
Notification
.addError("Failed to open project "
+ projectName
+ ". Removing it from workspace (not from filesystem though).");
projectsFailed.add(projectName);
}
} else {
Notification.addError("Unable to find project "
+ projectName
+ "'s root folder. Removing it from workspace");
projectsFailed.add(projectName);
}
} else {
projects.add(new ClosedProject(this, projectName));
}
}
for (String projectName : projectsFailed) {
projectsName.remove(projectName);
projectsOpenByName.remove(projectName);
}
notifyCreated();
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public Project getProject() {
return null;
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0, this);
if (projectsTreeModel != null)
projectsTreeModel.insertNode(new TreePath(path.toArray()));
}
@Override
public Image getIcon() {
return null;
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0, this);
ProjectTreeNode last = path.get(path.size() - 1);
if (projectsTreeModel != null) {
while (path.size() > 1) {
projectsTreeModel.changeNode(new TreePath(path.toArray()));
path.remove(path.size() - 1);
}
@Override
public Image getClosedIcon() {
return null;
}
}
ATContentStudio.frame.editorChanged(last);
}
@Override
public Image getLeafIcon() {
return null;
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
path.add(0, this);
if (projectsTreeModel != null)
projectsTreeModel.removeNode(new TreePath(path.toArray()));
}
@Override
public Image getOpenIcon() {
return null;
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (ProjectTreeNode node : projects) {
if (node != null)
node.notifyCreated();
}
}
public static void deleteProject(ClosedProject cp) {
cp.childrenRemoved(new ArrayList<ProjectTreeNode>());
activeWorkspace.projects.remove(cp);
activeWorkspace.projectsOpenByName.remove(cp.name);
activeWorkspace.projectsName.remove(cp.name);
if (delete(new File(activeWorkspace.baseFolder, cp.name))) {
Notification.addSuccess("Closed project " + cp.name
+ " successfully deleted.");
} else {
Notification.addError("Error while deleting closed project "
+ cp.name + ". Files may remain in the workspace.");
}
cp = null;
saveActive();
}
@Override
public String getDesc() {
return "Workspace: " + baseFolder.getAbsolutePath();
}
public static void deleteProject(Project p) {
p.childrenRemoved(new ArrayList<ProjectTreeNode>());
activeWorkspace.projects.remove(p);
activeWorkspace.projectsOpenByName.remove(p.name);
activeWorkspace.projectsName.remove(p.name);
if (delete(p.baseFolder)) {
Notification.addSuccess("Project " + p.name
+ " successfully deleted.");
} else {
Notification.addError("Error while deleting project " + p.name
+ ". Files may remain in the workspace.");
}
p = null;
saveActive();
}
public static void createProject(final String projectName,
final File gameSourceFolder, final Project.ResourceSet sourceSet) {
WorkerDialog.showTaskMessage("Creating project " + projectName + "...",
ATContentStudio.frame, new Runnable() {
@Override
public void run() {
if (activeWorkspace.projectsName.contains(projectName)) {
Notification.addError("A project named "
+ projectName
+ " already exists in this workspace.");
return;
}
Project p = new Project(activeWorkspace, projectName,
gameSourceFolder, sourceSet);
activeWorkspace.projects.add(p);
activeWorkspace.projectsName.add(projectName);
activeWorkspace.projectsOpenByName.put(projectName,
p.open);
activeWorkspace.knownMapSourcesFolders
.add(gameSourceFolder);
p.notifyCreated();
Notification.addSuccess("Project " + projectName
+ " successfully created");
saveActive();
}
});
}
private static boolean delete(File f) {
boolean b = true;
if (f.isDirectory()) {
for (File c : f.listFiles())
b &= delete(c);
}
return b &= f.delete();
}
public static void closeProject(Project p) {
int index = activeWorkspace.projects.indexOf(p);
if (index < 0) {
Notification.addError("Cannot close unknown project " + p.name);
return;
}
p.close();
ClosedProject cp = new ClosedProject(activeWorkspace, p.name);
activeWorkspace.projects.set(index, cp);
activeWorkspace.projectsOpenByName.put(p.name, false);
cp.notifyCreated();
saveActive();
}
@Override
public GameDataSet getDataSet() {
return null;
}
public static void openProject(final ClosedProject cp) {
WorkerDialog.showTaskMessage("Opening project " + cp.name + "...",
ATContentStudio.frame, new Runnable() {
@Override
public void run() {
int index = activeWorkspace.projects.indexOf(cp);
if (index < 0) {
Notification
.addError("Cannot open unknown project "
+ cp.name);
return;
}
cp.childrenRemoved(new ArrayList<ProjectTreeNode>());
Project p = Project.fromFolder(activeWorkspace,
new File(activeWorkspace.baseFolder, cp.name));
p.open();
activeWorkspace.projects.set(index, p);
activeWorkspace.projectsOpenByName.put(p.name, true);
p.notifyCreated();
saveActive();
}
});
}
@Override
public Type getDataType() {
return null;
}
public void refreshTransients() {
this.settings = new WorkspaceSettings(this);
this.projects = new ArrayList<ProjectTreeNode>();
Set<String> projectsFailed = new HashSet<String>();
for (String projectName : projectsName) {
if (projectsOpenByName.get(projectName)) {
File projRoot = new File(this.baseFolder, projectName);
if (projRoot.exists()) {
Project p = Project.fromFolder(this, projRoot);
if (p != null) {
projects.add(p);
} else {
Notification
.addError("Failed to open project "
+ projectName
+ ". Removing it from workspace (not from filesystem though).");
projectsFailed.add(projectName);
}
} else {
Notification.addError("Unable to find project "
+ projectName
+ "'s root folder. Removing it from workspace");
projectsFailed.add(projectName);
}
} else {
projects.add(new ClosedProject(this, projectName));
}
}
for (String projectName : projectsFailed) {
projectsName.remove(projectName);
projectsOpenByName.remove(projectName);
}
notifyCreated();
}
@Override
public boolean isEmpty() {
return projects.isEmpty();
}
@Override
public Project getProject() {
return null;
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : projects) {
if (node.needsSaving()) return true;
}
return false;
}
@Override
public Image getIcon() {
return null;
}
@Override
public Image getClosedIcon() {
return null;
}
@Override
public Image getLeafIcon() {
return null;
}
@Override
public Image getOpenIcon() {
return null;
}
public static void deleteProject(ClosedProject cp) {
cp.childrenRemoved(new ArrayList<ProjectTreeNode>());
activeWorkspace.projects.remove(cp);
activeWorkspace.projectsOpenByName.remove(cp.name);
activeWorkspace.projectsName.remove(cp.name);
if (delete(new File(activeWorkspace.baseFolder, cp.name))) {
Notification.addSuccess("Closed project " + cp.name
+ " successfully deleted.");
} else {
Notification.addError("Error while deleting closed project "
+ cp.name + ". Files may remain in the workspace.");
}
saveActive();
}
public static void deleteProject(Project p) {
p.childrenRemoved(new ArrayList<ProjectTreeNode>());
activeWorkspace.projects.remove(p);
activeWorkspace.projectsOpenByName.remove(p.name);
activeWorkspace.projectsName.remove(p.name);
if (delete(p.baseFolder)) {
Notification.addSuccess("Project " + p.name
+ " successfully deleted.");
} else {
Notification.addError("Error while deleting project " + p.name
+ ". Files may remain in the workspace.");
}
saveActive();
}
private static boolean delete(File f) {
boolean b = true;
if (Files.isSymbolicLink(f.toPath())) {
b &= f.delete();
} else if (f.isDirectory()) {
for (File c : f.listFiles())
b &= delete(c);
}
return b & f.delete();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return projects.isEmpty();
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : projects) {
if (node.needsSaving()) return true;
}
return false;
}
}

View File

@@ -1,215 +1,199 @@
package com.gpl.rpg.atcontentstudio.model;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
import org.json.simple.parser.JSONParser;
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.io.JsonPrettyWriter;
public class WorkspaceSettings {
public static final String VERSION_KEY = "ATCS_Version";
public static final String FILENAME = "workspace_settings.json";
public static final int SETTINGS_VERSION = 1;
public Workspace parent;
public File file;
public static Boolean DEFAULT_USE_SYS_MAP_EDITOR = true;
public Setting<Boolean> useSystemDefaultMapEditor = new PrimitiveSetting<Boolean>("useSystemDefaultMapEditor", DEFAULT_USE_SYS_MAP_EDITOR);
public static String DEFAULT_MAP_EDITOR_COMMAND = "tiled";
public Setting<String> mapEditorCommand = new PrimitiveSetting<String>("mapEditorCommand", DEFAULT_MAP_EDITOR_COMMAND);
public static Boolean DEFAULT_USE_SYS_IMG_VIEWER = true;
public Setting<Boolean> useSystemDefaultImageViewer = new PrimitiveSetting<Boolean>("useSystemDefaultImageViewer", DEFAULT_USE_SYS_IMG_VIEWER);
public static Boolean DEFAULT_USE_SYS_IMG_EDITOR = false;
public Setting<Boolean> useSystemDefaultImageEditor = new PrimitiveSetting<Boolean>("useSystemDefaultImageEditor", DEFAULT_USE_SYS_IMG_EDITOR);
public static String DEFAULT_IMG_EDITOR_COMMAND = "gimp";
public Setting<String> imageEditorCommand = new PrimitiveSetting<String>("imageEditorCommand", DEFAULT_IMG_EDITOR_COMMAND);
public static final String VERSION_KEY = "ATCS_Version";
public static final String FILENAME = "workspace_settings.json";
public static String[] LANGUAGE_LIST = new String[]{null, "de", "ru", "pl", "fr", "it", "es", "nl", "uk", "ca", "sv", "pt", "pt_BR", "zh_Hant", "zh_Hans", "ja", "cs", "tr", "ko", "hu", "sl", "bg", "id", "fi", "th", "gl", "ms" ,"pa", "az"};
public Setting<String> translatorLanguage = new NullDefaultPrimitiveSetting<String>("translatorLanguage");
public static Boolean DEFAULT_ALLOW_INTERNET = true;
public Setting<Boolean> useInternet = new PrimitiveSetting<Boolean>("useInternet", DEFAULT_ALLOW_INTERNET);
public static final int SETTINGS_VERSION = 1;
public List<Setting<? extends Object>> settings = new ArrayList<Setting<? extends Object>>();
public WorkspaceSettings(Workspace parent) {
this.parent = parent;
settings.add(useSystemDefaultMapEditor);
settings.add(mapEditorCommand);
settings.add(useSystemDefaultImageViewer);
settings.add(useSystemDefaultImageEditor);
settings.add(imageEditorCommand);
settings.add(translatorLanguage);
settings.add(useInternet);
file = new File(parent.baseFolder, FILENAME);
if (file.exists()) {
load(file);
}
}
public void load(File f) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(f);
@SuppressWarnings("rawtypes")
Map jsonSettings = (Map) parser.parse(reader);
Integer version = ((Number) jsonSettings.get(VERSION_KEY)).intValue();
if (version != null) {
if (version >= 1) {
loadv1(jsonSettings);
}
}
} catch (Exception e) {
Notification.addError("Error while parsing workspace settings: "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
private void loadv1(Map jsonSettings) {
for (Setting s : settings) {
s.readFromJson(jsonSettings);
}
}
public Workspace parent;
public File file;
@SuppressWarnings("unchecked")
public void save() {
@SuppressWarnings("rawtypes")
Map json = new LinkedHashMap();
for (Setting<? extends Object> s : settings) {
s.saveToJson(json);
}
if (json.isEmpty()) {
//Everything is default.
file.delete();
return;
}
public static Boolean DEFAULT_USE_SYS_MAP_EDITOR = true;
public Setting<Boolean> useSystemDefaultMapEditor = new PrimitiveSetting<Boolean>("useSystemDefaultMapEditor", DEFAULT_USE_SYS_MAP_EDITOR);
public static String DEFAULT_MAP_EDITOR_COMMAND = "tiled";
public Setting<String> mapEditorCommand = new PrimitiveSetting<String>("mapEditorCommand", DEFAULT_MAP_EDITOR_COMMAND);
json.put(VERSION_KEY, SETTINGS_VERSION);
StringWriter writer = new JsonPrettyWriter();
try {
JSONObject.writeJSONString(json, writer);
} catch (IOException e) {
//Impossible with a StringWriter
}
String toWrite = writer.toString();
try {
FileWriter w = new FileWriter(file);
w.write(toWrite);
w.close();
Notification.addSuccess("Workspace settings saved.");
} catch (IOException e) {
Notification.addError("Error while saving workspace settings : "+e.getMessage());
e.printStackTrace();
}
}
public void resetDefault() {
for (Setting<? extends Object> s : settings) {
s.resetDefault();
}
}
public abstract class Setting<X extends Object> {
public static Boolean DEFAULT_USE_SYS_IMG_VIEWER = true;
public Setting<Boolean> useSystemDefaultImageViewer = new PrimitiveSetting<Boolean>("useSystemDefaultImageViewer", DEFAULT_USE_SYS_IMG_VIEWER);
public static Boolean DEFAULT_USE_SYS_IMG_EDITOR = false;
public Setting<Boolean> useSystemDefaultImageEditor = new PrimitiveSetting<Boolean>("useSystemDefaultImageEditor", DEFAULT_USE_SYS_IMG_EDITOR);
public static String DEFAULT_IMG_EDITOR_COMMAND = "gimp";
public Setting<String> imageEditorCommand = new PrimitiveSetting<String>("imageEditorCommand", DEFAULT_IMG_EDITOR_COMMAND);
public String id;
public X value, defaultValue;
public void setCurrentValue(X value) {
this.value = value;
}
public X getCurrentValue() {
return value;
}
public X getDefaultValue() {
return defaultValue;
}
public void resetDefault() {
value = defaultValue;
}
public abstract void readFromJson(Map json);
@SuppressWarnings({ "rawtypes", "unchecked" })
public void saveToJson(Map json) {
if (!defaultValue.equals(value)) json.put(id, value);
}
}
public class PrimitiveSetting<X extends Object> extends Setting<X> {
public PrimitiveSetting(String id, X defaultValue) {
this.id = id;
this.value = this.defaultValue = defaultValue;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public void readFromJson(Map json) {
if (json.get(id) != null) value = (X)json.get(id);
}
}
public class NullDefaultPrimitiveSetting<X extends Object> extends PrimitiveSetting<X> {
public NullDefaultPrimitiveSetting(String id) {
super(id, null);
}
@Override
public void saveToJson(Map json) {
if (value != null) json.put(id, value);
}
}
public class ListSetting<X extends Object> extends Setting<List<X>> {
public static String[] LANGUAGE_LIST = new String[]{null, "de", "ru", "pl", "fr", "it", "es", "nl", "uk", "ca", "sv", "pt", "pt_BR", "zh_Hant", "zh_Hans", "ja", "cs", "tr", "ko", "hu", "sl", "bg", "id", "fi", "th", "gl", "ms", "pa", "az", "nb"};
public Setting<String> translatorLanguage = new NullDefaultPrimitiveSetting<String>("translatorLanguage");
public static Boolean DEFAULT_ALLOW_INTERNET = true;
public Setting<Boolean> useInternet = new PrimitiveSetting<Boolean>("useInternet", DEFAULT_ALLOW_INTERNET);
public static Boolean DEFAULT_CHECK_UPDATE = true;
public Setting<Boolean> checkUpdates = new PrimitiveSetting<Boolean>("checkUpdates", DEFAULT_CHECK_UPDATE);
public List<Setting<? extends Object>> settings = new ArrayList<Setting<? extends Object>>();
public WorkspaceSettings(Workspace parent) {
this.parent = parent;
settings.add(useSystemDefaultMapEditor);
settings.add(mapEditorCommand);
settings.add(useSystemDefaultImageViewer);
settings.add(useSystemDefaultImageEditor);
settings.add(imageEditorCommand);
settings.add(translatorLanguage);
settings.add(useInternet);
settings.add(checkUpdates);
file = new File(parent.baseFolder, FILENAME);
if (file.exists()) {
load(file);
}
}
public void load(File f) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(f);
@SuppressWarnings("rawtypes")
Map jsonSettings = (Map) parser.parse(reader);
Integer version = ((Number) jsonSettings.get(VERSION_KEY)).intValue();
if (version != null) {
if (version >= 1) {
loadv1(jsonSettings);
}
}
} catch (Exception e) {
Notification.addError("Error while parsing workspace settings: " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
private void loadv1(Map jsonSettings) {
for (Setting s : settings) {
s.readFromJson(jsonSettings);
}
}
@SuppressWarnings("unchecked")
public void save() {
@SuppressWarnings("rawtypes")
Map json = new LinkedHashMap();
for (Setting<? extends Object> s : settings) {
s.saveToJson(json);
}
if (json.isEmpty()) {
//Everything is default.
file.delete();
return;
}
json.put(VERSION_KEY, SETTINGS_VERSION);
String toWrite = FileUtils.toJsonString(json);
FileUtils.writeStringToFile(toWrite, file, "Workspace settings");
}
public void resetDefault() {
for (Setting<? extends Object> s : settings) {
s.resetDefault();
}
}
public abstract class Setting<X extends Object> {
public String id;
public X value, defaultValue;
public void setCurrentValue(X value) {
this.value = value;
}
public X getCurrentValue() {
return value;
}
public X getDefaultValue() {
return defaultValue;
}
public void resetDefault() {
value = defaultValue;
}
public abstract void readFromJson(@SuppressWarnings("rawtypes") Map json);
@SuppressWarnings({"rawtypes", "unchecked"})
public void saveToJson(Map json) {
if (!defaultValue.equals(value)) json.put(id, value);
}
}
public class PrimitiveSetting<X extends Object> extends Setting<X> {
public PrimitiveSetting(String id, X defaultValue) {
this.id = id;
this.value = this.defaultValue = defaultValue;
}
@SuppressWarnings({"rawtypes", "unchecked"})
public void readFromJson(Map json) {
if (json.get(id) != null) value = (X) json.get(id);
}
}
public class NullDefaultPrimitiveSetting<X extends Object> extends PrimitiveSetting<X> {
public NullDefaultPrimitiveSetting(String id) {
super(id, null);
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void saveToJson(Map json) {
if (value != null) json.put(id, value);
}
}
public class ListSetting<X extends Object> extends Setting<List<X>> {
public ListSetting(String id, List<X> defaultValue) {
this.id = id;
this.value = this.defaultValue = defaultValue;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void readFromJson(Map json) {
value = new ArrayList<X>();
if (json.get(id) != null) {
for (Object o : ((List) json.get(id))) {
value.add((X) o);
}
}
}
}
public ListSetting(String id, List<X> defaultValue) {
this.id = id;
this.value = this.defaultValue = defaultValue;
}
@Override
public void readFromJson(Map json) {
value = new ArrayList<X>();
if (json.get(id) != null) {
for (Object o : ((List)json.get(id))) {
value.add((X)o);
}
}
}
}
}

View File

@@ -0,0 +1,161 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class BookmarkEntry implements BookmarkNode {
public GameDataElement bookmarkedElement;
public BookmarkFolder parent;
public BookmarkEntry(BookmarkFolder parent, GameDataElement target) {
this.parent = parent;
this.bookmarkedElement = target;
target.bookmark = this;
parent.contents.add(this);
}
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@Override
public boolean getAllowsChildren() {
return false;
}
@Override
public TreeNode getChildAt(int childIndex) {
return null;
}
@Override
public int getChildCount() {
return 0;
}
@Override
public int getIndex(TreeNode node) {
return 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return true;
}
@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>());
}
@Override
public String getDesc() {
if (bookmarkedElement instanceof QuestStage) {
String text = ((GameDataElement) bookmarkedElement).getDesc();
if (text.length() > 60) {
text = text.substring(0, 57) + "...";
}
return ((GameDataElement) bookmarkedElement).getDataType().toString() +
"/" +
((Quest) ((QuestStage) bookmarkedElement).parent).id +
"#" +
((QuestStage) bookmarkedElement).progress +
":" +
text;
} else {
return ((GameDataElement) bookmarkedElement).getDataType().toString() + "/" + ((GameDataElement) bookmarkedElement).getDesc();
}
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Image getIcon() {
return bookmarkedElement.getIcon();
}
@Override
public Image getOpenIcon() {
return null;
}
@Override
public Image getClosedIcon() {
return null;
}
@Override
public Image getLeafIcon() {
return getIcon();
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean needsSaving() {
return false;
}
public void delete() {
bookmarkedElement.bookmark = null;
parent.delete(this);
}
@Override
public void save() {
parent.save();
}
}

View File

@@ -0,0 +1,165 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.util.List;
import java.util.*;
public class BookmarkFolder implements BookmarkNode {
List<BookmarkNode> contents = new LinkedList<BookmarkNode>();
BookmarkNode parent;
String name;
Image closedIcon, openIcon;
public BookmarkFolder(BookmarkNode parent, String name) {
this(parent, name, DefaultIcons.getStdClosedIcon(), DefaultIcons.getStdOpenIcon());
}
public BookmarkFolder(BookmarkNode parent, String name, Image closedIcon, Image openIcon) {
this.parent = parent;
this.name = name;
this.closedIcon = closedIcon;
this.openIcon = openIcon;
}
@Override
public Enumeration<? extends ProjectTreeNode> children() {
return Collections.enumeration(contents);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int childIndex) {
return contents.get(childIndex);
}
@Override
public int getChildCount() {
return contents.size();
}
@Override
public int getIndex(TreeNode node) {
return contents.indexOf(node);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public String getDesc() {
return name;
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Image getIcon() {
return getClosedIcon();
}
@Override
public Image getOpenIcon() {
return openIcon;
}
@Override
public Image getClosedIcon() {
return closedIcon;
}
@Override
public Image getLeafIcon() {
return getClosedIcon();
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return contents.isEmpty();
}
@Override
public boolean needsSaving() {
return false;
}
public void delete(BookmarkEntry bookmarkEntry) {
if (contents.contains(bookmarkEntry)) {
bookmarkEntry.childrenRemoved(new ArrayList<ProjectTreeNode>());
contents.remove(bookmarkEntry);
save();
}
}
public void delete(BookmarkFolder bookmarkFolder) {
// TODO Auto-generated method stub
}
public void save() {
parent.save();
}
public void delete() {
}
}

View File

@@ -0,0 +1,11 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
public interface BookmarkNode extends ProjectTreeNode {
public void save();
public void delete();
}

View File

@@ -0,0 +1,206 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SavedSlotCollection;
import com.gpl.rpg.atcontentstudio.model.gamedata.*;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class BookmarksRoot implements BookmarkNode {
SavedSlotCollection v = new SavedSlotCollection();
public transient Project parent;
BookmarkFolder ac, diag, dl, it, ic, npc, q, tmx, sp, wm;
public BookmarksRoot(Project parent) {
this.parent = parent;
v.add(ac = new BookmarkFolder(this, ActorCondition.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(diag = new BookmarkFolder(this, Dialogue.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(dl = new BookmarkFolder(this, Droplist.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(it = new BookmarkFolder(this, Item.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(ic = new BookmarkFolder(this, ItemCategory.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(npc = new BookmarkFolder(this, NPC.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(q = new BookmarkFolder(this, Quest.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(tmx = new BookmarkFolder(this, "TMX Maps", DefaultIcons.getTmxClosedIcon(), DefaultIcons.getTmxOpenIcon()));
v.add(sp = new BookmarkFolder(this, "Spritesheets", DefaultIcons.getSpriteClosedIcon(), DefaultIcons.getSpriteOpenIcon()));
v.add(wm = new BookmarkFolder(this, "Worldmap", DefaultIcons.getSpriteClosedIcon(), DefaultIcons.getSpriteOpenIcon()));
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return v.getNonEmptyElementAt(arg0);
}
@Override
public int getChildCount() {
return v.getNonEmptySize();
}
@Override
public int getIndex(TreeNode arg0) {
return v.getNonEmptyIndexOf((ProjectTreeNode) arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.v.getNonEmptySize() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
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() ? "*" : "") + "Bookmarks";
}
@Override
public Project getProject() {
return parent == null ? null : parent.getProject();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getBookmarkOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getBookmarkClosedIcon();
}
@Override
public Image getLeafIcon() {
return getClosedIcon();
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return v.isEmpty();
}
@Override
public boolean needsSaving() {
return false;
}
public void save() {
}
@Override
public void delete() {
}
public void addBookmark(GameDataElement target) {
BookmarkEntry node;
BookmarkFolder folder;
if (target instanceof ActorCondition) {
folder = ac;
} else if (target instanceof Dialogue) {
folder = diag;
} else if (target instanceof Droplist) {
folder = dl;
} else if (target instanceof Item) {
folder = it;
} else if (target instanceof ItemCategory) {
folder = ic;
} else if (target instanceof NPC) {
folder = npc;
} else if (target instanceof Quest) {
folder = q;
} else if (target instanceof TMXMap) {
folder = tmx;
} else if (target instanceof Spritesheet) {
folder = sp;
} else if (target instanceof WorldmapSegment) {
folder = wm;
} else {
return;
}
ProjectTreeNode higherEmptyParent = folder;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode) higherEmptyParent.getParent()).isEmpty())
higherEmptyParent = (ProjectTreeNode) higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
node = new BookmarkEntry(folder, target);
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
}

View File

@@ -1,6 +1,12 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -9,340 +15,372 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
public class ActorCondition extends JSONElement {
private static final long serialVersionUID = -3969824899972048507L;
public static final Integer CLEAR_AC_MAGNITUDE = -99;
// Available from init state
//public String id; inherited.
public String icon_id;
public String display_name;
// Available from parsed state
public ACCategory category = null;
public Integer positive = null;
public Integer stacking = null;
public RoundEffect round_effect = null;
public RoundEffect full_round_effect = null;
public AbilityEffect constant_ability_effect = null;
public enum ACCategory {
spiritual,
mental,
physical,
blood
}
public static class RoundEffect implements Cloneable {
// Available from parsed state
public String visual_effect = null;
public Integer hp_boost_min = null;
public Integer hp_boost_max = null;
public Integer ap_boost_min = null;
public Integer ap_boost_max = null;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
public static class AbilityEffect implements Cloneable {
// Available from parsed state
public Integer max_hp_boost = null;
public Integer max_ap_boost = null;
public Integer increase_move_cost = null;
public Integer increase_use_cost = null;
public Integer increase_reequip_cost = null;
public Integer increase_attack_cost = null;
public Integer increase_attack_chance = null;
public Integer increase_damage_min = null;
public Integer increase_damage_max = null;
public Integer increase_critical_skill = null;
public Integer increase_block_chance = null;
public Integer increase_damage_resistance = null;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+display_name+" ("+id+")";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<ActorCondition> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List actorConditions = (List) parser.parse(reader);
for (Object obj : actorConditions) {
Map aCondJson = (Map)obj;
ActorCondition aCond = fromJson(aCondJson);
aCond.jsonFile = jsonFile;
aCond.parent = category;
if (aCond.getDataType() == GameSource.Type.created || aCond.getDataType() == GameSource.Type.altered) {
aCond.writable = true;
}
category.add(aCond);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static ActorCondition fromJson(String jsonString) throws ParseException {
Map aCondJson = (Map) new JSONParser().parse(jsonString);
ActorCondition aCond = fromJson(aCondJson);
aCond.parse(aCondJson);
return aCond;
}
@SuppressWarnings("rawtypes")
public static ActorCondition fromJson(Map aCondJson) {
ActorCondition aCond = new ActorCondition();
aCond.icon_id = (String) aCondJson.get("iconID");
aCond.id = (String) aCondJson.get("id");
aCond.display_name = (String) aCondJson.get("name");
return aCond;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map aCondJson) {
private static final long serialVersionUID = -3969824899972048507L;
if (aCondJson.get("category") != null) this.category = ACCategory.valueOf((String) aCondJson.get("category"));
this.positive = JSONElement.getInteger((Number) aCondJson.get("isPositive"));
Map abilityEffect = (Map) aCondJson.get("abilityEffect");
if (abilityEffect != null) {
this.constant_ability_effect = new AbilityEffect();
this.constant_ability_effect.increase_attack_chance = JSONElement.getInteger((Number) abilityEffect.get("increaseAttackChance"));
if (abilityEffect.get("increaseAttackDamage") != null) {
this.constant_ability_effect.increase_damage_min = JSONElement.getInteger((Number) (((Map)abilityEffect.get("increaseAttackDamage")).get("min")));
this.constant_ability_effect.increase_damage_max = JSONElement.getInteger((Number) (((Map)abilityEffect.get("increaseAttackDamage")).get("max")));
}
this.constant_ability_effect.max_hp_boost = JSONElement.getInteger((Number) abilityEffect.get("increaseMaxHP"));
this.constant_ability_effect.max_ap_boost = JSONElement.getInteger((Number) abilityEffect.get("increaseMaxAP"));
this.constant_ability_effect.increase_move_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseMoveCost"));
this.constant_ability_effect.increase_use_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseUseItemCost"));
this.constant_ability_effect.increase_reequip_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseReequipCost"));
this.constant_ability_effect.increase_attack_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseAttackCost"));
this.constant_ability_effect.increase_critical_skill = JSONElement.getInteger((Number) abilityEffect.get("increaseCriticalSkill"));
this.constant_ability_effect.increase_block_chance = JSONElement.getInteger((Number) abilityEffect.get("increaseBlockChance"));
this.constant_ability_effect.increase_damage_resistance = JSONElement.getInteger((Number) abilityEffect.get("increaseDamageResistance"));
}
this.stacking = JSONElement.getInteger((Number) aCondJson.get("isStacking"));
Map roundEffect = (Map) aCondJson.get("roundEffect");
if (roundEffect != null) {
this.round_effect = new RoundEffect();
if (roundEffect.get("increaseCurrentHP") != null) {
this.round_effect.hp_boost_max = JSONElement.getInteger((Number) (((Map)roundEffect.get("increaseCurrentHP")).get("max")));
this.round_effect.hp_boost_min = JSONElement.getInteger((Number) (((Map)roundEffect.get("increaseCurrentHP")).get("min")));
}
if (roundEffect.get("increaseCurrentAP") != null) {
this.round_effect.ap_boost_max = JSONElement.getInteger((Number) (((Map)roundEffect.get("increaseCurrentAP")).get("max")));
this.round_effect.ap_boost_min = JSONElement.getInteger((Number) (((Map)roundEffect.get("increaseCurrentAP")).get("min")));
}
this.round_effect.visual_effect = (String) roundEffect.get("visualEffectID");
}
Map fullRoundEffect = (Map) aCondJson.get("fullRoundEffect");
if (fullRoundEffect != null) {
this.full_round_effect = new RoundEffect();
if (fullRoundEffect.get("increaseCurrentHP") != null) {
this.full_round_effect.hp_boost_max = JSONElement.getInteger((Number) (((Map)fullRoundEffect.get("increaseCurrentHP")).get("max")));
this.full_round_effect.hp_boost_min = JSONElement.getInteger((Number) (((Map)fullRoundEffect.get("increaseCurrentHP")).get("min")));
}
if (fullRoundEffect.get("increaseCurrentAP") != null) {
this.full_round_effect.ap_boost_max = JSONElement.getInteger((Number) (((Map)fullRoundEffect.get("increaseCurrentAP")).get("max")));
this.full_round_effect.ap_boost_min = JSONElement.getInteger((Number) (((Map)fullRoundEffect.get("increaseCurrentAP")).get("min")));
}
this.full_round_effect.visual_effect = (String) fullRoundEffect.get("visualEffectID");
}
this.state = State.parsed;
public static final Integer MAGNITUDE_CLEAR = -99;
public static final Integer DURATION_FOREVER = 999;
public static final Integer DURATION_NONE = 0;
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
if (this.icon_id != null) {
String spritesheetId = this.icon_id.split(":")[0];
getProject().getSpritesheet(spritesheetId).addBacklink(this);
}
this.state = State.linked;
}
// Available from init state
//public String id; inherited.
public String icon_id;
public String display_name;
public String description;
public static String getStaticDesc() {
return "Actor Conditions";
}
// Available from parsed state
public ACCategory category = null;
public Integer positive = null;
public Integer stacking = null;
public RoundEffect round_effect = null;
public RoundEffect full_round_effect = null;
public AbilityEffect constant_ability_effect = null;
@Override
public Image getIcon() {
return getProject().getIcon(icon_id);
}
public Image getImage() {
return getProject().getImage(icon_id);
}
@Override
public JSONElement clone() {
ActorCondition clone = new ActorCondition();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.display_name = this.display_name;
clone.icon_id = this.icon_id;
clone.category = this.category;
clone.positive = this.positive;
clone.stacking = this.stacking;
if (this.round_effect != null) {
clone.round_effect = (RoundEffect) this.round_effect.clone();
}
if (this.constant_ability_effect != null) {
clone.constant_ability_effect = (AbilityEffect) constant_ability_effect.clone();
}
if (this.full_round_effect != null) {
clone.full_round_effect = (RoundEffect) this.full_round_effect.clone();
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
//Nothing to link to.
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map jsonAC = new LinkedHashMap();
jsonAC.put("id", this.id);
if (this.icon_id != null) jsonAC.put("iconID", this.icon_id);
if (this.display_name != null) jsonAC.put("name", this.display_name);
if (this.category != null) jsonAC.put("category", this.category.toString());
if (this.positive != null && this.positive == 1) jsonAC.put("isPositive", this.positive);
if (this.stacking != null && this.stacking == 1) jsonAC.put("isStacking", this.stacking);
if (this.round_effect != null) {
Map jsonRound = new LinkedHashMap();
if (this.round_effect.visual_effect != null) jsonRound.put("visualEffectID", this.round_effect.visual_effect);
if (this.round_effect.hp_boost_min != null || this.round_effect.hp_boost_max != null) {
Map jsonHP = new LinkedHashMap();
if (this.round_effect.hp_boost_min != null) jsonHP.put("min", this.round_effect.hp_boost_min);
else jsonHP.put("min", 0);
if (this.round_effect.hp_boost_max != null) jsonHP.put("max", this.round_effect.hp_boost_max);
else jsonHP.put("max", 0);
jsonRound.put("increaseCurrentHP", jsonHP);
}
if (this.round_effect.ap_boost_min != null || this.round_effect.ap_boost_max != null) {
Map jsonAP = new LinkedHashMap();
if (this.round_effect.ap_boost_min != null) jsonAP.put("min", this.round_effect.ap_boost_min);
else jsonAP.put("min", 0);
if (this.round_effect.ap_boost_max != null) jsonAP.put("max", this.round_effect.ap_boost_max);
else jsonAP.put("max", 0);
jsonRound.put("increaseCurrentAP", jsonAP);
}
jsonAC.put("roundEffect", jsonRound);
}
if (this.full_round_effect != null) {
Map jsonFullRound = new LinkedHashMap();
if (this.full_round_effect.visual_effect != null) jsonFullRound.put("visualEffectID", this.full_round_effect.visual_effect);
if (this.full_round_effect.hp_boost_min != null || this.full_round_effect.hp_boost_max != null) {
Map jsonHP = new LinkedHashMap();
if (this.full_round_effect.hp_boost_min != null) jsonHP.put("min", this.full_round_effect.hp_boost_min);
else jsonHP.put("min", 0);
if (this.full_round_effect.hp_boost_max != null) jsonHP.put("max", this.full_round_effect.hp_boost_max);
else jsonHP.put("max", 0);
jsonFullRound.put("increaseCurrentHP", jsonHP);
}
if (this.full_round_effect.ap_boost_min != null || this.full_round_effect.ap_boost_max != null) {
Map jsonAP = new LinkedHashMap();
if (this.full_round_effect.ap_boost_min != null) jsonAP.put("min", this.full_round_effect.ap_boost_min);
else jsonAP.put("min", 0);
if (this.full_round_effect.ap_boost_max != null) jsonAP.put("max", this.full_round_effect.ap_boost_max);
else jsonAP.put("max", 0);
jsonFullRound.put("increaseCurrentAP", jsonAP);
}
jsonAC.put("fullRoundEffect", jsonFullRound);
}
if (this.constant_ability_effect != null) {
Map jsonAbility = new LinkedHashMap();
if (this.constant_ability_effect.increase_attack_chance != null) jsonAbility.put("increaseAttackChance", this.constant_ability_effect.increase_attack_chance);
if (this.constant_ability_effect.increase_damage_min != null || this.constant_ability_effect.increase_damage_max != null) {
Map jsonAD = new LinkedHashMap();
if (this.constant_ability_effect.increase_damage_min != null) jsonAD.put("min", this.constant_ability_effect.increase_damage_min);
else jsonAD.put("min", 0);
if (this.constant_ability_effect.increase_damage_max != null) jsonAD.put("max", this.constant_ability_effect.increase_damage_max);
else jsonAD.put("max", 0);
jsonAbility.put("increaseAttackDamage", jsonAD);
}
if (this.constant_ability_effect.max_hp_boost != null) jsonAbility.put("increaseMaxHP", this.constant_ability_effect.max_hp_boost);
if (this.constant_ability_effect.max_ap_boost != null) jsonAbility.put("increaseMaxAP", this.constant_ability_effect.max_ap_boost);
if (this.constant_ability_effect.increase_move_cost != null) jsonAbility.put("increaseMoveCost", this.constant_ability_effect.increase_move_cost);
if (this.constant_ability_effect.increase_use_cost != null) jsonAbility.put("increaseUseItemCost", this.constant_ability_effect.increase_use_cost);
if (this.constant_ability_effect.increase_reequip_cost != null) jsonAbility.put("increaseReequipCost", this.constant_ability_effect.increase_reequip_cost);
if (this.constant_ability_effect.increase_attack_cost != null) jsonAbility.put("increaseAttackCost", this.constant_ability_effect.increase_attack_cost);
if (this.constant_ability_effect.increase_critical_skill != null) jsonAbility.put("increaseCriticalSkill", this.constant_ability_effect.increase_critical_skill);
if (this.constant_ability_effect.increase_block_chance != null) jsonAbility.put("increaseBlockChance", this.constant_ability_effect.increase_block_chance);
if (this.constant_ability_effect.increase_damage_resistance != null) jsonAbility.put("increaseDamageResistance", this.constant_ability_effect.increase_damage_resistance);
jsonAC.put("abilityEffect", jsonAbility);
}
return jsonAC;
}
public enum ACCategory {
spiritual,
mental,
physical,
blood
}
public static enum VisualEffectID {
redSplash, blueSwirl, greenSplash, miss
}
public static class RoundEffect implements Cloneable {
// Available from parsed state
public VisualEffectID visual_effect = null;
public Integer hp_boost_min = null;
public Integer hp_boost_max = null;
public Integer ap_boost_min = null;
public Integer ap_boost_max = null;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
public static class AbilityEffect implements Cloneable {
// Available from parsed state
public Integer max_hp_boost = null;
public Integer max_ap_boost = null;
public Integer increase_move_cost = null;
public Integer increase_use_cost = null;
public Integer increase_reequip_cost = null;
public Integer increase_attack_cost = null;
public Integer increase_attack_chance = null;
public Integer increase_damage_min = null;
public Integer increase_damage_max = null;
public Integer increase_critical_skill = null;
public Integer increase_block_chance = null;
public Integer increase_damage_resistance = null;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + display_name + " (" + id + ")";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<ActorCondition> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List actorConditions = (List) parser.parse(reader);
for (Object obj : actorConditions) {
Map aCondJson = (Map) obj;
ActorCondition aCond = fromJson(aCondJson);
aCond.jsonFile = jsonFile;
aCond.parent = category;
if (aCond.getDataType() == GameSource.Type.created || aCond.getDataType() == GameSource.Type.altered) {
aCond.writable = true;
}
category.add(aCond);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static ActorCondition fromJson(String jsonString) throws ParseException {
Map aCondJson = (Map) new JSONParser().parse(jsonString);
ActorCondition aCond = fromJson(aCondJson);
aCond.parse(aCondJson);
return aCond;
}
@SuppressWarnings("rawtypes")
public static ActorCondition fromJson(Map aCondJson) {
ActorCondition aCond = new ActorCondition();
aCond.icon_id = (String) aCondJson.get("iconID");
aCond.id = (String) aCondJson.get("id");
aCond.display_name = (String) aCondJson.get("name");
return aCond;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map aCondJson) {
if (aCondJson.get("description") != null) this.description = (String) aCondJson.get("description");
if (aCondJson.get("category") != null) this.category = ACCategory.valueOf((String) aCondJson.get("category"));
this.positive = JSONElement.getInteger((Number) aCondJson.get("isPositive"));
Map abilityEffect = (Map) aCondJson.get("abilityEffect");
if (abilityEffect != null) {
this.constant_ability_effect = new AbilityEffect();
this.constant_ability_effect.increase_attack_chance = JSONElement.getInteger((Number) abilityEffect.get("increaseAttackChance"));
if (abilityEffect.get("increaseAttackDamage") != null) {
this.constant_ability_effect.increase_damage_min = JSONElement.getInteger((Number) (((Map) abilityEffect.get("increaseAttackDamage")).get("min")));
this.constant_ability_effect.increase_damage_max = JSONElement.getInteger((Number) (((Map) abilityEffect.get("increaseAttackDamage")).get("max")));
}
this.constant_ability_effect.max_hp_boost = JSONElement.getInteger((Number) abilityEffect.get("increaseMaxHP"));
this.constant_ability_effect.max_ap_boost = JSONElement.getInteger((Number) abilityEffect.get("increaseMaxAP"));
this.constant_ability_effect.increase_move_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseMoveCost"));
this.constant_ability_effect.increase_use_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseUseItemCost"));
this.constant_ability_effect.increase_reequip_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseReequipCost"));
this.constant_ability_effect.increase_attack_cost = JSONElement.getInteger((Number) abilityEffect.get("increaseAttackCost"));
this.constant_ability_effect.increase_critical_skill = JSONElement.getInteger((Number) abilityEffect.get("increaseCriticalSkill"));
this.constant_ability_effect.increase_block_chance = JSONElement.getInteger((Number) abilityEffect.get("increaseBlockChance"));
this.constant_ability_effect.increase_damage_resistance = JSONElement.getInteger((Number) abilityEffect.get("increaseDamageResistance"));
}
this.stacking = JSONElement.getInteger((Number) aCondJson.get("isStacking"));
Map roundEffect = (Map) aCondJson.get("roundEffect");
if (roundEffect != null) {
this.round_effect = new RoundEffect();
if (roundEffect.get("increaseCurrentHP") != null) {
this.round_effect.hp_boost_max = JSONElement.getInteger((Number) (((Map) roundEffect.get("increaseCurrentHP")).get("max")));
this.round_effect.hp_boost_min = JSONElement.getInteger((Number) (((Map) roundEffect.get("increaseCurrentHP")).get("min")));
}
if (roundEffect.get("increaseCurrentAP") != null) {
this.round_effect.ap_boost_max = JSONElement.getInteger((Number) (((Map) roundEffect.get("increaseCurrentAP")).get("max")));
this.round_effect.ap_boost_min = JSONElement.getInteger((Number) (((Map) roundEffect.get("increaseCurrentAP")).get("min")));
}
String vfx = (String) roundEffect.get("visualEffectID");
this.round_effect.visual_effect = null;
if (vfx != null) {
try {
this.round_effect.visual_effect = VisualEffectID.valueOf(vfx);
} catch (IllegalArgumentException e) {
}
}
}
Map fullRoundEffect = (Map) aCondJson.get("fullRoundEffect");
if (fullRoundEffect != null) {
this.full_round_effect = new RoundEffect();
if (fullRoundEffect.get("increaseCurrentHP") != null) {
this.full_round_effect.hp_boost_max = JSONElement.getInteger((Number) (((Map) fullRoundEffect.get("increaseCurrentHP")).get("max")));
this.full_round_effect.hp_boost_min = JSONElement.getInteger((Number) (((Map) fullRoundEffect.get("increaseCurrentHP")).get("min")));
}
if (fullRoundEffect.get("increaseCurrentAP") != null) {
this.full_round_effect.ap_boost_max = JSONElement.getInteger((Number) (((Map) fullRoundEffect.get("increaseCurrentAP")).get("max")));
this.full_round_effect.ap_boost_min = JSONElement.getInteger((Number) (((Map) fullRoundEffect.get("increaseCurrentAP")).get("min")));
}
String vfx = (String) fullRoundEffect.get("visualEffectID");
this.full_round_effect.visual_effect = null;
if (vfx != null) {
try {
this.full_round_effect.visual_effect = VisualEffectID.valueOf(vfx);
} catch (IllegalArgumentException e) {
}
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
if (this.icon_id != null) {
String spritesheetId = this.icon_id.split(":")[0];
if (getProject().getSpritesheet(spritesheetId) == null) {
System.out.println("Actor Condition");
System.out.println(this.id);
System.out.println("failed to load spritesheet:");
System.out.println(spritesheetId);
System.out.println("while creating backlink for icon_id:");
System.out.println(this.icon_id);
}
getProject().getSpritesheet(spritesheetId).addBacklink(this);
}
this.state = State.linked;
}
public static String getStaticDesc() {
return "Actor Conditions";
}
@Override
public Image getIcon() {
return getProject().getIcon(icon_id);
}
public Image getImage() {
return getProject().getImage(icon_id);
}
@Override
public JSONElement clone() {
ActorCondition clone = new ActorCondition();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.display_name = this.display_name;
clone.description = this.description;
clone.icon_id = this.icon_id;
clone.category = this.category;
clone.positive = this.positive;
clone.stacking = this.stacking;
if (this.round_effect != null) {
clone.round_effect = (RoundEffect) this.round_effect.clone();
}
if (this.constant_ability_effect != null) {
clone.constant_ability_effect = (AbilityEffect) constant_ability_effect.clone();
}
if (this.full_round_effect != null) {
clone.full_round_effect = (RoundEffect) this.full_round_effect.clone();
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
//Nothing to link to.
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map jsonAC = new LinkedHashMap();
jsonAC.put("id", this.id);
if (this.icon_id != null) jsonAC.put("iconID", this.icon_id);
if (this.display_name != null) jsonAC.put("name", this.display_name);
if (this.description != null) jsonAC.put("description", this.description);
if (this.category != null) jsonAC.put("category", this.category.toString());
if (this.positive != null && this.positive == 1) jsonAC.put("isPositive", this.positive);
if (this.stacking != null && this.stacking == 1) jsonAC.put("isStacking", this.stacking);
if (this.round_effect != null) {
Map jsonRound = new LinkedHashMap();
if (this.round_effect.visual_effect != null)
jsonRound.put("visualEffectID", this.round_effect.visual_effect.toString());
if (this.round_effect.hp_boost_min != null || this.round_effect.hp_boost_max != null) {
Map jsonHP = new LinkedHashMap();
if (this.round_effect.hp_boost_min != null) jsonHP.put("min", this.round_effect.hp_boost_min);
else jsonHP.put("min", 0);
if (this.round_effect.hp_boost_max != null) jsonHP.put("max", this.round_effect.hp_boost_max);
else jsonHP.put("max", 0);
jsonRound.put("increaseCurrentHP", jsonHP);
}
if (this.round_effect.ap_boost_min != null || this.round_effect.ap_boost_max != null) {
Map jsonAP = new LinkedHashMap();
if (this.round_effect.ap_boost_min != null) jsonAP.put("min", this.round_effect.ap_boost_min);
else jsonAP.put("min", 0);
if (this.round_effect.ap_boost_max != null) jsonAP.put("max", this.round_effect.ap_boost_max);
else jsonAP.put("max", 0);
jsonRound.put("increaseCurrentAP", jsonAP);
}
jsonAC.put("roundEffect", jsonRound);
}
if (this.full_round_effect != null) {
Map jsonFullRound = new LinkedHashMap();
if (this.full_round_effect.visual_effect != null)
jsonFullRound.put("visualEffectID", this.full_round_effect.visual_effect.toString());
if (this.full_round_effect.hp_boost_min != null || this.full_round_effect.hp_boost_max != null) {
Map jsonHP = new LinkedHashMap();
if (this.full_round_effect.hp_boost_min != null) jsonHP.put("min", this.full_round_effect.hp_boost_min);
else jsonHP.put("min", 0);
if (this.full_round_effect.hp_boost_max != null) jsonHP.put("max", this.full_round_effect.hp_boost_max);
else jsonHP.put("max", 0);
jsonFullRound.put("increaseCurrentHP", jsonHP);
}
if (this.full_round_effect.ap_boost_min != null || this.full_round_effect.ap_boost_max != null) {
Map jsonAP = new LinkedHashMap();
if (this.full_round_effect.ap_boost_min != null) jsonAP.put("min", this.full_round_effect.ap_boost_min);
else jsonAP.put("min", 0);
if (this.full_round_effect.ap_boost_max != null) jsonAP.put("max", this.full_round_effect.ap_boost_max);
else jsonAP.put("max", 0);
jsonFullRound.put("increaseCurrentAP", jsonAP);
}
jsonAC.put("fullRoundEffect", jsonFullRound);
}
if (this.constant_ability_effect != null) {
Map jsonAbility = new LinkedHashMap();
if (this.constant_ability_effect.increase_attack_chance != null)
jsonAbility.put("increaseAttackChance", this.constant_ability_effect.increase_attack_chance);
if (this.constant_ability_effect.increase_damage_min != null || this.constant_ability_effect.increase_damage_max != null) {
Map jsonAD = new LinkedHashMap();
if (this.constant_ability_effect.increase_damage_min != null)
jsonAD.put("min", this.constant_ability_effect.increase_damage_min);
else jsonAD.put("min", 0);
if (this.constant_ability_effect.increase_damage_max != null)
jsonAD.put("max", this.constant_ability_effect.increase_damage_max);
else jsonAD.put("max", 0);
jsonAbility.put("increaseAttackDamage", jsonAD);
}
if (this.constant_ability_effect.max_hp_boost != null)
jsonAbility.put("increaseMaxHP", this.constant_ability_effect.max_hp_boost);
if (this.constant_ability_effect.max_ap_boost != null)
jsonAbility.put("increaseMaxAP", this.constant_ability_effect.max_ap_boost);
if (this.constant_ability_effect.increase_move_cost != null)
jsonAbility.put("increaseMoveCost", this.constant_ability_effect.increase_move_cost);
if (this.constant_ability_effect.increase_use_cost != null)
jsonAbility.put("increaseUseItemCost", this.constant_ability_effect.increase_use_cost);
if (this.constant_ability_effect.increase_reequip_cost != null)
jsonAbility.put("increaseReequipCost", this.constant_ability_effect.increase_reequip_cost);
if (this.constant_ability_effect.increase_attack_cost != null)
jsonAbility.put("increaseAttackCost", this.constant_ability_effect.increase_attack_cost);
if (this.constant_ability_effect.increase_critical_skill != null)
jsonAbility.put("increaseCriticalSkill", this.constant_ability_effect.increase_critical_skill);
if (this.constant_ability_effect.increase_block_chance != null)
jsonAbility.put("increaseBlockChance", this.constant_ability_effect.increase_block_chance);
if (this.constant_ability_effect.increase_damage_resistance != null)
jsonAbility.put("increaseDamageResistance", this.constant_ability_effect.increase_damage_resistance);
jsonAC.put("abilityEffect", jsonAbility);
}
return jsonAC;
}
@Override
public String getProjectFilename() {
return "actorconditions_" + getProject().name + ".json";
}
@Override
public String getProjectFilename() {
return "actorconditions_"+getProject().name+".json";
}
}

View File

@@ -0,0 +1,384 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.Project;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public final class Common {
public static <T extends ActorConditionEffect> void actorConditionElementChanged(List<T> list, GameDataElement oldOne, GameDataElement newOne, GameDataElement backlink) {
if (list != null) {
for (T c : list) {
if (c.condition == oldOne) {
oldOne.removeBacklink(backlink);
c.condition = (ActorCondition) newOne;
if (newOne != null) newOne.addBacklink(backlink);
}
}
}
}
//region link common stuff
public static void linkConditions(List<? extends ActorConditionEffect> conditions, Project proj, GameDataElement backlink) {
if (conditions != null) {
for (ActorConditionEffect ce : conditions) {
if (ce.condition_id != null) ce.condition = proj.getActorCondition(ce.condition_id);
if (ce.condition != null) ce.condition.addBacklink(backlink);
}
}
}
public static void linkEffects(HitEffect effect, Project proj, GameDataElement backlink) {
linkEffects((DeathEffect) effect, proj, backlink);
if (effect != null) {
linkConditions(effect.conditions_target, proj, backlink);
}
}
public static void linkEffects(DeathEffect effect, Project proj, GameDataElement backlink) {
if (effect != null) {
linkConditions(effect.conditions_source, proj, backlink);
}
}
public static void linkIcon(Project proj, String iconId, GameDataElement backlink) {
if (iconId != null) {
String spritesheetId = iconId.split(":")[0];
if (proj.getSpritesheet(spritesheetId) == null) {
Notification.addError("Error Spritesheet " + spritesheetId + ". has no backlink. (" + iconId + ")");
return;
}
proj.getSpritesheet(spritesheetId).addBacklink(backlink);
}
}
//endregion
//region write common stuff
public static void writeMinMaxToMap(Map parent, Integer min, Integer max, int defaultValue) {
if (min != null || max != null) {
if (min != null)
parent.put("min", min);
else parent.put("min", defaultValue);
if (max != null)
parent.put("max", max);
else parent.put("max", defaultValue);
}
}
public static void writeMinMaxToMap(Map parent, String key, Integer min, Integer max, int defaultValue) {
if (min != null || max != null) {
Map minMaxMap = new LinkedHashMap();
parent.put(key, minMaxMap);
writeMinMaxToMap(minMaxMap, min, max, defaultValue);
}
}
public static void writeDescriptionToMap(Map parent, String description) {
if (description != null) parent.put("description", description);
}
public static void writeIconToMap(Map parent, String icon_id) {
if (icon_id != null) parent.put("iconID", icon_id);
}
public static void writeHitReceivedEffectToMap(Map parent, HitReceivedEffect effect) {
if (effect != null) {
writeHitEffectToMap(parent, effect);
writeBasicEffectObjectToMap(effect.target, parent, "increaseAttackerCurrentHP", "increaseAttackerCurrentAP");
}
}
public static void writeHitReceivedEffectToMap(Map parent, HitReceivedEffect effect, String key) {
if (effect != null) {
Map effectJson = new LinkedHashMap();
parent.put(key, effectJson);
writeHitReceivedEffectToMap(effectJson, effect);
}
}
public static void writeHitEffectToMap(Map parent, HitEffect effect) {
if (effect != null) {
writeDeathEffectToMap(parent, effect);
writeTimedActorConditionEffectObjectToMap(effect.conditions_target, parent, "conditionsTarget");
}
}
public static void writeHitEffectToMap(Map parent, HitEffect effect, String key) {
if (effect != null) {
Map effectJson = new LinkedHashMap();
parent.put(key, effectJson);
writeHitEffectToMap(effectJson, effect);
}
}
public static void writeDeathEffectToMap(Map parent, DeathEffect effect) {
writeBasicEffectObjectToMap(effect, parent, "increaseCurrentHP", "increaseCurrentAP");
writeTimedActorConditionEffectObjectToMap(effect.conditions_source, parent, "conditionsSource");
}
public static void writeDeathEffectToMap(Map parent, DeathEffect effect, String key) {
if (effect != null) {
Map effectJson = new LinkedHashMap();
parent.put(key, effectJson);
writeDeathEffectToMap(effectJson, effect);
}
}
public static void writeBasicEffectObjectToMap(BasicEffect effect, Map parent, String keyHP, String keyAP) {
writeMinMaxToMap(parent, keyHP, effect.hp_boost_min, effect.hp_boost_max, 0);
writeMinMaxToMap(parent, keyAP, effect.ap_boost_min, effect.ap_boost_max, 0);
}
public static void writeTimedActorConditionEffectObjectToMap(List<TimedActorConditionEffect> list, Map parent, String key) {
if (list != null) {
List conditionsSourceJson = new ArrayList();
parent.put(key, conditionsSourceJson);
for (TimedActorConditionEffect condition : list) {
Map conditionJson = new LinkedHashMap();
conditionsSourceJson.add(conditionJson);
writeTimedConditionEffectToMap(condition, conditionJson);
}
}
}
public static void writeConditionEffectToMap(ActorConditionEffect condition, Map parent) {
if (condition.condition != null) {
parent.put("condition", condition.condition.id);
} else if (condition.condition_id != null) {
parent.put("condition", condition.condition_id);
}
if (condition.magnitude != null) {
parent.put("magnitude", condition.magnitude);
}
}
public static void writeTimedConditionEffectToMap(TimedActorConditionEffect condition, Map parent) {
writeConditionEffectToMap(condition, parent);
if (condition.duration != null) {
parent.put("duration", condition.duration);
}
if (condition.chance != null) {
parent.put("chance", JSONElement.printJsonChance(condition.chance));
}
}
//endregion
public static class TimedActorConditionEffect extends ActorConditionEffect {
//Available from parsed state
public Integer duration = null;
public Double chance = null;
public TimedActorConditionEffect createClone() {
TimedActorConditionEffect cclone = new TimedActorConditionEffect();
cclone.magnitude = this.magnitude;
cclone.condition_id = this.condition_id;
cclone.condition = this.condition;
cclone.chance = this.chance;
cclone.duration = this.duration;
return cclone;
}
public boolean isInfinite() {
return duration != null && duration.equals(ActorCondition.DURATION_FOREVER);
}
public boolean isImmunity() {
return (super.isClear()) && (duration != null && duration > ActorCondition.DURATION_NONE);
}
@Override
public boolean isClear() {
return (super.isClear()) && (duration == null || duration.equals(ActorCondition.DURATION_NONE));
}
}
public static class ActorConditionEffect {
//Available from parsed state
public Integer magnitude = null;
public String condition_id = null;
//Available from linked state
public ActorCondition condition = null;
public boolean isClear() {
return magnitude == null || magnitude.equals(ActorCondition.MAGNITUDE_CLEAR);
}
}
@SuppressWarnings("rawtypes")
public static ArrayList<TimedActorConditionEffect> parseTimedConditionEffects(List conditionsSourceJson) {
ArrayList<TimedActorConditionEffect> conditions_source;
if (conditionsSourceJson != null && !conditionsSourceJson.isEmpty()) {
conditions_source = new ArrayList<>();
for (Object conditionJsonObj : conditionsSourceJson) {
Map conditionJson = (Map) conditionJsonObj;
TimedActorConditionEffect condition = new TimedActorConditionEffect();
readConditionEffect(condition, conditionJson);
condition.duration = JSONElement.getInteger((Number) conditionJson.get("duration"));
if (conditionJson.get("chance") != null)
condition.chance = JSONElement.parseChance(conditionJson.get("chance").toString());
conditions_source.add(condition);
}
} else {
conditions_source = null;
}
return conditions_source;
}
@SuppressWarnings("rawtypes")
private static void readConditionEffect(ActorConditionEffect condition, Map conditionJson) {
condition.condition_id = (String) conditionJson.get("condition");
condition.magnitude = JSONElement.getInteger((Number) conditionJson.get("magnitude"));
}
@SuppressWarnings("rawtypes")
public static Common.DeathEffect parseDeathEffect(Map killEffect) {
Common.DeathEffect kill_effect = new Common.DeathEffect();
readDeathEffect(killEffect, kill_effect);
return kill_effect;
}
@SuppressWarnings("rawtypes")
public static HitEffect parseHitEffect(Map hitEffect) {
Common.HitEffect hit_effect = new Common.HitEffect();
readHitEffect(hitEffect, hit_effect);
return hit_effect;
}
@SuppressWarnings("rawtypes")
public static HitReceivedEffect parseHitReceivedEffect(Map hitReceivedEffect) {
HitReceivedEffect hit_received_effect = new Common.HitReceivedEffect();
readHitEffect(hitReceivedEffect, hit_received_effect);
if (hitReceivedEffect.get("increaseAttackerCurrentHP") != null) {
hit_received_effect.target.hp_boost_max = JSONElement.getInteger((Number) (((Map) hitReceivedEffect.get("increaseAttackerCurrentHP")).get("max")));
hit_received_effect.target.hp_boost_min = JSONElement.getInteger((Number) (((Map) hitReceivedEffect.get("increaseAttackerCurrentHP")).get("min")));
}
if (hitReceivedEffect.get("increaseAttackerCurrentAP") != null) {
hit_received_effect.target.ap_boost_max = JSONElement.getInteger((Number) (((Map) hitReceivedEffect.get("increaseAttackerCurrentAP")).get("max")));
hit_received_effect.target.ap_boost_min = JSONElement.getInteger((Number) (((Map) hitReceivedEffect.get("increaseAttackerCurrentAP")).get("min")));
}
return hit_received_effect;
}
@SuppressWarnings("rawtypes")
private static void readDeathEffect(Map killEffect, DeathEffect kill_effect) {
if (killEffect.get("increaseCurrentHP") != null) {
kill_effect.hp_boost_min = JSONElement.getInteger((Number) (((Map) killEffect.get("increaseCurrentHP")).get("min")));
kill_effect.hp_boost_max = JSONElement.getInteger((Number) (((Map) killEffect.get("increaseCurrentHP")).get("max")));
}
if (killEffect.get("increaseCurrentAP") != null) {
kill_effect.ap_boost_min = JSONElement.getInteger((Number) (((Map) killEffect.get("increaseCurrentAP")).get("min")));
kill_effect.ap_boost_max = JSONElement.getInteger((Number) (((Map) killEffect.get("increaseCurrentAP")).get("max")));
}
List conditionsSourceJson = (List) killEffect.get("conditionsSource");
kill_effect.conditions_source = parseTimedConditionEffects(conditionsSourceJson);
}
@SuppressWarnings("rawtypes")
private static void readHitEffect(Map hitEffect, HitEffect hit_effect) {
readDeathEffect(hitEffect, hit_effect);
List conditionsTargetJson = (List) hitEffect.get("conditionsTarget");
hit_effect.conditions_target = parseTimedConditionEffects(conditionsTargetJson);
}
public static class BasicEffect {
public Integer hp_boost_min = null;
public Integer hp_boost_max = null;
public Integer ap_boost_min = null;
public Integer ap_boost_max = null;
public boolean isNull() {
if (ap_boost_min != null) return false;
if (ap_boost_max != null) return false;
if (hp_boost_min != null) return false;
if (hp_boost_max != null) return false;
return true;
}
}
public static class DeathEffect extends BasicEffect {
//Available from parsed state
public List<TimedActorConditionEffect> conditions_source = null;
@Override
public boolean isNull() {
if (!super.isNull()) return false;
if (conditions_source != null) return false;
return true;
}
}
public static class HitEffect extends DeathEffect {
//Available from parsed state
public List<TimedActorConditionEffect> conditions_target = null;
@Override
public boolean isNull() {
if (!super.isNull()) return false;
if (conditions_target != null) return false;
return true;
}
}
public static class HitReceivedEffect extends Common.HitEffect {
//Available from parsed state
public BasicEffect target = new BasicEffect();
@Override
public boolean isNull() {
if (!super.isNull()) return false;
if (!target.isNull()) return false;
return true;
}
}
public static void copyDeathEffectValues(Common.DeathEffect target, Common.DeathEffect source, GameDataElement backlink) {
copyEffectValues(target, source);
if (source.conditions_source != null) {
target.conditions_source = new ArrayList<>();
for (TimedActorConditionEffect c : source.conditions_source) {
TimedActorConditionEffect cclone = c.createClone();
if (cclone.condition != null) {
cclone.condition.addBacklink(backlink);
}
target.conditions_source.add(cclone);
}
}
}
private static void copyEffectValues(BasicEffect target, BasicEffect source) {
target.ap_boost_max = source.ap_boost_max;
target.ap_boost_min = source.ap_boost_min;
target.hp_boost_max = source.hp_boost_max;
target.hp_boost_min = source.hp_boost_min;
}
public static void copyHitEffectValues(Common.HitEffect target, Common.HitEffect source, GameDataElement backlink) {
copyDeathEffectValues(target, source, backlink);
if (source.conditions_target != null) {
target.conditions_target = new ArrayList<>();
for (TimedActorConditionEffect c : source.conditions_target) {
TimedActorConditionEffect cclone = c.createClone();
if (cclone.condition != null) {
cclone.condition.addBacklink(backlink);
}
target.conditions_target.add(cclone);
}
}
}
public static void copyHitReceivedEffectValues(Common.HitReceivedEffect target, Common.HitReceivedEffect source, GameDataElement backlink) {
copyHitEffectValues(target, source, backlink);
copyEffectValues(target.target, source.target);
}
}

View File

@@ -1,19 +1,5 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
@@ -21,444 +7,455 @@ import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement.RequirementType;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.*;
public class Dialogue extends JSONElement {
private static final long serialVersionUID = -6872164604703134683L;
//Available from init state
//public String id = null; inherited.
public String message = null;
//Available from parsed state;
public List<Reward> rewards = null;
public List<Reply> replies = null;
public String switch_to_npc_id = null;
//Available from linked state;
public NPC switch_to_npc = null;
public static class Reward {
//Available from parsed state
public RewardType type = null;
public String reward_obj_id = null;
public Integer reward_value = null;
public String map_name = null;
//Available from linked state
public GameDataElement reward_obj = null;
public TMXMap map = null;
public enum RewardType {
questProgress,
removeQuestProgress,
dropList,
skillIncrease,
actorCondition,
alignmentChange,
giveItem,
createTimer,
spawnAll,
removeSpawnArea,
deactivateSpawnArea,
activateMapObjectGroup,
deactivateMapObjectGroup,
changeMapFilter
}
}
public static class Reply {
public static final String GO_NEXT_TEXT = "N";
public static final String SHOP_PHRASE_ID = "S";
public static final String FIGHT_PHRASE_ID = "F";
public static final String EXIT_PHRASE_ID = "X";
public static final String REMOVE_PHRASE_ID = "R";
public static final List<String> KEY_PHRASE_ID = Arrays.asList(new String[]{SHOP_PHRASE_ID, FIGHT_PHRASE_ID, EXIT_PHRASE_ID, REMOVE_PHRASE_ID});
//Available from parsed state
public String text = null;
public String next_phrase_id = null;
public List<Requirement> requirements = null;
//Available from linked state
public Dialogue next_phrase = null;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+id;
}
public static String getStaticDesc() {
return "Dialogues";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<Dialogue> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List dialogues = (List) parser.parse(reader);
for (Object obj : dialogues) {
Map dialogueJson = (Map)obj;
Dialogue dialogue = fromJson(dialogueJson);
dialogue.jsonFile = jsonFile;
dialogue.parent = category;
if (dialogue.getDataType() == GameSource.Type.created || dialogue.getDataType() == GameSource.Type.altered) {
dialogue.writable = true;
}
category.add(dialogue);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static Dialogue fromJson(String jsonString) throws ParseException {
Map dialogueJson = (Map) new JSONParser().parse(jsonString);
Dialogue dialogue = fromJson(dialogueJson);
dialogue.parse(dialogueJson);
return dialogue;
}
@SuppressWarnings("rawtypes")
public static Dialogue fromJson(Map dialogueJson) {
Dialogue dialogue = new Dialogue();
dialogue.id = (String) dialogueJson.get("id");
dialogue.message = (String) dialogueJson.get("message");
return dialogue;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map dialogueJson) {
this.switch_to_npc_id = (String) dialogueJson.get("switchToNPC");
List repliesJson = (List) dialogueJson.get("replies");
if (repliesJson != null && !repliesJson.isEmpty()) {
this.replies = new ArrayList<Dialogue.Reply>();
for (Object replyJsonObj : repliesJson) {
Map replyJson = (Map)replyJsonObj;
Reply reply = new Reply();
reply.text = (String) replyJson.get("text");
reply.next_phrase_id = (String) replyJson.get("nextPhraseID");
List requirementsJson = (List) replyJson.get("requires");
if (requirementsJson != null && !requirementsJson.isEmpty()) {
reply.requirements = new ArrayList<Requirement>();
for (Object requirementJsonObj : requirementsJson) {
Map requirementJson = (Map) requirementJsonObj;
Requirement requirement = new Requirement();
requirement.jsonFile = this.jsonFile;
requirement.parent = this;
if (requirementJson.get("requireType") != null) requirement.type = RequirementType.valueOf((String) requirementJson.get("requireType"));
requirement.required_obj_id = (String) requirementJson.get("requireID");
if (requirementJson.get("value") != null) requirement.required_value = JSONElement.getInteger(Integer.parseInt(requirementJson.get("value").toString()));
if (requirementJson.get("negate") != null) requirement.negated = (Boolean) requirementJson.get("negate");
requirement.state = State.parsed;
reply.requirements.add(requirement);
}
}
this.replies.add(reply);
}
}
List rewardsJson = (List) dialogueJson.get("rewards");
if (rewardsJson != null && !rewardsJson.isEmpty()) {
this.rewards = new ArrayList<Dialogue.Reward>();
for (Object rewardJsonObj : rewardsJson) {
Map rewardJson = (Map)rewardJsonObj;
Reward reward = new Reward();
if (rewardJson.get("rewardType") != null) reward.type = Reward.RewardType.valueOf((String) rewardJson.get("rewardType"));
if (rewardJson.get("rewardID") != null) reward.reward_obj_id = (String) rewardJson.get("rewardID");
if (rewardJson.get("value") != null) reward.reward_value = JSONElement.getInteger((Number) rewardJson.get("value"));
if (rewardJson.get("mapName") != null) reward.map_name = (String) rewardJson.get("mapName");
this.rewards.add(reward);
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking dialogue "+id+". No parent project found.");
return;
}
if (this.switch_to_npc_id != null) this.switch_to_npc = proj.getNPC(this.switch_to_npc_id);
if (this.switch_to_npc != null) this.switch_to_npc.addBacklink(this);
if (replies != null) {
for (Reply reply : replies) {
if (reply.next_phrase_id != null) {
if (!Reply.KEY_PHRASE_ID.contains(reply.next_phrase_id)) {
reply.next_phrase = proj.getDialogue(reply.next_phrase_id);
}
}
if (reply.next_phrase != null) reply.next_phrase.addBacklink(this);
if (reply.requirements != null) {
for (Requirement requirement : reply.requirements) {
requirement.link();
}
}
}
}
if (rewards != null) {
for (Reward reward : rewards) {
if (reward.reward_obj_id != null) {
switch (reward.type) {
case activateMapObjectGroup:
case deactivateMapObjectGroup:
case spawnAll:
case removeSpawnArea:
case deactivateSpawnArea:
case changeMapFilter:
reward.map = reward.map_name != null ? proj.getMap(reward.map_name) : null;
break;
case actorCondition:
reward.reward_obj = proj.getActorCondition(reward.reward_obj_id);
break;
case alignmentChange:
//Nothing to do (yet ?).
break;
case createTimer:
//Nothing to do.
break;
case dropList:
reward.reward_obj = proj.getDroplist(reward.reward_obj_id);
break;
case giveItem:
reward.reward_obj = proj.getItem(reward.reward_obj_id);
break;
case questProgress:
case removeQuestProgress:
reward.reward_obj = proj.getQuest(reward.reward_obj_id);
if (reward.reward_obj != null && reward.reward_value != null) {
QuestStage stage = ((Quest)reward.reward_obj).getStage(reward.reward_value);
if (stage != null) {
stage.addBacklink(this);
}
}
break;
case skillIncrease:
//Nothing to do (yet ?).
break;
}
if (reward.reward_obj != null) reward.reward_obj.addBacklink(this);
if (reward.map != null) reward.map.addBacklink(this);
}
}
}
this.state = State.linked;
}
private static final long serialVersionUID = -6872164604703134683L;
@Override
public Image getIcon() {
return DefaultIcons.getDialogueIcon();
}
//Available from init state
//public String id = null; inherited.
public String message = null;
public Image getImage() {
return DefaultIcons.getDialogueImage();
}
@Override
public GameDataElement clone() {
Dialogue clone = new Dialogue();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.message = this.message;
clone.switch_to_npc_id = this.switch_to_npc_id;
clone.switch_to_npc = this.switch_to_npc;
if (clone.switch_to_npc != null) {
clone.switch_to_npc.addBacklink(clone);
}
if (this.rewards != null) {
clone.rewards = new ArrayList<Dialogue.Reward>();
for (Reward r : this.rewards) {
Reward rclone = new Reward();
rclone.type = r.type;
rclone.reward_obj_id = r.reward_obj_id;
rclone.reward_value = r.reward_value;
rclone.reward_obj = r.reward_obj;
if (rclone.reward_obj != null) {
rclone.reward_obj.addBacklink(clone);
}
rclone.map = r.map;
rclone.map_name = r.map_name;
if (rclone.map != null) {
rclone.map.addBacklink(clone);
}
clone.rewards.add(rclone);
}
}
if (this.replies != null) {
clone.replies = new ArrayList<Dialogue.Reply>();
for (Reply r : this.replies) {
Reply rclone = new Reply();
rclone.text = r.text;
rclone.next_phrase_id = r.next_phrase_id;
rclone.next_phrase = r.next_phrase;
if (rclone.next_phrase != null) {
rclone.next_phrase.addBacklink(clone);
}
if (r.requirements != null) {
rclone.requirements = new ArrayList<Requirement>();
for (Requirement req : r.requirements) {
//Special clone method, as Requirement is a special GDE, hidden from the project tree.
rclone.requirements.add((Requirement) req.clone(clone));
}
}
clone.replies.add(rclone);
}
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (switch_to_npc == oldOne) {
oldOne.removeBacklink(this);
switch_to_npc = (NPC) newOne;
if (newOne != null) newOne.addBacklink(this);
} else {
if (replies != null) {
for (Reply r : replies) {
if (r.next_phrase == oldOne) {
oldOne.removeBacklink(this);
r.next_phrase = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(this);
}
if (r.requirements != null) {
for (Requirement req : r.requirements) {
req.elementChanged(oldOne, newOne);
}
}
}
}
if (rewards != null) {
for (Reward r : rewards) {
if (r.reward_obj == oldOne) {
oldOne.removeBacklink(this);
r.reward_obj = newOne;
if (newOne != null) newOne.addBacklink(this);
}
if (oldOne instanceof QuestStage) {
if (r.reward_obj != null && r.reward_obj.equals(oldOne.parent) && r.reward_value != null && r.reward_value.equals(((QuestStage) oldOne).progress)) {
oldOne.removeBacklink((GameDataElement) this);
if (newOne != null) newOne.addBacklink((GameDataElement) this);
}
}
}
}
}
}
//Available from parsed state;
public List<Reward> rewards = null;
public List<Reply> replies = null;
public String switch_to_npc_id = null;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map dialogueJson = new LinkedHashMap();
dialogueJson.put("id", this.id);
if (this.message != null) dialogueJson.put("message", this.message);
if (this.switch_to_npc != null) {
dialogueJson.put("switchToNPC", this.switch_to_npc.id);
} else if (this.switch_to_npc_id != null) {
dialogueJson.put("switchToNPC", this.switch_to_npc_id);
}
if (this.replies != null) {
List repliesJson = new ArrayList();
dialogueJson.put("replies", repliesJson);
for (Reply reply : this.replies){
Map replyJson = new LinkedHashMap();
repliesJson.add(replyJson);
if (reply.text != null) replyJson.put("text", reply.text);
if (reply.next_phrase != null) {
replyJson.put("nextPhraseID", reply.next_phrase.id);
} else if (reply.next_phrase_id != null) {
replyJson.put("nextPhraseID", reply.next_phrase_id);
}
if (reply.requirements != null) {
List requirementsJson = new ArrayList();
replyJson.put("requires", requirementsJson);
for (Requirement requirement : reply.requirements) {
Map requirementJson = new LinkedHashMap();
requirementsJson.add(requirementJson);
if (requirement.type != null) requirementJson.put("requireType", requirement.type.toString());
if (requirement.required_obj != null) {
requirementJson.put("requireID", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
requirementJson.put("requireID", requirement.required_obj_id);
}
if (requirement.required_value != null) {
requirementJson.put("value", requirement.required_value);
}
if (requirement.negated != null) requirementJson.put("negate", requirement.negated);
}
}
}
}
if (this.rewards != null) {
List rewardsJson = new ArrayList();
dialogueJson.put("rewards", rewardsJson);
for (Reward reward : this.rewards) {
Map rewardJson = new LinkedHashMap();
rewardsJson.add(rewardJson);
if (reward.type != null) rewardJson.put("rewardType", reward.type.toString());
if (reward.reward_obj != null) {
rewardJson.put("rewardID", reward.reward_obj.id);
} else if (reward.reward_obj_id != null) {
rewardJson.put("rewardID", reward.reward_obj_id);
}
if (reward.reward_value != null) rewardJson.put("value", reward.reward_value);
if (reward.map != null) {
rewardJson.put("mapName", reward.map.id);
} else if (reward.map_name != null) rewardJson.put("mapName", reward.map_name);
}
}
return dialogueJson;
}
//Available from linked state;
public NPC switch_to_npc = null;
public static class Reward {
//Available from parsed state
public RewardType type = null;
public String reward_obj_id = null;
public Integer reward_value = null;
public String map_name = null;
//Available from linked state
public GameDataElement reward_obj = null;
public TMXMap map = null;
public enum RewardType {
questProgress,
removeQuestProgress,
dropList,
skillIncrease,
actorCondition,
actorConditionImmunity,
alignmentChange,
alignmentSet,
giveItem,
createTimer,
spawnAll,
removeSpawnArea,
deactivateSpawnArea,
activateMapObjectGroup,
deactivateMapObjectGroup,
changeMapFilter,
mapchange
}
}
public static class Reply {
public static final String GO_NEXT_TEXT = "N";
public static final String SHOP_PHRASE_ID = "S";
public static final String FIGHT_PHRASE_ID = "F";
public static final String EXIT_PHRASE_ID = "X";
public static final String REMOVE_PHRASE_ID = "R";
public static final List<String> KEY_PHRASE_ID = Arrays.asList(new String[]{SHOP_PHRASE_ID, FIGHT_PHRASE_ID, EXIT_PHRASE_ID, REMOVE_PHRASE_ID});
//Available from parsed state
public String text = null;
public String next_phrase_id = null;
public List<Requirement> requirements = null;
//Available from linked state
public Dialogue next_phrase = null;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + id;
}
public static String getStaticDesc() {
return "Dialogues";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<Dialogue> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List dialogues = (List) parser.parse(reader);
for (Object obj : dialogues) {
Map dialogueJson = (Map) obj;
Dialogue dialogue = fromJson(dialogueJson);
dialogue.jsonFile = jsonFile;
dialogue.parent = category;
if (dialogue.getDataType() == GameSource.Type.created || dialogue.getDataType() == GameSource.Type.altered) {
dialogue.writable = true;
}
category.add(dialogue);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static Dialogue fromJson(String jsonString) throws ParseException {
Map dialogueJson = (Map) new JSONParser().parse(jsonString);
Dialogue dialogue = fromJson(dialogueJson);
dialogue.parse(dialogueJson);
return dialogue;
}
@SuppressWarnings("rawtypes")
public static Dialogue fromJson(Map dialogueJson) {
Dialogue dialogue = new Dialogue();
dialogue.id = (String) dialogueJson.get("id");
dialogue.message = (String) dialogueJson.get("message");
return dialogue;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map dialogueJson) {
this.switch_to_npc_id = (String) dialogueJson.get("switchToNPC");
List repliesJson = (List) dialogueJson.get("replies");
if (repliesJson != null && !repliesJson.isEmpty()) {
this.replies = new ArrayList<Dialogue.Reply>();
for (Object replyJsonObj : repliesJson) {
Map replyJson = (Map) replyJsonObj;
Reply reply = new Reply();
reply.text = (String) replyJson.get("text");
reply.next_phrase_id = (String) replyJson.get("nextPhraseID");
List requirementsJson = (List) replyJson.get("requires");
if (requirementsJson != null && !requirementsJson.isEmpty()) {
reply.requirements = new ArrayList<Requirement>();
for (Object requirementJsonObj : requirementsJson) {
Map requirementJson = (Map) requirementJsonObj;
Requirement requirement = new Requirement();
requirement.jsonFile = this.jsonFile;
requirement.parent = this;
if (requirementJson.get("requireType") != null)
requirement.type = RequirementType.valueOf((String) requirementJson.get("requireType"));
requirement.required_obj_id = (String) requirementJson.get("requireID");
if (requirementJson.get("value") != null)
requirement.required_value = JSONElement.getInteger(Integer.parseInt(requirementJson.get("value").toString()));
if (requirementJson.get("negate") != null)
requirement.negated = (Boolean) requirementJson.get("negate");
requirement.state = State.parsed;
reply.requirements.add(requirement);
}
}
this.replies.add(reply);
}
}
List rewardsJson = (List) dialogueJson.get("rewards");
if (rewardsJson != null && !rewardsJson.isEmpty()) {
this.rewards = new ArrayList<Dialogue.Reward>();
for (Object rewardJsonObj : rewardsJson) {
Map rewardJson = (Map) rewardJsonObj;
Reward reward = new Reward();
if (rewardJson.get("rewardType") != null)
reward.type = Reward.RewardType.valueOf((String) rewardJson.get("rewardType"));
if (rewardJson.get("rewardID") != null) reward.reward_obj_id = (String) rewardJson.get("rewardID");
if (rewardJson.get("value") != null)
reward.reward_value = JSONElement.getInteger((Number) rewardJson.get("value"));
if (rewardJson.get("mapName") != null) reward.map_name = (String) rewardJson.get("mapName");
this.rewards.add(reward);
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking dialogue " + id + ". No parent project found.");
return;
}
if (this.switch_to_npc_id != null) this.switch_to_npc = proj.getNPC(this.switch_to_npc_id);
if (this.switch_to_npc != null) this.switch_to_npc.addBacklink(this);
if (replies != null) {
for (Reply reply : replies) {
if (reply.next_phrase_id != null) {
if (!Reply.KEY_PHRASE_ID.contains(reply.next_phrase_id)) {
reply.next_phrase = proj.getDialogue(reply.next_phrase_id);
}
}
if (reply.next_phrase != null) reply.next_phrase.addBacklink(this);
if (reply.requirements != null) {
for (Requirement requirement : reply.requirements) {
requirement.link();
}
}
}
}
if (rewards != null) {
for (Reward reward : rewards) {
if (reward.reward_obj_id != null) {
switch (reward.type) {
case activateMapObjectGroup:
case deactivateMapObjectGroup:
case spawnAll:
case removeSpawnArea:
case deactivateSpawnArea:
case changeMapFilter:
case mapchange:
reward.map = reward.map_name != null ? proj.getMap(reward.map_name) : null;
break;
case actorCondition:
case actorConditionImmunity:
reward.reward_obj = proj.getActorCondition(reward.reward_obj_id);
break;
case alignmentChange:
case alignmentSet:
//Nothing to do (yet ?).
break;
case createTimer:
//Nothing to do.
break;
case dropList:
reward.reward_obj = proj.getDroplist(reward.reward_obj_id);
break;
case giveItem:
reward.reward_obj = proj.getItem(reward.reward_obj_id);
break;
case questProgress:
case removeQuestProgress:
reward.reward_obj = proj.getQuest(reward.reward_obj_id);
if (reward.reward_obj != null && reward.reward_value != null) {
QuestStage stage = ((Quest) reward.reward_obj).getStage(reward.reward_value);
if (stage != null) {
stage.addBacklink(this);
}
}
break;
case skillIncrease:
//Nothing to do (yet ?).
break;
}
if (reward.reward_obj != null) reward.reward_obj.addBacklink(this);
if (reward.map != null) reward.map.addBacklink(this);
}
}
}
this.state = State.linked;
}
@Override
public Image getIcon() {
return DefaultIcons.getDialogueIcon();
}
public Image getImage() {
return DefaultIcons.getDialogueImage();
}
@Override
public GameDataElement clone() {
Dialogue clone = new Dialogue();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.message = this.message;
clone.switch_to_npc_id = this.switch_to_npc_id;
clone.switch_to_npc = this.switch_to_npc;
if (clone.switch_to_npc != null) {
clone.switch_to_npc.addBacklink(clone);
}
if (this.rewards != null) {
clone.rewards = new ArrayList<Dialogue.Reward>();
for (Reward r : this.rewards) {
Reward rclone = new Reward();
rclone.type = r.type;
rclone.reward_obj_id = r.reward_obj_id;
rclone.reward_value = r.reward_value;
rclone.reward_obj = r.reward_obj;
if (rclone.reward_obj != null) {
rclone.reward_obj.addBacklink(clone);
}
rclone.map = r.map;
rclone.map_name = r.map_name;
if (rclone.map != null) {
rclone.map.addBacklink(clone);
}
clone.rewards.add(rclone);
}
}
if (this.replies != null) {
clone.replies = new ArrayList<Dialogue.Reply>();
for (Reply r : this.replies) {
Reply rclone = new Reply();
rclone.text = r.text;
rclone.next_phrase_id = r.next_phrase_id;
rclone.next_phrase = r.next_phrase;
if (rclone.next_phrase != null) {
rclone.next_phrase.addBacklink(clone);
}
if (r.requirements != null) {
rclone.requirements = new ArrayList<Requirement>();
for (Requirement req : r.requirements) {
//Special clone method, as Requirement is a special GDE, hidden from the project tree.
rclone.requirements.add((Requirement) req.clone(clone));
}
}
clone.replies.add(rclone);
}
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (switch_to_npc == oldOne) {
oldOne.removeBacklink(this);
switch_to_npc = (NPC) newOne;
if (newOne != null) newOne.addBacklink(this);
} else {
if (replies != null) {
for (Reply r : replies) {
if (r.next_phrase == oldOne) {
oldOne.removeBacklink(this);
r.next_phrase = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(this);
}
if (r.requirements != null) {
for (Requirement req : r.requirements) {
req.elementChanged(oldOne, newOne);
}
}
}
}
if (rewards != null) {
for (Reward r : rewards) {
if (r.reward_obj == oldOne) {
oldOne.removeBacklink(this);
r.reward_obj = newOne;
if (newOne != null) newOne.addBacklink(this);
}
if (oldOne instanceof QuestStage) {
if (r.reward_obj != null && r.reward_obj.equals(oldOne.parent) && r.reward_value != null && r.reward_value.equals(((QuestStage) oldOne).progress)) {
oldOne.removeBacklink((GameDataElement) this);
if (newOne != null) newOne.addBacklink((GameDataElement) this);
}
}
}
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map dialogueJson = new LinkedHashMap();
dialogueJson.put("id", this.id);
if (this.message != null) dialogueJson.put("message", this.message);
if (this.switch_to_npc != null) {
dialogueJson.put("switchToNPC", this.switch_to_npc.id);
} else if (this.switch_to_npc_id != null) {
dialogueJson.put("switchToNPC", this.switch_to_npc_id);
}
if (this.replies != null) {
List repliesJson = new ArrayList();
dialogueJson.put("replies", repliesJson);
for (Reply reply : this.replies) {
Map replyJson = new LinkedHashMap();
repliesJson.add(replyJson);
if (reply.text != null) replyJson.put("text", reply.text);
if (reply.next_phrase != null) {
replyJson.put("nextPhraseID", reply.next_phrase.id);
} else if (reply.next_phrase_id != null) {
replyJson.put("nextPhraseID", reply.next_phrase_id);
}
if (reply.requirements != null) {
List requirementsJson = new ArrayList();
replyJson.put("requires", requirementsJson);
for (Requirement requirement : reply.requirements) {
Map requirementJson = new LinkedHashMap();
requirementsJson.add(requirementJson);
if (requirement.type != null) requirementJson.put("requireType", requirement.type.toString());
if (requirement.required_obj != null) {
requirementJson.put("requireID", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
requirementJson.put("requireID", requirement.required_obj_id);
}
if (requirement.required_value != null) {
requirementJson.put("value", requirement.required_value);
}
if (requirement.negated != null) requirementJson.put("negate", requirement.negated);
}
}
}
}
if (this.rewards != null) {
List rewardsJson = new ArrayList();
dialogueJson.put("rewards", rewardsJson);
for (Reward reward : this.rewards) {
Map rewardJson = new LinkedHashMap();
rewardsJson.add(rewardJson);
if (reward.type != null) rewardJson.put("rewardType", reward.type.toString());
if (reward.reward_obj != null) {
rewardJson.put("rewardID", reward.reward_obj.id);
} else if (reward.reward_obj_id != null) {
rewardJson.put("rewardID", reward.reward_obj_id);
}
if (reward.reward_value != null) rewardJson.put("value", reward.reward_value);
if (reward.map != null) {
rewardJson.put("mapName", reward.map.id);
} else if (reward.map_name != null) rewardJson.put("mapName", reward.map_name);
}
}
return dialogueJson;
}
@Override
public String getProjectFilename() {
return "conversationlist_" + getProject().name + ".json";
}
@Override
public String getProjectFilename() {
return "conversationlist_"+getProject().name+".json";
}
}

View File

@@ -1,6 +1,14 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -10,231 +18,216 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class Droplist extends JSONElement {
private static final long serialVersionUID = -2903944916807382571L;
//Available from init state
//public String id = null; inherited.
private static final long serialVersionUID = -2903944916807382571L;
//Available from parsed state;
public List<DroppedItem> dropped_items = null;
//Available from linked state;
//None
public static class DroppedItem {
//Available from parsed state;
public String item_id = null;
public Double chance = null;
public Integer quantity_min = null;
public Integer quantity_max = null;
//Available from linked state;
public Item item = null;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+id;
}
//Available from init state
//public String id = null; inherited.
public static String getStaticDesc() {
return "Droplists";
}
//Available from parsed state;
public List<DroppedItem> dropped_items = null;
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<Droplist> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List droplists = (List) parser.parse(reader);
for (Object obj : droplists) {
Map droplistJson = (Map)obj;
Droplist droplist = fromJson(droplistJson);
droplist.jsonFile = jsonFile;
droplist.parent = category;
if (droplist.getDataType() == GameSource.Type.created || droplist.getDataType() == GameSource.Type.altered) {
droplist.writable = true;
}
category.add(droplist);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static Droplist fromJson(String jsonString) throws ParseException {
Map droplistJson = (Map) new JSONParser().parse(jsonString);
Droplist droplist = fromJson(droplistJson);
droplist.parse(droplistJson);
return droplist;
}
@SuppressWarnings("rawtypes")
public static Droplist fromJson(Map droplistJson) {
Droplist droplist = new Droplist();
droplist.id = (String) droplistJson.get("id");
return droplist;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map droplistJson) {
List droppedItemsJson = (List) droplistJson.get("items");
if (droppedItemsJson != null && !droppedItemsJson.isEmpty()) {
this.dropped_items = new ArrayList<DroppedItem>();
for (Object droppedItemJsonObj : droppedItemsJson) {
Map droppedItemJson = (Map)droppedItemJsonObj;
DroppedItem droppedItem = new DroppedItem();
droppedItem.item_id = (String) droppedItemJson.get("itemID");
if (droppedItemJson.get("chance") != null) droppedItem.chance = JSONElement.parseChance(droppedItemJson.get("chance").toString());
Map droppedItemQtyJson = (Map) droppedItemJson.get("quantity");
if (droppedItemQtyJson != null) {
droppedItem.quantity_min = JSONElement.getInteger((Number) droppedItemQtyJson.get("min"));
droppedItem.quantity_max = JSONElement.getInteger((Number) droppedItemQtyJson.get("max"));
}
this.dropped_items.add(droppedItem);
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking droplist "+id+". No parent project found.");
return;
}
if (dropped_items != null) {
for (DroppedItem droppedItem : dropped_items) {
if (droppedItem.item_id != null) droppedItem.item = proj.getItem(droppedItem.item_id);
if (droppedItem.item != null) droppedItem.item.addBacklink(this);
}
}
this.state = State.linked;
}
//Available from linked state;
//None
public static class DroppedItem {
//Available from parsed state;
public String item_id = null;
public String chance = null;
public Integer quantity_min = null;
public Integer quantity_max = null;
//Available from linked state;
public Item item = null;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + id;
}
public static String getStaticDesc() {
return "Droplists";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<Droplist> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List droplists = (List) parser.parse(reader);
for (Object obj : droplists) {
Map droplistJson = (Map) obj;
Droplist droplist = fromJson(droplistJson);
droplist.jsonFile = jsonFile;
droplist.parent = category;
if (droplist.getDataType() == GameSource.Type.created || droplist.getDataType() == GameSource.Type.altered) {
droplist.writable = true;
}
category.add(droplist);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static Droplist fromJson(String jsonString) throws ParseException {
Map droplistJson = (Map) new JSONParser().parse(jsonString);
Droplist droplist = fromJson(droplistJson);
droplist.parse(droplistJson);
return droplist;
}
@SuppressWarnings("rawtypes")
public static Droplist fromJson(Map droplistJson) {
Droplist droplist = new Droplist();
droplist.id = (String) droplistJson.get("id");
return droplist;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map droplistJson) {
List droppedItemsJson = (List) droplistJson.get("items");
if (droppedItemsJson != null && !droppedItemsJson.isEmpty()) {
this.dropped_items = new ArrayList<DroppedItem>();
for (Object droppedItemJsonObj : droppedItemsJson) {
Map droppedItemJson = (Map) droppedItemJsonObj;
DroppedItem droppedItem = new DroppedItem();
droppedItem.item_id = (String) droppedItemJson.get("itemID");
//if (droppedItemJson.get("chance") != null) droppedItem.chance = JSONElement.parseChance(droppedItemJson.get("chance").toString());
droppedItem.chance = (String) droppedItemJson.get("chance");
Map droppedItemQtyJson = (Map) droppedItemJson.get("quantity");
if (droppedItemQtyJson != null) {
droppedItem.quantity_min = JSONElement.getInteger((Number) droppedItemQtyJson.get("min"));
droppedItem.quantity_max = JSONElement.getInteger((Number) droppedItemQtyJson.get("max"));
}
this.dropped_items.add(droppedItem);
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking droplist " + id + ". No parent project found.");
return;
}
if (dropped_items != null) {
for (DroppedItem droppedItem : dropped_items) {
if (droppedItem.item_id != null) droppedItem.item = proj.getItem(droppedItem.item_id);
if (droppedItem.item != null) droppedItem.item.addBacklink(this);
}
}
this.state = State.linked;
}
public static Image getImage() {
return DefaultIcons.getDroplistImage();
}
@Override
public Image getIcon() {
return DefaultIcons.getDroplistIcon();
}
@Override
public GameDataElement clone() {
Droplist clone = new Droplist();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
if (this.dropped_items != null) {
clone.dropped_items = new ArrayList<Droplist.DroppedItem>();
for (DroppedItem di : this.dropped_items) {
DroppedItem diclone = new DroppedItem();
diclone.chance = di.chance;
diclone.item_id = di.item_id;
diclone.quantity_min = di.quantity_min;
diclone.quantity_max = di.quantity_max;
diclone.item = di.item;
if (diclone.item != null) {
diclone.item.addBacklink(clone);
}
clone.dropped_items.add(diclone);
}
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (dropped_items != null) {
for (DroppedItem di : dropped_items) {
if (di.item == oldOne) {
oldOne.removeBacklink(this);
di.item = (Item) newOne;
if (newOne != null) newOne.addBacklink(this);
}
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map droplistJson = new LinkedHashMap();
droplistJson.put("id", this.id);
if (this.dropped_items != null) {
List droppedItemsJson = new ArrayList();
droplistJson.put("items", droppedItemsJson);
for (DroppedItem droppedItem : this.dropped_items) {
Map droppedItemJson = new LinkedHashMap();
droppedItemsJson.add(droppedItemJson);
if (droppedItem.item != null) {
droppedItemJson.put("itemID", droppedItem.item.id);
} else if (droppedItem.item_id != null) {
droppedItemJson.put("itemID", droppedItem.item_id);
}
if (droppedItem.chance != null) droppedItemJson.put("chance", JSONElement.printJsonChance(droppedItem.chance));
if (droppedItem.quantity_min != null || droppedItem.quantity_max != null) {
Map quantityJson = new LinkedHashMap();
droppedItemJson.put("quantity", quantityJson);
if (droppedItem.quantity_min != null) quantityJson.put("min", droppedItem.quantity_min);
else quantityJson.put("min", 0);
if (droppedItem.quantity_max != null) quantityJson.put("max", droppedItem.quantity_max);
else quantityJson.put("max", 0);
}
}
}
return droplistJson;
}
public static Image getImage() {
return DefaultIcons.getDroplistImage();
}
@Override
public Image getIcon() {
return DefaultIcons.getDroplistIcon();
}
@Override
public GameDataElement clone() {
Droplist clone = new Droplist();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
if (this.dropped_items != null) {
clone.dropped_items = new ArrayList<Droplist.DroppedItem>();
for (DroppedItem di : this.dropped_items) {
DroppedItem diclone = new DroppedItem();
diclone.chance = di.chance;
diclone.item_id = di.item_id;
diclone.quantity_min = di.quantity_min;
diclone.quantity_max = di.quantity_max;
diclone.item = di.item;
if (diclone.item != null) {
diclone.item.addBacklink(clone);
}
clone.dropped_items.add(diclone);
}
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (dropped_items != null) {
for (DroppedItem di : dropped_items) {
if (di.item == oldOne) {
oldOne.removeBacklink(this);
di.item = (Item) newOne;
if (newOne != null) newOne.addBacklink(this);
}
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map droplistJson = new LinkedHashMap();
droplistJson.put("id", this.id);
if (this.dropped_items != null) {
List droppedItemsJson = new ArrayList();
droplistJson.put("items", droppedItemsJson);
for (DroppedItem droppedItem : this.dropped_items) {
Map droppedItemJson = new LinkedHashMap();
droppedItemsJson.add(droppedItemJson);
if (droppedItem.item != null) {
droppedItemJson.put("itemID", droppedItem.item.id);
} else if (droppedItem.item_id != null) {
droppedItemJson.put("itemID", droppedItem.item_id);
}
//if (droppedItem.chance != null) droppedItemJson.put("chance", JSONElement.printJsonChance(droppedItem.chance));
if (droppedItem.chance != null) droppedItemJson.put("chance", droppedItem.chance);
if (droppedItem.quantity_min != null || droppedItem.quantity_max != null) {
Map quantityJson = new LinkedHashMap();
droppedItemJson.put("quantity", quantityJson);
if (droppedItem.quantity_min != null) quantityJson.put("min", droppedItem.quantity_min);
else quantityJson.put("min", 0);
if (droppedItem.quantity_max != null) quantityJson.put("max", droppedItem.quantity_max);
else quantityJson.put("max", 0);
}
}
}
return droplistJson;
}
@Override
public String getProjectFilename() {
return "droplists_" + getProject().name + ".json";
}
@Override
public String getProjectFilename() {
return "droplists_"+getProject().name+".json";
}
}

View File

@@ -1,253 +1,321 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
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.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.*;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.List;
import org.json.simple.JSONArray;
public class GameDataCategory<E extends JSONElement> implements ProjectTreeNode {
//region Data
private final ArrayList<String> keyList = new ArrayList<>();
private final HashMap<String, E> dataMap = new HashMap<>();
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.io.JsonPrettyWriter;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
//endregion
public class GameDataCategory<E extends JSONElement> extends ArrayList<E> implements ProjectTreeNode, Serializable {
private static final long serialVersionUID = 5486008219704443733L;
public GameDataSet parent;
public String name;
public GameDataCategory(GameDataSet parent, String name) {
super();
this.parent = parent;
this.name = name;
}
public GameDataSet parent;
public String name;
@Override
public TreeNode getChildAt(int childIndex) {
return get(childIndex);
}
public GameDataCategory(GameDataSet parent, String name) {
this.parent = parent;
this.name = name;
}
@Override
public int getChildCount() {
return size();
}
//region Helpers
public E get(String key) {
return dataMap.get(key);
}
@Override
public TreeNode getParent() {
return parent;
}
public E get(int index) {
String key = keyList.get(index);
return dataMap.get(key);
}
@Override
public int getIndex(TreeNode node) {
return indexOf(node);
}
public E getIgnoreCase(String key) {
for (String k : keyList) {
if (k.equalsIgnoreCase(key)) {
return dataMap.get(k);
}
}
return null;
}
@Override
public boolean getAllowsChildren() {
return true;
}
public E put(String key, E element) {
if (!dataMap.containsKey(key)) {
keyList.add(key);
}
return dataMap.put(key, element);
}
@Override
public boolean isLeaf() {
return false;
}
public void add(E quest) {
String key = quest.id;
put(key, quest);
}
@Override
public Enumeration<E> children() {
return Collections.enumeration(this);
}
@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) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (E node : this) {
node.notifyCreated();
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+this.name;
}
public E remove(String key) {
if (dataMap.containsKey(key)) {
keyList.remove(key);
}
return dataMap.remove(key);
}
@Override
public boolean equals(Object o) {
return (o == this);
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getJsonOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return parent.getDataSet();
}
public E remove(int index) {
String key = keyList.get(index);
keyList.remove(index);
return dataMap.remove(key);
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@SuppressWarnings("rawtypes")
public void save(File jsonFile) {
if (getDataType() != GameSource.Type.created && getDataType() != GameSource.Type.altered) {
Notification.addError("Error while trying to write json file "+jsonFile.getAbsolutePath()+" : Game Source type "+getDataType().toString()+" should not be saved.");
return;
}
List<Map> dataToSave = new ArrayList<Map>();
for (E element : this) {
if (element.jsonFile.equals(jsonFile)) {
dataToSave.add(element.toJson());
}
}
if (dataToSave.isEmpty() && jsonFile.exists()) {
if (jsonFile.delete()) {
Notification.addSuccess("File "+jsonFile.getAbsolutePath()+" deleted.");
} else {
Notification.addError("Error deleting file "+jsonFile.getAbsolutePath());
}
return;
}
StringWriter writer = new JsonPrettyWriter();
try {
JSONArray.writeJSONString(dataToSave, writer);
} catch (IOException e) {
//Impossible with a StringWriter
}
String toWrite = writer.toString();
try {
FileWriter w = new FileWriter(jsonFile);
w.write(toWrite);
w.close();
for (E element : this) {
element.state = GameDataElement.State.saved;
}
Notification.addSuccess("Json file "+jsonFile.getAbsolutePath()+" saved.");
} catch (IOException e) {
Notification.addError("Error while writing json file "+jsonFile.getAbsolutePath()+" : "+e.getMessage());
e.printStackTrace();
}
}
public boolean removeGeneric(JSONElement element){
return remove((E) element);
}
public boolean remove(E element) {
String key = element.id;
int index = getProject().getNodeIndex(element);
boolean result = false;
if (dataMap.containsKey(key)) {
keyList.remove(key);
dataMap.remove(key);
result = true;
}
getProject().fireElementRemoved(element, index);
return result;
}
public List<SaveEvent> attemptSave(boolean checkImpactedCategory, String fileName) {
List<SaveEvent> events = new ArrayList<SaveEvent>();
GameDataCategory<? extends JSONElement> impactedCategory = null;
String impactedFileName = fileName;
Map<String, Integer> containedIds = new LinkedHashMap<String, Integer>();
for (JSONElement node : this) {
if (node.getDataType() == GameSource.Type.created && getProject().baseContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
if (getProject().alteredContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
events.add(new SaveEvent(SaveEvent.Type.moveToAltered, node, true, "Element ID matches one already present in the altered game content. Change this ID before saving."));
} else {
events.add(new SaveEvent(SaveEvent.Type.moveToAltered, node));
impactedFileName = getProject().baseContent.gameData.getGameDataElement(node.getClass(), node.id).jsonFile.getName();
impactedCategory = getProject().alteredContent.gameData.getCategory(node.getClass());
}
} else if (this.getDataType() == GameSource.Type.altered && getProject().baseContent.gameData.getGameDataElement(node.getClass(), node.id) == null) {
if (getProject().createdContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
events.add(new SaveEvent(SaveEvent.Type.moveToCreated, node, true, "Element ID matches one already present in the created game content. Change this ID before saving."));
} else {
events.add(new SaveEvent(SaveEvent.Type.moveToCreated, node));
impactedCategory = getProject().createdContent.gameData.getCategory(node.getClass());
impactedFileName = node.getProjectFilename();
}
} else if (node.needsSaving()) {
events.add(new SaveEvent(SaveEvent.Type.alsoSave, node));
}
if (containedIds.containsKey(node.id)) {
containedIds.put(node.id, containedIds.get(node.id) + 1);
} else {
containedIds.put(node.id, 1);
}
}
for (String key : containedIds.keySet()) {
if (containedIds.get(key) > 1) {
E node = null;
for (E n : this) {
if (key.equals(n.id)) {
node = n;
break;
}
}
events.add(new SaveEvent(SaveEvent.Type.alsoSave, node, true, "There are "+containedIds.get(node.id)+" elements with this ID in this category. Change the conflicting IDs before saving."));
}
}
if (checkImpactedCategory && impactedCategory != null) {
events.addAll(impactedCategory.attemptSave(false, impactedFileName));
}
return events;
}
public int size() {
return dataMap.size();
}
public int indexOf(String key) {
return keyList.indexOf(key);
}
public int indexOf(E element) {
String key = element.id;
return keyList.indexOf(key);
}
public ArrayList<E> toList() {
ArrayList<E> list = new ArrayList<>();
for (String key : keyList) {
list.add(dataMap.get(key));
}
return list;
}
//endregion
//region copied implementation of ProjectTreeNode
@Override
public TreeNode getChildAt(int childIndex) {
return get(childIndex);
}
@Override
public int getChildCount() {
return size();
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public int getIndex(TreeNode node) {
return indexOf((E) node);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public Enumeration<E> children() {
return Collections.enumeration(toList());
}
@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) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (E node : dataMap.values()) {
node.notifyCreated();
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + this.name;
}
@Override
public boolean equals(Object o) {
return (o == this);
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getJsonOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return parent.getDataSet();
}
@Override
public GameSource.Type getDataType() {
return parent.getDataType();
}
@Override
public boolean isEmpty() {
return dataMap.isEmpty();
}
@SuppressWarnings("rawtypes")
public void save(File jsonFile) {
if (getDataType() != GameSource.Type.created && getDataType() != GameSource.Type.altered) {
Notification.addError("Error while trying to write json file " + jsonFile.getAbsolutePath() + " : Game Source type " + getDataType().toString() + " should not be saved.");
return;
}
List<Map> dataToSave = new ArrayList<Map>();
for (E element : dataMap.values()) {
if (element.jsonFile.equals(jsonFile)) {
dataToSave.add(element.toJson());
}
}
if (dataToSave.isEmpty() && jsonFile.exists()) {
if (jsonFile.delete()) {
Notification.addSuccess("File " + jsonFile.getAbsolutePath() + " deleted.");
} else {
Notification.addError("Error deleting file " + jsonFile.getAbsolutePath());
}
return;
}
String toWrite = FileUtils.toJsonString(dataToSave);
if(FileUtils.writeStringToFile(toWrite, jsonFile, "JSON file '"+jsonFile.getAbsolutePath()+"'")){
for (E element : dataMap.values()) {
element.state = GameDataElement.State.saved;
}
}
}
public List<SaveEvent> attemptSave(boolean checkImpactedCategory, String fileName) {
List<SaveEvent> events = new ArrayList<SaveEvent>();
GameDataCategory<? extends JSONElement> impactedCategory = null;
String impactedFileName = fileName;
Map<String, Integer> containedIds = new LinkedHashMap<String, Integer>();
ArrayList<E> list = toList();
for (JSONElement node : list) {
if (node.getDataType() == GameSource.Type.created && getProject().baseContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
if (getProject().alteredContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
events.add(new SaveEvent(SaveEvent.Type.moveToAltered, node, true, "Element ID matches one already present in the altered game content. Change this ID before saving."));
} else {
events.add(new SaveEvent(SaveEvent.Type.moveToAltered, node));
impactedFileName = getProject().baseContent.gameData.getGameDataElement(node.getClass(), node.id).jsonFile.getName();
impactedCategory = getProject().alteredContent.gameData.getCategory(node.getClass());
}
} else if (this.getDataType() == GameSource.Type.altered && getProject().baseContent.gameData.getGameDataElement(node.getClass(), node.id) == null) {
if (getProject().createdContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
events.add(new SaveEvent(SaveEvent.Type.moveToCreated, node, true, "Element ID matches one already present in the created game content. Change this ID before saving."));
} else {
events.add(new SaveEvent(SaveEvent.Type.moveToCreated, node));
impactedCategory = getProject().createdContent.gameData.getCategory(node.getClass());
impactedFileName = node.getProjectFilename();
}
} else if (node.needsSaving()) {
events.add(new SaveEvent(SaveEvent.Type.alsoSave, node));
}
if (containedIds.containsKey(node.id)) {
containedIds.put(node.id, containedIds.get(node.id) + 1);
} else {
containedIds.put(node.id, 1);
}
}
for (String key : containedIds.keySet()) {
if (containedIds.get(key) > 1) {
E node = null;
for (E n : list) {
if (key.equals(n.id)) {
node = n;
break;
}
}
events.add(new SaveEvent(SaveEvent.Type.alsoSave, node, true,
"There are " + containedIds.get(node.id) + " elements with this ID in this category. Change the conflicting IDs before saving."));
}
}
if (checkImpactedCategory && impactedCategory != null) {
events.addAll(impactedCategory.attemptSave(false, impactedFileName));
}
return events;
}
@Override
public boolean needsSaving() {
for (E node : dataMap.values()) {
if (node.needsSaving()) return true;
}
return false;
}
//endregion
public boolean remove(E o) {
int index = getProject().getNodeIndex(o);
boolean result = super.remove(o);
getProject().fireElementRemoved(o, index);
return result;
}
@Override
public boolean needsSaving() {
for (E node : this) {
if (node.needsSaving()) return true;
}
return false;
}
}

View File

@@ -1,14 +1,5 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
@@ -18,456 +9,439 @@ import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SavedSlotCollection;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class GameDataSet implements ProjectTreeNode, Serializable {
private static final long serialVersionUID = -8558067213826970968L;
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res"+File.separator+"raw"+File.separator;
public static final String DEFAULT_REL_PATH_IN_PROJECT = "json"+File.separator;
public static final String GAME_AC_ARRAY_NAME = "loadresource_actorconditions";
public static final String GAME_DIALOGUES_ARRAY_NAME = "loadresource_conversationlists";
public static final String GAME_DROPLISTS_ARRAY_NAME = "loadresource_droplists";
public static final String GAME_ITEMS_ARRAY_NAME = "loadresource_items";
public static final String GAME_ITEMCAT_ARRAY_NAME = "loadresource_itemcategories";
public static final String GAME_NPC_ARRAY_NAME = "loadresource_monsters";
public static final String GAME_QUESTS_ARRAY_NAME = "loadresource_quests";
public static final String DEBUG_SUFFIX = "_debug";
public static final String RESOURCE_PREFIX = "@raw/";
public static final String FILENAME_SUFFIX = ".json";
public File baseFolder;
public GameDataCategory<ActorCondition> actorConditions;
public GameDataCategory<Dialogue> dialogues;
public GameDataCategory<Droplist> droplists;
public GameDataCategory<Item> items;
public GameDataCategory<ItemCategory> itemCategories;
public GameDataCategory<NPC> npcs;
public GameDataCategory<Quest> quests;
public GameSource parent;
public SavedSlotCollection v;
public GameDataSet(GameSource source) {
this.parent = source;
v = new SavedSlotCollection();
private static final long serialVersionUID = -8558067213826970968L;
if (parent.type.equals(GameSource.Type.altered) || parent.type.equals(GameSource.Type.created)) {
this.baseFolder = new File(parent.baseFolder, GameDataSet.DEFAULT_REL_PATH_IN_PROJECT);
if (!baseFolder.exists()) this.baseFolder.mkdirs();
} else if (parent.type.equals(GameSource.Type.source)) {
this.baseFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
}
actorConditions = new GameDataCategory<ActorCondition>(this, ActorCondition.getStaticDesc());
dialogues = new GameDataCategory<Dialogue>(this, Dialogue.getStaticDesc());
droplists = new GameDataCategory<Droplist>(this, Droplist.getStaticDesc());
items = new GameDataCategory<Item>(this, Item.getStaticDesc());
itemCategories = new GameDataCategory<ItemCategory>(this, ItemCategory.getStaticDesc());
npcs = new GameDataCategory<NPC>(this, NPC.getStaticDesc());
quests = new GameDataCategory<Quest>(this, Quest.getStaticDesc());
v.add(actorConditions);
v.add(dialogues);
v.add(droplists);
v.add(items);
v.add(itemCategories);
v.add(npcs);
v.add(quests);
//Start parsing to populate categories' content.
if (parent.type == GameSource.Type.source && (parent.parent.sourceSetToUse == ResourceSet.debugData || parent.parent.sourceSetToUse == ResourceSet.gameData)) {
String suffix = (parent.parent.sourceSetToUse == ResourceSet.debugData) ? DEBUG_SUFFIX : "";
if (parent.referencedSourceFiles.get(GAME_AC_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_AC_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
ActorCondition.fromJson(f, actorConditions);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_DIALOGUES_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_DIALOGUES_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Dialogue.fromJson(f, dialogues);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_DROPLISTS_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_DROPLISTS_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Droplist.fromJson(f, droplists);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_ITEMS_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_ITEMS_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Item.fromJson(f, items);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_ITEMCAT_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_ITEMCAT_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
ItemCategory.fromJson(f, itemCategories);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_NPC_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_NPC_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
NPC.fromJson(f, npcs);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_QUESTS_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_QUESTS_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Quest.fromJson(f, quests);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
} else if (parent.type != GameSource.Type.referenced) {
for (File f : baseFolder.listFiles()) {
if (f.getName().startsWith("actorconditions_")) {
ActorCondition.fromJson(f, actorConditions);
} else if (f.getName().startsWith("conversationlist_")) {
Dialogue.fromJson(f, dialogues);
} else if (f.getName().startsWith("droplists_")) {
Droplist.fromJson(f, droplists);
} else if (f.getName().startsWith("itemlist_")) {
Item.fromJson(f, items);
} else if (f.getName().startsWith("itemcategories_")) {
ItemCategory.fromJson(f, itemCategories);
} else if (f.getName().startsWith("monsterlist_")) {
NPC.fromJson(f, npcs);
} else if (f.getName().startsWith("questlist")) {
Quest.fromJson(f, quests);
}
}
}
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return v.getNonEmptyElementAt(arg0);
}
@Override
public int getChildCount() {
return v.getNonEmptySize();
}
@Override
public int getIndex(TreeNode arg0) {
return v.getNonEmptyIndexOf((ProjectTreeNode) arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.v.getNonEmptySize() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
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() ? "*" : "")+"JSON data";
}
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res" + File.separator + "raw" + File.separator;
public static final String DEFAULT_REL_PATH_IN_PROJECT = "json" + File.separator;
public void refreshTransients() {
}
public ActorCondition getActorCondition(String id) {
if (actorConditions == null) return null;
for (ActorCondition gde : actorConditions) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
public Dialogue getDialogue(String id) {
if (dialogues == null) return null;
for (Dialogue gde : dialogues) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
public Droplist getDroplist(String id) {
if (droplists == null) return null;
for (Droplist gde : droplists) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
public Item getItem(String id) {
if (items == null) return null;
for (Item gde : items) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
public ItemCategory getItemCategory(String id) {
if (itemCategories == null) return null;
for (ItemCategory gde : itemCategories) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
public NPC getNPC(String id) {
if (npcs == null) return null;
for (NPC gde : npcs) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
public NPC getNPCIgnoreCase(String id) {
if (npcs == null) return null;
for (NPC gde : npcs) {
if (id.equalsIgnoreCase(gde.id)){
return gde;
}
}
return null;
}
public Quest getQuest(String id) {
if (quests == null) return null;
for (Quest gde : quests) {
if (id.equals(gde.id)){
return gde;
}
}
return null;
}
@Override
public Project getProject() {
return parent.getProject();
}
public static final String GAME_AC_ARRAY_NAME = "loadresource_actorconditions";
public static final String GAME_DIALOGUES_ARRAY_NAME = "loadresource_conversationlists";
public static final String GAME_DROPLISTS_ARRAY_NAME = "loadresource_droplists";
public static final String GAME_ITEMS_ARRAY_NAME = "loadresource_items";
public static final String GAME_ITEMCAT_ARRAY_NAME = "loadresource_itemcategories";
public static final String GAME_NPC_ARRAY_NAME = "loadresource_monsters";
public static final String GAME_QUESTS_ARRAY_NAME = "loadresource_quests";
public static final String DEBUG_SUFFIX = "_debug";
public static final String RESOURCE_PREFIX = "@raw/";
public static final String FILENAME_SUFFIX = ".json";
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getJsonOpenIcon();
}
public File baseFolder;
public void addElement(JSONElement node) {
ProjectTreeNode higherEmptyParent = this;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode)higherEmptyParent.getParent()).isEmpty()) higherEmptyParent = (ProjectTreeNode)higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
if (node instanceof ActorCondition) {
if (actorConditions.isEmpty() && higherEmptyParent == null) higherEmptyParent = actorConditions;
actorConditions.add((ActorCondition) node);
node.parent = actorConditions;
} else if (node instanceof Dialogue) {
if (dialogues.isEmpty() && higherEmptyParent == null) higherEmptyParent = dialogues;
dialogues.add((Dialogue) node);
node.parent = dialogues;
} else if (node instanceof Droplist) {
if (droplists.isEmpty() && higherEmptyParent == null) higherEmptyParent = droplists;
droplists.add((Droplist) node);
node.parent = droplists;
} else if (node instanceof Item) {
if (items.isEmpty() && higherEmptyParent == null) higherEmptyParent = items;
items.add((Item) node);
node.parent = items;
} else if (node instanceof ItemCategory) {
if (itemCategories.isEmpty() && higherEmptyParent == null) higherEmptyParent = itemCategories;
itemCategories.add((ItemCategory) node);
node.parent = itemCategories;
} else if (node instanceof NPC) {
if (npcs.isEmpty() && higherEmptyParent == null) higherEmptyParent = npcs;
npcs.add((NPC) node);
node.parent = npcs;
} else if (node instanceof Quest) {
if (quests.isEmpty() && higherEmptyParent == null) higherEmptyParent = quests;
quests.add((Quest) node);
node.parent = quests;
} else {
Notification.addError("Cannot add "+node.getDesc()+". Unknown data type.");
return;
}
if (node.jsonFile != null && parent.type == GameSource.Type.altered) {
//Altered node.
node.jsonFile = new File(this.baseFolder, node.jsonFile.getName());
} else {
//Created node.
node.jsonFile = new File(this.baseFolder, node.getProjectFilename());
}
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
public GameDataCategory<ActorCondition> actorConditions;
public GameDataCategory<Dialogue> dialogues;
public GameDataCategory<Droplist> droplists;
public GameDataCategory<Item> items;
public GameDataCategory<ItemCategory> itemCategories;
public GameDataCategory<NPC> npcs;
public GameDataCategory<Quest> quests;
@Override
public GameDataSet getDataSet() {
return this;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@Override
public boolean isEmpty() {
return v.isEmpty();
}
public GameSource parent;
public SavedSlotCollection v;
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 GameDataSet(GameSource source) {
public GameDataCategory<? extends JSONElement> getCategory(Class<? extends JSONElement> gdeClass) {
if (gdeClass == ActorCondition.class) {
return actorConditions;
}
if (gdeClass == Dialogue.class) {
return dialogues;
}
if (gdeClass == Droplist.class) {
return droplists;
}
if (gdeClass == ItemCategory.class) {
return itemCategories;
}
if (gdeClass == Item.class) {
return items;
}
if (gdeClass == NPC.class) {
return npcs;
}
if (gdeClass == Quest.class) {
return quests;
}
return null;
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
if (node.needsSaving()) return true;
}
return false;
}
this.parent = source;
v = new SavedSlotCollection();
if (parent.type.equals(GameSource.Type.altered) || parent.type.equals(GameSource.Type.created)) {
this.baseFolder = new File(parent.baseFolder, GameDataSet.DEFAULT_REL_PATH_IN_PROJECT);
if (!baseFolder.exists()) this.baseFolder.mkdirs();
} else if (parent.type.equals(GameSource.Type.source)) {
this.baseFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
}
actorConditions = new GameDataCategory<ActorCondition>(this, ActorCondition.getStaticDesc());
dialogues = new GameDataCategory<Dialogue>(this, Dialogue.getStaticDesc());
droplists = new GameDataCategory<Droplist>(this, Droplist.getStaticDesc());
items = new GameDataCategory<Item>(this, Item.getStaticDesc());
itemCategories = new GameDataCategory<ItemCategory>(this, ItemCategory.getStaticDesc());
npcs = new GameDataCategory<NPC>(this, NPC.getStaticDesc());
quests = new GameDataCategory<>(this, Quest.getStaticDesc());
v.add(actorConditions);
v.add(dialogues);
v.add(droplists);
v.add(items);
v.add(itemCategories);
v.add(npcs);
v.add(quests);
//Start parsing to populate categories' content.
if (parent.type == GameSource.Type.source && (parent.parent.sourceSetToUse == ResourceSet.debugData || parent.parent.sourceSetToUse == ResourceSet.gameData)) {
String suffix = (parent.parent.sourceSetToUse == ResourceSet.debugData) ? DEBUG_SUFFIX : "";
if (parent.referencedSourceFiles.get(GAME_AC_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_AC_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
ActorCondition.fromJson(f, actorConditions);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_DIALOGUES_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_DIALOGUES_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
Dialogue.fromJson(f, dialogues);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_DROPLISTS_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_DROPLISTS_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
Droplist.fromJson(f, droplists);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_ITEMS_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_ITEMS_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
Item.fromJson(f, items);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_ITEMCAT_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_ITEMCAT_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
ItemCategory.fromJson(f, itemCategories);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_NPC_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_NPC_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
NPC.fromJson(f, npcs);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_QUESTS_ARRAY_NAME + suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_QUESTS_ARRAY_NAME + suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
Quest.fromJson(f, quests);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
} else if (parent.type != GameSource.Type.referenced) {
for (File f : baseFolder.listFiles()) {
if (f.getName().startsWith("actorconditions_")) {
ActorCondition.fromJson(f, actorConditions);
} else if (f.getName().startsWith("conversationlist_")) {
Dialogue.fromJson(f, dialogues);
} else if (f.getName().startsWith("droplists_")) {
Droplist.fromJson(f, droplists);
} else if (f.getName().startsWith("itemlist_")) {
Item.fromJson(f, items);
} else if (f.getName().startsWith("itemcategories_")) {
ItemCategory.fromJson(f, itemCategories);
} else if (f.getName().startsWith("monsterlist_")) {
NPC.fromJson(f, npcs);
} else if (f.getName().startsWith("questlist")) {
Quest.fromJson(f, quests);
}
}
}
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return v.getNonEmptyElementAt(arg0);
}
@Override
public int getChildCount() {
return v.getNonEmptySize();
}
@Override
public int getIndex(TreeNode arg0) {
return v.getNonEmptyIndexOf((ProjectTreeNode) arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.v.getNonEmptySize() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
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() ? "*" : "") + "JSON data";
}
public void refreshTransients() {
}
public ActorCondition getActorCondition(String id) {
if (actorConditions == null) return null;
return actorConditions.get(id);
}
public Dialogue getDialogue(String id) {
if (dialogues == null) return null;
return dialogues.get(id);
}
public Droplist getDroplist(String id) {
if (droplists == null) return null;
return droplists.get(id);
}
public Item getItem(String id) {
if (items == null) return null;
return items.get(id);
}
public ItemCategory getItemCategory(String id) {
if (itemCategories == null) return null;
return itemCategories.get(id);
}
public NPC getNPC(String id) {
if (npcs == null) return null;
return npcs.get(id);
}
public NPC getNPCIgnoreCase(String id) {
if (npcs == null) return null;
return npcs.getIgnoreCase(id);
}
public Quest getQuest(String id) {
if (quests == null) return null;
return quests.get(id);
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getJsonClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getJsonOpenIcon();
}
public void addElement(JSONElement node) {
ProjectTreeNode higherEmptyParent = this;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode) higherEmptyParent.getParent()).isEmpty())
higherEmptyParent = (ProjectTreeNode) higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
if (node instanceof ActorCondition) {
if (actorConditions.isEmpty() && higherEmptyParent == null) higherEmptyParent = actorConditions;
actorConditions.add((ActorCondition) node);
node.parent = actorConditions;
} else if (node instanceof Dialogue) {
if (dialogues.isEmpty() && higherEmptyParent == null) higherEmptyParent = dialogues;
dialogues.add((Dialogue) node);
node.parent = dialogues;
} else if (node instanceof Droplist) {
if (droplists.isEmpty() && higherEmptyParent == null) higherEmptyParent = droplists;
droplists.add((Droplist) node);
node.parent = droplists;
} else if (node instanceof Item) {
if (items.isEmpty() && higherEmptyParent == null) higherEmptyParent = items;
items.add((Item) node);
node.parent = items;
} else if (node instanceof ItemCategory) {
if (itemCategories.isEmpty() && higherEmptyParent == null) higherEmptyParent = itemCategories;
itemCategories.add((ItemCategory) node);
node.parent = itemCategories;
} else if (node instanceof NPC) {
if (npcs.isEmpty() && higherEmptyParent == null) higherEmptyParent = npcs;
npcs.add((NPC) node);
node.parent = npcs;
} else if (node instanceof Quest) {
if (quests.isEmpty() && higherEmptyParent == null) higherEmptyParent = quests;
quests.add((Quest) node);
node.parent = quests;
} else {
Notification.addError("Cannot add " + node.getDesc() + ". Unknown data type.");
return;
}
if (node.jsonFile != null && parent.type == GameSource.Type.altered) {
//Altered node.
node.jsonFile = new File(this.baseFolder, node.jsonFile.getName());
} else {
//Created node.
node.jsonFile = new File(this.baseFolder, node.getProjectFilename());
}
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
@Override
public GameDataSet getDataSet() {
return this;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@Override
public boolean isEmpty() {
return v.isEmpty();
}
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 GameDataCategory<? extends JSONElement> getCategory(Class<? extends JSONElement> gdeClass) {
if (gdeClass == ActorCondition.class) {
return actorConditions;
}
if (gdeClass == Dialogue.class) {
return dialogues;
}
if (gdeClass == Droplist.class) {
return droplists;
}
if (gdeClass == ItemCategory.class) {
return itemCategories;
}
if (gdeClass == Item.class) {
return items;
}
if (gdeClass == NPC.class) {
return npcs;
}
if (gdeClass == Quest.class) {
return quests;
}
return null;
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
if (node.needsSaving()) return true;
}
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,13 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import javax.imageio.ImageIO;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -9,321 +16,307 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
public class ItemCategory extends JSONElement {
private static final long serialVersionUID = -348864002519568300L;
public static final String ICON_NO_SLOT_RES = "/com/gpl/rpg/atcontentstudio/img/equip_square.png";
public static final String ICON_BODY_RES = "/com/gpl/rpg/atcontentstudio/img/equip_body.png";
public static final String ICON_FEET_RES = "/com/gpl/rpg/atcontentstudio/img/equip_feet.png";
public static final String ICON_HAND_RES = "/com/gpl/rpg/atcontentstudio/img/equip_hand.png";
public static final String ICON_HEAD_RES = "/com/gpl/rpg/atcontentstudio/img/equip_head.png";
public static final String ICON_NECK_RES = "/com/gpl/rpg/atcontentstudio/img/equip_neck.png";
public static final String ICON_RING_RES = "/com/gpl/rpg/atcontentstudio/img/equip_ring.png";
public static final String ICON_SHIELD_RES = "/com/gpl/rpg/atcontentstudio/img/equip_shield.png";
public static final String ICON_WEAPON_RES = "/com/gpl/rpg/atcontentstudio/img/equip_weapon.png";
private static final long serialVersionUID = -348864002519568300L;
public static Image no_slot_image = null;
public static Image no_slot_icon = null;
public static final String ICON_NO_SLOT_RES = "/com/gpl/rpg/atcontentstudio/img/equip_square.png";
public static final String ICON_BODY_RES = "/com/gpl/rpg/atcontentstudio/img/equip_body.png";
public static final String ICON_FEET_RES = "/com/gpl/rpg/atcontentstudio/img/equip_feet.png";
public static final String ICON_HAND_RES = "/com/gpl/rpg/atcontentstudio/img/equip_hand.png";
public static final String ICON_HEAD_RES = "/com/gpl/rpg/atcontentstudio/img/equip_head.png";
public static final String ICON_NECK_RES = "/com/gpl/rpg/atcontentstudio/img/equip_neck.png";
public static final String ICON_RING_RES = "/com/gpl/rpg/atcontentstudio/img/equip_ring.png";
public static final String ICON_SHIELD_RES = "/com/gpl/rpg/atcontentstudio/img/equip_shield.png";
public static final String ICON_WEAPON_RES = "/com/gpl/rpg/atcontentstudio/img/equip_weapon.png";
public static Image body_image = null;
public static Image body_icon = null;
public static Image no_slot_image = null;
public static Image no_slot_icon = null;
public static Image feet_image = null;
public static Image feet_icon = null;
public static Image body_image = null;
public static Image body_icon = null;
public static Image hand_image = null;
public static Image hand_icon = null;
public static Image feet_image = null;
public static Image feet_icon = null;
public static Image head_image = null;
public static Image head_icon = null;
public static Image hand_image = null;
public static Image hand_icon = null;
public static Image neck_image = null;
public static Image neck_icon = null;
public static Image head_image = null;
public static Image head_icon = null;
public static Image ring_image = null;
public static Image ring_icon = null;
public static Image neck_image = null;
public static Image neck_icon = null;
public static Image shield_image = null;
public static Image shield_icon = null;
public static Image ring_image = null;
public static Image ring_icon = null;
public static Image weapon_image = null;
public static Image weapon_icon = null;
//Available from init state
//public String id = null; inherited.
public String name = null;
public InventorySlot slot = null;
//Available from parsed state
public ActionType action_type = null;
public Size size = null;
//Available from linked state
//None
public static enum ActionType {
none,
use,
equip
}
public static enum Size {
none,
light,
std,
large
}
public static enum InventorySlot {
weapon,
shield,
head,
body,
hand,
feet,
neck,
leftring,
rightring
}
public static Image shield_image = null;
public static Image shield_icon = null;
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+name+" ("+id+")";
}
public static Image weapon_image = null;
public static Image weapon_icon = null;
public static String getStaticDesc() {
return "Item categories";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<ItemCategory> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List itemCategories = (List) parser.parse(reader);
for (Object obj : itemCategories) {
Map itemCatJson = (Map)obj;
ItemCategory itemCat = fromJson(itemCatJson);
itemCat.jsonFile = jsonFile;
itemCat.parent = category;
if (itemCat.getDataType() == GameSource.Type.created || itemCat.getDataType() == GameSource.Type.altered) {
itemCat.writable = true;
}
category.add(itemCat);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static ItemCategory fromJson(String jsonString) throws ParseException {
Map itemCatJson = (Map) new JSONParser().parse(jsonString);
ItemCategory item = fromJson(itemCatJson);
item.parse(itemCatJson);
return item;
}
@SuppressWarnings("rawtypes")
public static ItemCategory fromJson(Map itemCatJson) {
ItemCategory itemCat = new ItemCategory();
itemCat.id = (String) itemCatJson.get("id");
itemCat.name = (String) itemCatJson.get("name");
if (itemCatJson.get("inventorySlot") != null) itemCat.slot = InventorySlot.valueOf((String) itemCatJson.get("inventorySlot"));
return itemCat;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map itemCatJson) {
if (itemCatJson.get("actionType") != null) action_type = ActionType.valueOf((String) itemCatJson.get("actionType"));
if (itemCatJson.get("size") != null) size = Size.valueOf((String) itemCatJson.get("size"));
this.state = State.parsed;
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
//Nothing to link to :D
this.state = State.linked;
}
@Override
public Image getIcon() {
return getIcon(this.slot);
}
public Image getImage() {
return getImage(this.slot);
}
public static Image getImage(InventorySlot slot) {
if (slot == null) {
return getImage(ICON_NO_SLOT_RES, no_slot_image, "no_slot_image");
}
switch (slot) {
case body:
return getImage(ICON_BODY_RES, body_image, "body_image");
case feet:
return getImage(ICON_FEET_RES, feet_image, "feet_image");
case hand:
return getImage(ICON_HAND_RES, hand_image, "hand_image");
case head:
return getImage(ICON_HEAD_RES, head_image, "head_image");
case leftring:
case rightring:
return getImage(ICON_RING_RES, ring_image, "ring_image");
case neck:
return getImage(ICON_NECK_RES, neck_image, "neck_image");
case shield:
return getImage(ICON_SHIELD_RES, shield_image, "shield_image");
case weapon:
return getImage(ICON_WEAPON_RES, weapon_image, "weapon_image");
default:
return getImage(ICON_NO_SLOT_RES, no_slot_image, "no_slot_image");
}
}
public static Image getIcon(InventorySlot slot) {
if (slot == null) {
return getIcon(ICON_NO_SLOT_RES, no_slot_image, no_slot_icon, "no_slot_image", "no_slot_icon");
}
switch (slot) {
case body:
return getIcon(ICON_BODY_RES, body_image, body_icon, "body_image", "body_icon");
case feet:
return getIcon(ICON_FEET_RES, feet_image, feet_icon, "feet_image", "feet_icon");
case hand:
return getIcon(ICON_HAND_RES, hand_image, hand_icon, "hand_image", "hand_icon");
case head:
return getIcon(ICON_HEAD_RES, head_image, head_icon, "head_image", "head_icon");
case leftring:
case rightring:
return getIcon(ICON_RING_RES, ring_image, ring_icon, "ring_image", "ring_icon");
case neck:
return getIcon(ICON_NECK_RES, neck_image, neck_icon, "neck_image", "neck_icon");
case shield:
return getIcon(ICON_SHIELD_RES, shield_image, shield_icon, "shield_image", "shield_icon");
case weapon:
return getIcon(ICON_WEAPON_RES, weapon_image, weapon_icon, "weapon_image", "weapon_icon");
default:
return getIcon(ICON_NO_SLOT_RES, no_slot_image, no_slot_icon, "no_slot_image", "no_slot_icon");
}
}
public static Image getImage(String res, Image img, String fieldName) {
if (img == null) {
try {
img = ImageIO.read(ItemCategory.class.getResourceAsStream(res));
ItemCategory.class.getField(fieldName).set(null, img);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Failed to load item category icon "+res);
e.printStackTrace();
}
}
return img;
}
public static Image getIcon(String res, Image img, Image icon, String imgFieldName, String iconFieldName) {
if (icon == null) {
icon = getImage(res, img, imgFieldName).getScaledInstance(16, 16, Image.SCALE_SMOOTH);
try {
ItemCategory.class.getField(iconFieldName).set(null, icon);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
return icon;
}
@Override
public GameDataElement clone() {
ItemCategory clone = new ItemCategory();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.name = this.name;
clone.size = this.size;
clone.slot = this.slot;
clone.action_type = this.action_type;
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
// Nothing to link to.
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map itemCatJson = new LinkedHashMap();
itemCatJson.put("id", this.id);
if (this.name != null) itemCatJson.put("name", this.name);
if (this.action_type != null) itemCatJson.put("actionType", this.action_type.toString());
if (this.size != null) itemCatJson.put("size", this.size.toString());
if (this.slot != null) itemCatJson.put("inventorySlot", this.slot.toString());
return itemCatJson;
}
//Available from init state
//public String id = null; inherited.
public String name = null;
public InventorySlot slot = null;
//Available from parsed state
public ActionType action_type = null;
public Size size = null;
//Available from linked state
//None
public static enum ActionType {
none,
use,
equip
}
public static enum Size {
none,
light,
std,
large
}
public static enum InventorySlot {
weapon,
shield,
head,
body,
hand,
feet,
neck,
leftring,
rightring
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + name + " (" + id + ")";
}
public static String getStaticDesc() {
return "Item categories";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<ItemCategory> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List itemCategories = (List) parser.parse(reader);
for (Object obj : itemCategories) {
Map itemCatJson = (Map) obj;
ItemCategory itemCat = fromJson(itemCatJson);
itemCat.jsonFile = jsonFile;
itemCat.parent = category;
if (itemCat.getDataType() == GameSource.Type.created || itemCat.getDataType() == GameSource.Type.altered) {
itemCat.writable = true;
}
category.add(itemCat);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static ItemCategory fromJson(String jsonString) throws ParseException {
Map itemCatJson = (Map) new JSONParser().parse(jsonString);
ItemCategory item = fromJson(itemCatJson);
item.parse(itemCatJson);
return item;
}
@SuppressWarnings("rawtypes")
public static ItemCategory fromJson(Map itemCatJson) {
ItemCategory itemCat = new ItemCategory();
itemCat.id = (String) itemCatJson.get("id");
itemCat.name = (String) itemCatJson.get("name");
if (itemCatJson.get("inventorySlot") != null)
itemCat.slot = InventorySlot.valueOf((String) itemCatJson.get("inventorySlot"));
return itemCat;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map itemCatJson) {
if (itemCatJson.get("actionType") != null)
action_type = ActionType.valueOf((String) itemCatJson.get("actionType"));
if (itemCatJson.get("size") != null) size = Size.valueOf((String) itemCatJson.get("size"));
this.state = State.parsed;
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
//Nothing to link to :D
this.state = State.linked;
}
@Override
public Image getIcon() {
return getIcon(this.slot);
}
public Image getImage() {
return getImage(this.slot);
}
public static Image getImage(InventorySlot slot) {
if (slot == null) {
return getImage(ICON_NO_SLOT_RES, no_slot_image, "no_slot_image");
}
switch (slot) {
case body:
return getImage(ICON_BODY_RES, body_image, "body_image");
case feet:
return getImage(ICON_FEET_RES, feet_image, "feet_image");
case hand:
return getImage(ICON_HAND_RES, hand_image, "hand_image");
case head:
return getImage(ICON_HEAD_RES, head_image, "head_image");
case leftring:
case rightring:
return getImage(ICON_RING_RES, ring_image, "ring_image");
case neck:
return getImage(ICON_NECK_RES, neck_image, "neck_image");
case shield:
return getImage(ICON_SHIELD_RES, shield_image, "shield_image");
case weapon:
return getImage(ICON_WEAPON_RES, weapon_image, "weapon_image");
default:
return getImage(ICON_NO_SLOT_RES, no_slot_image, "no_slot_image");
}
}
public static Image getIcon(InventorySlot slot) {
if (slot == null) {
return getIcon(ICON_NO_SLOT_RES, no_slot_image, no_slot_icon, "no_slot_image", "no_slot_icon");
}
switch (slot) {
case body:
return getIcon(ICON_BODY_RES, body_image, body_icon, "body_image", "body_icon");
case feet:
return getIcon(ICON_FEET_RES, feet_image, feet_icon, "feet_image", "feet_icon");
case hand:
return getIcon(ICON_HAND_RES, hand_image, hand_icon, "hand_image", "hand_icon");
case head:
return getIcon(ICON_HEAD_RES, head_image, head_icon, "head_image", "head_icon");
case leftring:
case rightring:
return getIcon(ICON_RING_RES, ring_image, ring_icon, "ring_image", "ring_icon");
case neck:
return getIcon(ICON_NECK_RES, neck_image, neck_icon, "neck_image", "neck_icon");
case shield:
return getIcon(ICON_SHIELD_RES, shield_image, shield_icon, "shield_image", "shield_icon");
case weapon:
return getIcon(ICON_WEAPON_RES, weapon_image, weapon_icon, "weapon_image", "weapon_icon");
default:
return getIcon(ICON_NO_SLOT_RES, no_slot_image, no_slot_icon, "no_slot_image", "no_slot_icon");
}
}
public static Image getImage(String res, Image img, String fieldName) {
if (img == null) {
try {
img = ImageIO.read(ItemCategory.class.getResourceAsStream(res));
ItemCategory.class.getField(fieldName).set(null, img);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Failed to load item category icon " + res);
e.printStackTrace();
}
}
return img;
}
public static Image getIcon(String res, Image img, Image icon, String imgFieldName, String iconFieldName) {
if (icon == null) {
icon = getImage(res, img, imgFieldName).getScaledInstance(16, 16, Image.SCALE_SMOOTH);
try {
ItemCategory.class.getField(iconFieldName).set(null, icon);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
return icon;
}
@Override
public GameDataElement clone() {
ItemCategory clone = new ItemCategory();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.name = this.name;
clone.size = this.size;
clone.slot = this.slot;
clone.action_type = this.action_type;
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
// Nothing to link to.
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map itemCatJson = new LinkedHashMap();
itemCatJson.put("id", this.id);
if (this.name != null) itemCatJson.put("name", this.name);
if (this.action_type != null) itemCatJson.put("actionType", this.action_type.toString());
if (this.size != null) itemCatJson.put("size", this.size.toString());
if (this.slot != null) itemCatJson.put("inventorySlot", this.slot.toString());
return itemCatJson;
}
@Override
public String getProjectFilename() {
return "itemcategories_" + getProject().name + ".json";
}
@Override
public String getProjectFilename() {
return "itemcategories_"+getProject().name+".json";
}
}

View File

@@ -1,123 +1,122 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.io.JsonPrettyWriter;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.*;
import java.util.List;
import java.util.Map;
public abstract class JSONElement extends GameDataElement {
private static final long serialVersionUID = -8015398814080503982L;
private static final long serialVersionUID = -8015398814080503982L;
//Available from state init.
public File jsonFile;
@SuppressWarnings("rawtypes")
public void parse() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List gameDataElements = (List) parser.parse(reader);
for (Object obj : gameDataElements) {
Map jsonObj = (Map)obj;
String id = (String) jsonObj.get("id");
if (id != null && id.equals(this.id )) {
this.parse(jsonObj);
this.state = State.parsed;
break;
}
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public abstract void parse(@SuppressWarnings("rawtypes") Map jsonObj);
@SuppressWarnings("rawtypes")
public abstract Map toJson();
public String toJsonString() {
StringWriter writer = new JsonPrettyWriter();
try {
JSONObject.writeJSONString(this.toJson(), writer);
} catch (IOException e) {
//Impossible with a StringWriter
}
return writer.toString();
}
@Override
public GameDataSet getDataSet() {
if (parent == null) {
System.out.println("blerf.");
}
return parent.getDataSet();
}
public void save() {
if (this.getParent() instanceof GameDataCategory<?> && writable) {
((GameDataCategory<?>)this.getParent()).save(this.jsonFile);
}
}
/**
* Returns null if save occurred (no notable events).
*/
public List<SaveEvent> attemptSave() {
List<SaveEvent> events = ((GameDataCategory<?>)this.getParent()).attemptSave(true, this.jsonFile.getName());
if (events == null || events.isEmpty()) {
return null;
}
if (events.size() == 1 && events.get(0).type == SaveEvent.Type.alsoSave && events.get(0).target == this) {
save();
return null;
}
return events;
}
//Available from state init.
public File jsonFile;
public static Integer getInteger(Number n) {
return n == null ? null : n.intValue();
}
@SuppressWarnings("rawtypes")
public void parse() {
if (shouldSkipParse()) {
return;
}
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List gameDataElements = (List) parser.parse(reader);
for (Object obj : gameDataElements) {
Map jsonObj = (Map) obj;
String id = (String) jsonObj.get("id");
try {
if (id != null && id.equals(this.id)) {
this.parse(jsonObj);
this.state = State.parsed;
break;
}
} catch (Exception e) {
System.out.println("Error in ID: " + id);
System.out.println(e.getMessage());
}
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IllegalArgumentException e) {
System.out.println(id);
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Double getDouble(Number n) {
return n == null ? null : n.doubleValue();
}
public static Double parseChance(String s) {
if (s.equals("100")) return 100d;
}
public abstract void parse(@SuppressWarnings("rawtypes") Map jsonObj);
@SuppressWarnings("rawtypes")
public abstract Map toJson();
public String toJsonString() {
Map json = this.toJson();
return FileUtils.toJsonString(json);
}
@Override
public GameDataSet getDataSet() {
if (parent == null) {
System.out.println("blerf.");
}
return parent.getDataSet();
}
public void save() {
if (this.getParent() instanceof GameDataCategory<?> && writable) {
((GameDataCategory<?>) this.getParent()).save(this.jsonFile);
}
}
/**
* Returns null if save occurred (no notable events).
*/
public List<SaveEvent> attemptSave() {
List<SaveEvent> events = ((GameDataCategory<?>) this.getParent()).attemptSave(true, this.jsonFile.getName());
if (events == null || events.isEmpty()) {
return null;
}
if (events.size() == 1 && events.get(0).type == SaveEvent.Type.alsoSave && events.get(0).target == this) {
save();
return null;
}
return events;
}
public static Integer getInteger(Number n) {
return n == null ? null : n.intValue();
}
public static Double getDouble(Number n) {
return n == null ? null : n.doubleValue();
}
public static Double parseChance(String s) {
if (s.equals("100")) return 100d;
else if (s.equals("70")) return 70d;
else if (s.equals("30")) return 30d;
else if (s.equals("25")) return 25d;
@@ -128,28 +127,30 @@ public abstract class JSONElement extends GameDataElement {
else if (s.equals("1/1000")) return 0.1;
else if (s.equals("1/10000")) return 0.01;
else if (s.indexOf('/') >= 0) {
int c = s.indexOf('/');
double a = 1;
try {
a = Integer.parseInt(s.substring(0, c));
} catch (NumberFormatException nfe) {}
double b = 100;
try {
b = Integer.parseInt(s.substring(c+1));
} catch (NumberFormatException nfe) {}
return a/b;
int c = s.indexOf('/');
double a = 1;
try {
a = Integer.parseInt(s.substring(0, c));
} catch (NumberFormatException nfe) {
}
double b = 100;
try {
b = Integer.parseInt(s.substring(c + 1));
} catch (NumberFormatException nfe) {
}
return a / b;
} else {
double a = 10;
try {
a = Double.parseDouble(s);
} catch (NumberFormatException nfe) {
}
return a;
}
else {
double a = 10;
try {
a = Double.parseDouble(s);
} catch (NumberFormatException nfe) {}
return a;
}
}
public static String printJsonChance(Double chance) {
if (chance.equals(100d)) return "100";
}
public static String printJsonChance(Double chance) {
if (chance.equals(100d)) return "100";
else if (chance.equals(70d)) return "70";
else if (chance.equals(30d)) return "30";
else if (chance.equals(25d)) return "25";
@@ -160,11 +161,11 @@ public abstract class JSONElement extends GameDataElement {
else if (chance.equals(0.1d)) return "1/1000";
else if (chance.equals(0.01d)) return "1/10000";
else {
if (chance.intValue() == chance) return Integer.toString(chance.intValue());
//TODO Better handling of fractions. Chance description need a complete overhaul in AT.
//This part does not output the input content of parseDouble(String s) in the case of fractions.
return chance.toString();
if (chance.intValue() == chance) return Integer.toString(chance.intValue());
//TODO Better handling of fractions. Chance description need a complete overhaul in AT.
//This part does not output the input content of parseDouble(String s) in the case of fractions.
return chance.toString();
}
}
}
}

View File

@@ -1,515 +1,363 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.Project;
public class NPC extends JSONElement {
private static final long serialVersionUID = 1093728879485491933L;
//Available from init state
//public String id = null; inherited.
public String name = null;
public String icon_id = null;
//Available from parsed state
public Integer max_hp = null;
public Integer max_ap = null;
public Integer move_cost = null;
public Integer unique = null;
public MonsterClass monster_class = null;
public MovementType movement_type = null;
public Integer attack_damage_max = null;
public Integer attack_damage_min = null;
public String spawngroup_id = null;
public String faction_id = null;
public String dialogue_id = null;
public String droplist_id = null;
public Integer attack_cost = null;
public Integer attack_chance = null;
public Integer critical_skill = null;
public Double critical_multiplier = null;
public Integer block_chance = null;
public Integer damage_resistance = null;
public HitEffect hit_effect = null;
//Available from linked state
public Dialogue dialogue = null;
public Droplist droplist = null;
public enum MonsterClass {
humanoid,
insect,
demon,
construct,
animal,
giant,
undead,
reptile,
ghost
}
public enum MovementType {
none,
helpOthers,
protectSpawn,
wholeMap
}
public static class HitEffect {
//Available from parsed state
public Integer hp_boost_min = null;
public Integer hp_boost_max = null;
public Integer ap_boost_min = null;
public Integer ap_boost_max = null;
public List<TimedConditionEffect> conditions_source = null;
public List<TimedConditionEffect> conditions_target = null;
}
public static class TimedConditionEffect {
//Available from parsed state
public Integer magnitude = null;
public String condition_id = null;
public Integer duration = null;
public Double chance = null;
//Available from linked state
public ActorCondition condition = null;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+name+" ("+id+")";
}
public static String getStaticDesc() {
return "NPCs";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<NPC> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List npcs = (List) parser.parse(reader);
for (Object obj : npcs) {
Map npcJson = (Map)obj;
NPC npc = fromJson(npcJson);
npc.jsonFile = jsonFile;
npc.parent = category;
if (npc.getDataType() == GameSource.Type.created || npc.getDataType() == GameSource.Type.altered) {
npc.writable = true;
}
category.add(npc);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static NPC fromJson(String jsonString) throws ParseException {
Map npcJson = (Map) new JSONParser().parse(jsonString);
NPC npc = fromJson(npcJson);
npc.parse(npcJson);
return npc;
}
@SuppressWarnings("rawtypes")
public static NPC fromJson(Map npcJson) {
NPC npc = new NPC();
npc.icon_id = (String) npcJson.get("iconID");
npc.id = (String) npcJson.get("id");
npc.name = (String) npcJson.get("name");
return npc;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map npcJson) {
this.max_hp = JSONElement.getInteger((Number) npcJson.get("maxHP"));
this.max_ap = JSONElement.getInteger((Number) npcJson.get("maxAP"));
this.move_cost = JSONElement.getInteger((Number) npcJson.get("moveCost"));
this.unique = JSONElement.getInteger((Number) npcJson.get("unique"));
if (npcJson.get("monsterClass") != null) this.monster_class = MonsterClass.valueOf((String) npcJson.get("monsterClass"));
if (npcJson.get("movementAggressionType") != null) this.movement_type = MovementType.valueOf((String) npcJson.get("movementAggressionType"));
if (npcJson.get("attackDamage") != null) {
this.attack_damage_min = JSONElement.getInteger((Number) (((Map)npcJson.get("attackDamage")).get("min")));
this.attack_damage_max = JSONElement.getInteger((Number) (((Map)npcJson.get("attackDamage")).get("max")));
}
this.spawngroup_id = (String) npcJson.get("spawnGroup");
this.faction_id = (String) npcJson.get("faction");
this.dialogue_id = (String) npcJson.get("phraseID");
this.droplist_id = (String) npcJson.get("droplistID");
this.attack_cost = JSONElement.getInteger((Number) npcJson.get("attackCost"));
this.attack_chance = JSONElement.getInteger((Number) npcJson.get("attackChance"));
this.critical_skill = JSONElement.getInteger((Number) npcJson.get("criticalSkill"));
//TODO correct game data, to unify format.
// this.critical_multiplier = JSONElement.getDouble((Number) npcJson.get("criticalMultiplier"));
if (npcJson.get("criticalMultiplier") != null) this.critical_multiplier = JSONElement.getDouble(Double.parseDouble(npcJson.get("criticalMultiplier").toString()));
this.block_chance = JSONElement.getInteger((Number) npcJson.get("blockChance"));
this.damage_resistance = JSONElement.getInteger((Number) npcJson.get("damageResistance"));
Map hitEffect = (Map) npcJson.get("hitEffect");
if (hitEffect != null) {
this.hit_effect = new HitEffect();
if (hitEffect.get("increaseCurrentHP") != null) {
this.hit_effect.hp_boost_max = JSONElement.getInteger((Number) (((Map)hitEffect.get("increaseCurrentHP")).get("max")));
this.hit_effect.hp_boost_min = JSONElement.getInteger((Number) (((Map)hitEffect.get("increaseCurrentHP")).get("min")));
}
if (hitEffect.get("increaseCurrentAP") != null) {
this.hit_effect.ap_boost_max = JSONElement.getInteger((Number) (((Map)hitEffect.get("increaseCurrentAP")).get("max")));
this.hit_effect.ap_boost_min = JSONElement.getInteger((Number) (((Map)hitEffect.get("increaseCurrentAP")).get("min")));
}
List conditionsSourceJson = (List) hitEffect.get("conditionsSource");
if (conditionsSourceJson != null && !conditionsSourceJson.isEmpty()) {
this.hit_effect.conditions_source = new ArrayList<NPC.TimedConditionEffect>();
for (Object conditionJsonObj : conditionsSourceJson) {
Map conditionJson = (Map)conditionJsonObj;
TimedConditionEffect condition = new TimedConditionEffect();
condition.condition_id = (String) conditionJson.get("condition");
condition.magnitude = JSONElement.getInteger((Number) conditionJson.get("magnitude"));
condition.duration = JSONElement.getInteger((Number) conditionJson.get("duration"));
if (conditionJson.get("chance") != null) condition.chance = JSONElement.parseChance(conditionJson.get("chance").toString());
this.hit_effect.conditions_source.add(condition);
}
}
List conditionsTargetJson = (List) hitEffect.get("conditionsTarget");
if (conditionsTargetJson != null && !conditionsTargetJson.isEmpty()) {
this.hit_effect.conditions_target = new ArrayList<NPC.TimedConditionEffect>();
for (Object conditionJsonObj : conditionsTargetJson) {
Map conditionJson = (Map)conditionJsonObj;
TimedConditionEffect condition = new TimedConditionEffect();
condition.condition_id = (String) conditionJson.get("condition");
condition.magnitude = JSONElement.getInteger((Number) conditionJson.get("magnitude"));
condition.duration = JSONElement.getInteger((Number) conditionJson.get("duration"));
if (conditionJson.get("chance") != null) condition.chance = JSONElement.parseChance(conditionJson.get("chance").toString());
this.hit_effect.conditions_target.add(condition);
}
}
}
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking item "+id+". No parent project found.");
return;
}
if (this.icon_id != null) {
String spritesheetId = this.icon_id.split(":")[0];
proj.getSpritesheet(spritesheetId).addBacklink(this);
}
if (this.dialogue_id != null) this.dialogue = proj.getDialogue(this.dialogue_id);
if (this.dialogue != null) this.dialogue.addBacklink(this);
if (this.droplist_id != null) this.droplist = proj.getDroplist(this.droplist_id);
if (this.droplist != null) this.droplist.addBacklink(this);
if (this.hit_effect != null && this.hit_effect.conditions_source != null) {
for (TimedConditionEffect ce : this.hit_effect.conditions_source) {
if (ce.condition_id != null) ce.condition = proj.getActorCondition(ce.condition_id);
if (ce.condition != null) ce.condition.addBacklink(this);
}
}
if (this.hit_effect != null && this.hit_effect.conditions_target != null) {
for (TimedConditionEffect ce : this.hit_effect.conditions_target) {
if (ce.condition_id != null) ce.condition = proj.getActorCondition(ce.condition_id);
if (ce.condition != null) ce.condition.addBacklink(this);
}
}
this.state = State.linked;
}
@Override
public Image getIcon() {
return getProject().getIcon(icon_id);
}
public Image getImage() {
return getProject().getImage(icon_id);
}
@Override
public GameDataElement clone() {
NPC clone = new NPC();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.name = this.name;
clone.icon_id = this.icon_id;
clone.attack_chance = this.attack_chance;
clone.attack_cost = this.attack_cost;
clone.attack_damage_min = this.attack_damage_min;
clone.attack_damage_max = this.attack_damage_max;
clone.block_chance = this.block_chance;
clone.critical_multiplier = this.critical_multiplier;
clone.critical_skill = this.critical_skill;
clone.damage_resistance = this.damage_resistance;
clone.dialogue = this.dialogue;
if (clone.dialogue != null) {
clone.dialogue.addBacklink(clone);
}
clone.dialogue_id = this.dialogue_id;
clone.droplist = this.droplist;
if (clone.droplist != null) {
clone.droplist.addBacklink(clone);
}
clone.droplist_id = this.droplist_id;
clone.faction_id = this.faction_id;
if (this.hit_effect != null) {
clone.hit_effect = new HitEffect();
clone.hit_effect.ap_boost_max = this.hit_effect.ap_boost_max;
clone.hit_effect.ap_boost_min = this.hit_effect.ap_boost_min;
clone.hit_effect.hp_boost_max = this.hit_effect.hp_boost_max;
clone.hit_effect.hp_boost_min = this.hit_effect.hp_boost_min;
if (this.hit_effect.conditions_source != null) {
clone.hit_effect.conditions_source = new ArrayList<TimedConditionEffect>();
for (TimedConditionEffect c : this.hit_effect.conditions_source) {
TimedConditionEffect cclone = new TimedConditionEffect();
cclone.magnitude = c.magnitude;
cclone.condition_id = c.condition_id;
cclone.condition = c.condition;
cclone.chance = c.chance;
cclone.duration = c.duration;
if (cclone.condition != null) {
cclone.condition.addBacklink(clone);
}
clone.hit_effect.conditions_source.add(cclone);
}
}
if (this.hit_effect.conditions_target != null) {
clone.hit_effect.conditions_target = new ArrayList<TimedConditionEffect>();
for (TimedConditionEffect c : this.hit_effect.conditions_target) {
TimedConditionEffect cclone = new TimedConditionEffect();
cclone.magnitude = c.magnitude;
cclone.condition_id = c.condition_id;
cclone.condition = c.condition;
cclone.chance = c.chance;
cclone.duration = c.duration;
if (cclone.condition != null) {
cclone.condition.addBacklink(clone);
}
clone.hit_effect.conditions_target.add(cclone);
}
}
}
clone.max_ap = this.max_ap;
clone.max_hp = this.max_hp;
clone.monster_class = this.monster_class;
clone.move_cost = this.move_cost;
clone.movement_type = this.movement_type;
clone.spawngroup_id = this.spawngroup_id;
clone.unique = this.unique;
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (dialogue == oldOne) {
oldOne.removeBacklink(this);
this.dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(this);
} else {
if (this.droplist == oldOne) {
oldOne.removeBacklink(this);
this.droplist = (Droplist) newOne;
if (newOne != null) newOne.addBacklink(this);
} else {
if (this.hit_effect != null && this.hit_effect.conditions_source != null) {
for (TimedConditionEffect tce : this.hit_effect.conditions_source) {
if (tce.condition == oldOne) {
oldOne.removeBacklink(this);
tce.condition = (ActorCondition) newOne;
if (newOne != null) newOne.addBacklink(this);
}
}
}
if (this.hit_effect != null && this.hit_effect.conditions_target != null) {
for (TimedConditionEffect tce : this.hit_effect.conditions_target) {
if (tce.condition == oldOne) {
oldOne.removeBacklink(this);
tce.condition = (ActorCondition) newOne;
if (newOne != null) newOne.addBacklink(this);
}
}
}
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map npcJson = new LinkedHashMap();
npcJson.put("id", this.id);
if (this.name != null) npcJson.put("name", this.name);
if (this.icon_id != null) npcJson.put("iconID", this.icon_id);
if (this.max_hp != null) npcJson.put("maxHP", this.max_hp);
if (this.max_ap != null) npcJson.put("maxAP", this.max_ap);
if (this.move_cost != null) npcJson.put("moveCost", this.move_cost);
if (this.unique != null) npcJson.put("unique", this.unique);
if (this.monster_class != null) npcJson.put("monsterClass", this.monster_class.toString());
if (this.movement_type != null) npcJson.put("movementAggressionType", this.movement_type.toString());
if (this.attack_damage_min != null || this.attack_damage_max != null) {
Map adJson = new LinkedHashMap();
npcJson.put("attackDamage", adJson);
if (this.attack_damage_min != null) adJson.put("min", this.attack_damage_min);
else adJson.put("min", 0);
if (this.attack_damage_max != null) adJson.put("max", this.attack_damage_max);
else adJson.put("max", 0);
}
if (this.spawngroup_id != null) npcJson.put("spawnGroup", this.spawngroup_id);
if (this.faction_id != null) npcJson.put("faction", this.faction_id);
if (this.dialogue != null) {
npcJson.put("phraseID", this.dialogue.id);
} else if (this.dialogue_id != null) {
npcJson.put("phraseID", this.dialogue_id);
}
if (this.droplist != null) {
npcJson.put("droplistID", this.droplist.id);
} else if (this.droplist_id != null) {
npcJson.put("droplistID", this.droplist_id);
}
if (this.attack_cost != null) npcJson.put("attackCost", this.attack_cost);
if (this.attack_chance != null) npcJson.put("attackChance", this.attack_chance);
if (this.critical_skill != null) npcJson.put("criticalSkill", this.critical_skill);
if (this.critical_multiplier != null) npcJson.put("criticalMultiplier", this.critical_multiplier);
if (this.block_chance != null) npcJson.put("blockChance", this.block_chance);
if (this.damage_resistance != null) npcJson.put("damageResistance", this.damage_resistance);
if (this.hit_effect != null) {
Map hitEffectJson = new LinkedHashMap();
npcJson.put("hitEffect", hitEffectJson);
if (this.hit_effect.hp_boost_min != null || this.hit_effect.hp_boost_max != null) {
Map hpJson = new LinkedHashMap();
hitEffectJson.put("increaseCurrentHP", hpJson);
if (this.hit_effect.hp_boost_min != null) hpJson.put("min", this.hit_effect.hp_boost_min);
else hpJson.put("min", 0);
if (this.hit_effect.hp_boost_max != null) hpJson.put("max", this.hit_effect.hp_boost_max);
else hpJson.put("max", 0);
}
if (this.hit_effect.ap_boost_min != null || this.hit_effect.ap_boost_max != null) {
Map apJson = new LinkedHashMap();
hitEffectJson.put("increaseCurrentAP", apJson);
if (this.hit_effect.ap_boost_min != null) apJson.put("min", this.hit_effect.ap_boost_min);
else apJson.put("min", 0);
if (this.hit_effect.ap_boost_max != null) apJson.put("max", this.hit_effect.ap_boost_max);
else apJson.put("max", 0);
}
if (this.hit_effect.conditions_source != null) {
List conditionsSourceJson = new ArrayList();
hitEffectJson.put("conditionsSource", conditionsSourceJson);
for (TimedConditionEffect condition : this.hit_effect.conditions_source) {
Map conditionJson = new LinkedHashMap();
conditionsSourceJson.add(conditionJson);
if (condition.condition != null) {
conditionJson.put("condition", condition.condition.id);
} else if (condition.condition_id != null) {
conditionJson.put("condition", condition.condition_id);
}
if (condition.magnitude != null) conditionJson.put("magnitude", condition.magnitude);
if (condition.duration != null) conditionJson.put("duration", condition.duration);
if (condition.chance != null) conditionJson.put("chance", JSONElement.printJsonChance(condition.chance));
}
}
if (this.hit_effect.conditions_target != null) {
List conditionsTargetJson = new ArrayList();
hitEffectJson.put("conditionsTarget", conditionsTargetJson);
for (TimedConditionEffect condition : this.hit_effect.conditions_target) {
Map conditionJson = new LinkedHashMap();
conditionsTargetJson.add(conditionJson);
if (condition.condition != null) {
conditionJson.put("condition", condition.condition.id);
} else if (condition.condition_id != null) {
conditionJson.put("condition", condition.condition_id);
}
if (condition.magnitude != null) conditionJson.put("magnitude", condition.magnitude);
if (condition.duration != null) conditionJson.put("duration", condition.duration);
if (condition.chance != null) conditionJson.put("chance", JSONElement.printJsonChance(condition.chance));
}
}
}
return npcJson;
}
@Override
public String getProjectFilename() {
return "monsterlist_"+getProject().name+".json";
}
public int getMonsterExperience() {
double EXP_FACTOR_DAMAGERESISTANCE = 9;
double EXP_FACTOR_SCALING = 0.7;
double attacksPerTurn = Math.floor((double)(max_ap != null ? max_ap : 10.0) / (double)(attack_cost != null ? attack_cost : 10.0));
double avgDamagePotential = 0;
if (attack_damage_min != null || attack_damage_max != null) {
avgDamagePotential = ((double)(attack_damage_min != null ? attack_damage_min : 0) + (double)(attack_damage_max != null ? attack_damage_max : 0)) / 2.0;
}
double avgCrit = 0;
if (critical_skill != null && critical_multiplier != null) {
avgCrit = (double)(critical_skill / 100.0) * critical_multiplier;
}
double avgAttackHP = attacksPerTurn * ((double)(attack_chance != null ? attack_chance : 0) / 100.0) * avgDamagePotential * (1 + avgCrit);
double avgDefenseHP = ((max_hp != null ? max_hp : 1) * (1 + ((double)(block_chance != null ? block_chance : 0) / 100.0))) + ( EXP_FACTOR_DAMAGERESISTANCE * (damage_resistance != null ? damage_resistance : 0));
double attackConditionBonus = 0;
if (hit_effect != null && hit_effect.conditions_target != null && hit_effect.conditions_target.size() > 0) {
attackConditionBonus = 50;
}
double experience = (((avgAttackHP * 3) + avgDefenseHP) * EXP_FACTOR_SCALING) + attackConditionBonus;
return new Double(Math.ceil(experience)).intValue();
};
}
package com.gpl.rpg.atcontentstudio.model.gamedata;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.Project;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static com.gpl.rpg.atcontentstudio.model.gamedata.Common.*;
public class NPC extends JSONElement {
private static final long serialVersionUID = 1093728879485491933L;
//Available from init state
//public String id = null; inherited.
public String name = null;
public String icon_id = null;
//Available from parsed state
public Integer max_hp = null;
public Integer max_ap = null;
public Integer move_cost = null;
public Integer unique = null;
public MonsterClass monster_class = null;
public MovementType movement_type = null;
public Integer attack_damage_max = null;
public Integer attack_damage_min = null;
public String spawngroup_id = null;
public String faction_id = null;
public Integer spriteFlipChance = null;
public String dialogue_id = null;
public String droplist_id = null;
public Integer attack_cost = null;
public Integer attack_chance = null;
public Integer critical_skill = null;
public Double critical_multiplier = null;
public Integer block_chance = null;
public Integer damage_resistance = null;
public HitEffect hit_effect = null;
public HitReceivedEffect hit_received_effect = null;
public DeathEffect death_effect = null;
//Available from linked state
public Dialogue dialogue = null;
public Droplist droplist = null;
public enum MonsterClass {
humanoid,
insect,
demon,
construct,
animal,
giant,
undead,
reptile,
ghost
}
public enum MovementType {
none,
helpOthers,
protectSpawn,
wholeMap
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + name + " (" + id + ")";
}
public static String getStaticDesc() {
return "NPCs";
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<NPC> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List npcs = (List) parser.parse(reader);
for (Object obj : npcs) {
Map npcJson = (Map) obj;
NPC npc = fromJson(npcJson);
npc.jsonFile = jsonFile;
npc.parent = category;
if (npc.getDataType() == GameSource.Type.created || npc.getDataType() == GameSource.Type.altered) {
npc.writable = true;
}
category.add(npc);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static NPC fromJson(String jsonString) throws ParseException {
Map npcJson = (Map) new JSONParser().parse(jsonString);
NPC npc = fromJson(npcJson);
npc.parse(npcJson);
return npc;
}
@SuppressWarnings("rawtypes")
public static NPC fromJson(Map npcJson) {
NPC npc = new NPC();
npc.icon_id = (String) npcJson.get("iconID");
npc.id = (String) npcJson.get("id");
npc.name = (String) npcJson.get("name");
return npc;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map npcJson) {
this.max_hp = JSONElement.getInteger((Number) npcJson.get("maxHP"));
this.max_ap = JSONElement.getInteger((Number) npcJson.get("maxAP"));
this.move_cost = JSONElement.getInteger((Number) npcJson.get("moveCost"));
this.unique = JSONElement.getInteger((Number) npcJson.get("unique"));
if (npcJson.get("monsterClass") != null)
this.monster_class = MonsterClass.valueOf((String) npcJson.get("monsterClass"));
if (npcJson.get("movementAggressionType") != null)
this.movement_type = MovementType.valueOf((String) npcJson.get("movementAggressionType"));
if (npcJson.get("attackDamage") != null) {
this.attack_damage_min = JSONElement.getInteger((Number) (((Map) npcJson.get("attackDamage")).get("min")));
this.attack_damage_max = JSONElement.getInteger((Number) (((Map) npcJson.get("attackDamage")).get("max")));
}
this.spawngroup_id = (String) npcJson.get("spawnGroup");
this.faction_id = (String) npcJson.get("faction");
this.spriteFlipChance = JSONElement.getInteger((Number) npcJson.get("spriteFlipChance"));
this.dialogue_id = (String) npcJson.get("phraseID");
this.droplist_id = (String) npcJson.get("droplistID");
this.attack_cost = JSONElement.getInteger((Number) npcJson.get("attackCost"));
this.attack_chance = JSONElement.getInteger((Number) npcJson.get("attackChance"));
this.critical_skill = JSONElement.getInteger((Number) npcJson.get("criticalSkill"));
//TODO correct game data, to unify format.
// this.critical_multiplier = JSONElement.getDouble((Number) npcJson.get("criticalMultiplier"));
if (npcJson.get("criticalMultiplier") != null)
this.critical_multiplier = JSONElement.getDouble(Double.parseDouble(npcJson.get("criticalMultiplier").toString()));
this.block_chance = JSONElement.getInteger((Number) npcJson.get("blockChance"));
this.damage_resistance = JSONElement.getInteger((Number) npcJson.get("damageResistance"));
Map hitEffect = (Map) npcJson.get("hitEffect");
if (hitEffect != null) {
this.hit_effect = parseHitEffect(hitEffect);
}
Map hitReceivedEffect = (Map) npcJson.get("hitReceivedEffect");
if (hitReceivedEffect != null) {
this.hit_received_effect = parseHitReceivedEffect(hitReceivedEffect);
}
Map deathEffect = (Map) npcJson.get("deathEffect");
if (deathEffect != null) {
this.death_effect = parseDeathEffect(deathEffect);
}
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking item " + id + ". No parent project found.");
return;
}
linkIcon(proj, this.icon_id, this);
if (this.dialogue_id != null) this.dialogue = proj.getDialogue(this.dialogue_id);
if (this.dialogue != null) this.dialogue.addBacklink(this);
if (this.droplist_id != null) this.droplist = proj.getDroplist(this.droplist_id);
if (this.droplist != null) this.droplist.addBacklink(this);
linkEffects(this.hit_effect, proj, this);
linkEffects(this.hit_received_effect, proj, this);
linkEffects(this.death_effect, proj, this);
this.state = State.linked;
}
@Override
public Image getIcon() {
return getProject().getIcon(icon_id);
}
public Image getImage() {
return getProject().getImage(icon_id);
}
@Override
public GameDataElement clone() {
NPC clone = new NPC();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.name = this.name;
clone.icon_id = this.icon_id;
clone.attack_chance = this.attack_chance;
clone.attack_cost = this.attack_cost;
clone.attack_damage_min = this.attack_damage_min;
clone.attack_damage_max = this.attack_damage_max;
clone.block_chance = this.block_chance;
clone.critical_multiplier = this.critical_multiplier;
clone.critical_skill = this.critical_skill;
clone.damage_resistance = this.damage_resistance;
clone.dialogue = this.dialogue;
if (clone.dialogue != null) {
clone.dialogue.addBacklink(clone);
}
clone.dialogue_id = this.dialogue_id;
clone.droplist = this.droplist;
if (clone.droplist != null) {
clone.droplist.addBacklink(clone);
}
clone.droplist_id = this.droplist_id;
clone.faction_id = this.faction_id;
clone.spriteFlipChance = this.spriteFlipChance;
if (this.hit_effect != null) {
clone.hit_effect = new HitEffect();
copyHitEffectValues(clone.hit_effect, this.hit_effect, clone);
}
if (this.hit_received_effect != null) {
clone.hit_received_effect = new HitReceivedEffect();
copyHitReceivedEffectValues(clone.hit_received_effect, this.hit_received_effect, clone);
}
if (this.death_effect != null) {
clone.death_effect = new DeathEffect();
copyDeathEffectValues(clone.death_effect, this.death_effect, clone);
}
clone.max_ap = this.max_ap;
clone.max_hp = this.max_hp;
clone.monster_class = this.monster_class;
clone.move_cost = this.move_cost;
clone.movement_type = this.movement_type;
clone.spawngroup_id = this.spawngroup_id;
clone.unique = this.unique;
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (dialogue == oldOne) {
oldOne.removeBacklink(this);
this.dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(this);
} else {
if (this.droplist == oldOne) {
oldOne.removeBacklink(this);
this.droplist = (Droplist) newOne;
if (newOne != null) newOne.addBacklink(this);
} else {
if (this.hit_effect != null) {
actorConditionElementChanged(this.hit_effect.conditions_source, oldOne, newOne, this);
actorConditionElementChanged(this.hit_effect.conditions_target, oldOne, newOne, this);
}
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map npcJson = new LinkedHashMap();
npcJson.put("id", this.id);
if (this.name != null) npcJson.put("name", this.name);
writeIconToMap(npcJson, this.icon_id);
if (this.max_hp != null) npcJson.put("maxHP", this.max_hp);
if (this.max_ap != null) npcJson.put("maxAP", this.max_ap);
if (this.move_cost != null) npcJson.put("moveCost", this.move_cost);
if (this.unique != null) npcJson.put("unique", this.unique);
if (this.monster_class != null) npcJson.put("monsterClass", this.monster_class.toString());
if (this.movement_type != null) npcJson.put("movementAggressionType", this.movement_type.toString());
writeMinMaxToMap(npcJson, "attackDamage", this.attack_damage_min, attack_damage_max, 0);
if (this.spawngroup_id != null) npcJson.put("spawnGroup", this.spawngroup_id);
if (this.faction_id != null) npcJson.put("faction", this.faction_id);
if (this.spriteFlipChance != null) npcJson.put("spriteFlipChance", this.spriteFlipChance);
if (this.dialogue != null) {
npcJson.put("phraseID", this.dialogue.id);
} else if (this.dialogue_id != null) {
npcJson.put("phraseID", this.dialogue_id);
}
if (this.droplist != null) {
npcJson.put("droplistID", this.droplist.id);
} else if (this.droplist_id != null) {
npcJson.put("droplistID", this.droplist_id);
}
if (this.attack_cost != null) npcJson.put("attackCost", this.attack_cost);
if (this.attack_chance != null) npcJson.put("attackChance", this.attack_chance);
if (this.critical_skill != null) npcJson.put("criticalSkill", this.critical_skill);
if (this.critical_multiplier != null) npcJson.put("criticalMultiplier", this.critical_multiplier);
if (this.block_chance != null) npcJson.put("blockChance", this.block_chance);
if (this.damage_resistance != null) npcJson.put("damageResistance", this.damage_resistance);
writeHitEffectToMap(npcJson, this.hit_effect, "hitEffect");
writeHitReceivedEffectToMap(npcJson, this.hit_received_effect, "hitReceivedEffect");
writeDeathEffectToMap(npcJson, this.death_effect, "deathEffect");
return npcJson;
}
@Override
public String getProjectFilename() {
return "monsterlist_" + getProject().name + ".json";
}
public int getMonsterExperience() {
double EXP_FACTOR_DAMAGERESISTANCE = 9;
double EXP_FACTOR_SCALING = 0.7;
double attacksPerTurn = Math.floor((double) (max_ap != null ? max_ap : 10.0) / (double) (attack_cost != null ? attack_cost : 10.0));
double avgDamagePotential = 0;
if (attack_damage_min != null || attack_damage_max != null) {
avgDamagePotential = ((double) (attack_damage_min != null ? attack_damage_min : 0) + (double) (attack_damage_max != null ? attack_damage_max : 0)) / 2.0;
}
double avgCrit = 0;
if (critical_skill != null && critical_multiplier != null) {
avgCrit = (double) (critical_skill / 100.0) * critical_multiplier;
}
double avgAttackHP = attacksPerTurn * ((double) (attack_chance != null ? attack_chance : 0) / 100.0) * avgDamagePotential * (1 + avgCrit);
double avgDefenseHP = ((max_hp != null ? max_hp : 1) * (1 + ((double) (block_chance != null ? block_chance : 0) / 100.0))) +
(EXP_FACTOR_DAMAGERESISTANCE * (damage_resistance != null ? damage_resistance : 0));
double attackConditionBonus = 0;
if (hit_effect != null && hit_effect.conditions_target != null && hit_effect.conditions_target.size() > 0) {
attackConditionBonus = 50;
}
double experience = (((avgAttackHP * 3) + avgDefenseHP) * EXP_FACTOR_SCALING) + attackConditionBonus;
return new Double(Math.ceil(experience)).intValue();
}
}

View File

@@ -1,6 +1,13 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -10,189 +17,173 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class Quest extends JSONElement {
private static final long serialVersionUID = 2004839647483250099L;
//Available from init state
//public String id = null; inherited.
public String name = null;
//Available in parsed state
public Integer visible_in_log = null;
public List<QuestStage> stages = null;
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+name+" ("+id+")";
}
private static final long serialVersionUID = 2004839647483250099L;
public static String getStaticDesc() {
return "Quests";
}
//Available from init state
//public String id = null; inherited.
public String name = null;
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<Quest> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List quests = (List) parser.parse(reader);
for (Object obj : quests) {
Map questJson = (Map)obj;
Quest quest = fromJson(questJson);
quest.jsonFile = jsonFile;
quest.parent = category;
if (quest.getDataType() == GameSource.Type.created || quest.getDataType() == GameSource.Type.altered) {
quest.writable = true;
}
category.add(quest);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file "+jsonFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static Quest fromJson(String jsonString) throws ParseException {
Map questJson = (Map) new JSONParser().parse(jsonString);
Quest quest = fromJson(questJson);
quest.parse(questJson);
return quest;
}
@SuppressWarnings("rawtypes")
public static Quest fromJson(Map questJson) {
Quest quest = new Quest();
quest.id = (String) questJson.get("id");
quest.name = (String) questJson.get("name");
//Quests have to be parsed to have their stages initialized.
quest.parse(questJson);
return quest;
}
//Available in parsed state
public Integer visible_in_log = null;
public List<QuestStage> stages = null;
@SuppressWarnings("rawtypes")
@Override
public void parse(Map questJson) {
this.visible_in_log = JSONElement.getInteger((Number) questJson.get("showInLog"));
List questStagesJson = (List) questJson.get("stages");
if (questStagesJson != null && !questStagesJson.isEmpty()) {
this.stages = new ArrayList<QuestStage>();
for (Object questStageJsonObj : questStagesJson) {
Map questStageJson = (Map)questStageJsonObj;
QuestStage questStage = new QuestStage(this);
questStage.parse(questStageJson);
this.stages.add(questStage);
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
for (QuestStage stage : stages) {
stage.link();
}
//Nothing to link to :D
this.state = State.linked;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + name + " (" + id + ")";
}
@Override
public Image getIcon() {
return DefaultIcons.getQuestIcon();
}
public Image getImage() {
return DefaultIcons.getQuestImage();
}
@Override
public GameDataElement clone() {
Quest clone = new Quest();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.name = this.name;
clone.visible_in_log = this.visible_in_log;
if (this.stages != null) {
clone.stages = new ArrayList<QuestStage>();
for (QuestStage stage : this.stages){
clone.stages.add((QuestStage) stage.clone(clone));
}
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
//Nothing to link to.
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map questJson = new LinkedHashMap();
questJson.put("id", this.id);
if (this.name != null) questJson.put("name", this.name);
if (this.visible_in_log != null) questJson.put("showInLog", this.visible_in_log);
if (this.stages != null) {
List stagesJson = new ArrayList();
questJson.put("stages", stagesJson);
for (QuestStage stage : this.stages) {
stagesJson.add(stage.toJson());
}
}
return questJson;
}
public static String getStaticDesc() {
return "Quests";
}
@Override
public String getProjectFilename() {
return "questlist_"+getProject().name+".json";
}
public QuestStage getStage(Integer stageId) {
for (QuestStage stage : stages) {
if (stage.progress.equals(stageId)) {
return stage;
}
}
return null;
}
@SuppressWarnings("rawtypes")
public static void fromJson(File jsonFile, GameDataCategory<Quest> category) {
JSONParser parser = new JSONParser();
FileReader reader = null;
try {
reader = new FileReader(jsonFile);
List quests = (List) parser.parse(reader);
for (Object obj : quests) {
Map questJson = (Map) obj;
Quest quest = fromJson(questJson);
quest.jsonFile = jsonFile;
quest.parent = category;
if (quest.getDataType() == GameSource.Type.created || quest.getDataType() == GameSource.Type.altered) {
quest.writable = true;
}
category.add(quest);
}
} catch (FileNotFoundException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
Notification.addError("Error while parsing JSON file " + jsonFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public static Quest fromJson(String jsonString) throws ParseException {
Map questJson = (Map) new JSONParser().parse(jsonString);
Quest quest = fromJson(questJson);
quest.parse(questJson);
return quest;
}
@SuppressWarnings("rawtypes")
public static Quest fromJson(Map questJson) {
Quest quest = new Quest();
quest.id = (String) questJson.get("id");
quest.name = (String) questJson.get("name");
//Quests have to be parsed to have their stages initialized.
quest.parse(questJson);
return quest;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map questJson) {
this.visible_in_log = JSONElement.getInteger((Number) questJson.get("showInLog"));
List questStagesJson = (List) questJson.get("stages");
this.stages = new ArrayList<QuestStage>();
if (questStagesJson != null && !questStagesJson.isEmpty()) {
for (Object questStageJsonObj : questStagesJson) {
Map questStageJson = (Map) questStageJsonObj;
QuestStage questStage = new QuestStage(this);
questStage.parse(questStageJson);
this.stages.add(questStage);
}
}
this.state = State.parsed;
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
for (QuestStage stage : stages) {
stage.link();
}
//Nothing to link to :D
this.state = State.linked;
}
@Override
public Image getIcon() {
return DefaultIcons.getQuestIcon();
}
public Image getImage() {
return DefaultIcons.getQuestImage();
}
@Override
public GameDataElement clone() {
Quest clone = new Quest();
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.id = this.id;
clone.name = this.name;
clone.visible_in_log = this.visible_in_log;
if (this.stages != null) {
clone.stages = new ArrayList<QuestStage>();
for (QuestStage stage : this.stages) {
clone.stages.add((QuestStage) stage.clone(clone));
}
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
//Nothing to link to.
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map questJson = new LinkedHashMap();
questJson.put("id", this.id);
if (this.name != null) questJson.put("name", this.name);
if (this.visible_in_log != null) questJson.put("showInLog", this.visible_in_log);
if (this.stages != null) {
List stagesJson = new ArrayList();
questJson.put("stages", stagesJson);
for (QuestStage stage : this.stages) {
stagesJson.add(stage.toJson());
}
}
return questJson;
}
@Override
public String getProjectFilename() {
return "questlist_" + getProject().name + ".json";
}
public QuestStage getStage(Integer stageId) {
for (QuestStage stage : stages) {
if (stage.progress.equals(stageId)) {
return stage;
}
}
return null;
}
}

View File

@@ -1,103 +1,96 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import java.awt.Image;
import java.util.LinkedHashMap;
import java.util.Map;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
import java.util.LinkedHashMap;
import java.util.Map;
public class QuestStage extends JSONElement {
private static final long serialVersionUID = 8313645819951513431L;
public Integer progress = null;
public String log_text = null;
public Integer exp_reward = null;
public Integer finishes_quest = null;
public QuestStage(Quest parent){
this.parent = parent;
}
public QuestStage clone(Quest cloneParent) {
QuestStage clone = new QuestStage(cloneParent);
clone.progress = progress != null ? new Integer(progress) : null;
clone.log_text = log_text != null ? new String(log_text) : null;
clone.exp_reward = exp_reward != null ? new Integer(exp_reward) : null;
clone.finishes_quest = finishes_quest != null ? new Integer(finishes_quest) : null;
clone.id = this.id;
return clone;
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map jsonObj) {
progress = JSONElement.getInteger((Number) jsonObj.get("progress"));
this.id = ((Quest)parent).id+":"+progress;
log_text = (String) jsonObj.get("logText");
exp_reward = JSONElement.getInteger((Number) jsonObj.get("rewardExperience"));
finishes_quest = JSONElement.getInteger((Number) jsonObj.get("finishesQuest"));
state = State.parsed;
}
private static final long serialVersionUID = 8313645819951513431L;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Map toJson() {
Map stageJson = new LinkedHashMap();
if (progress != null) stageJson.put("progress", progress);
if (log_text != null) stageJson.put("logText", log_text);
if (exp_reward != null) stageJson.put("rewardExperience", exp_reward);
if (finishes_quest != null) stageJson.put("finishesQuest", finishes_quest);
return stageJson;
}
public Integer progress = null;
public String log_text = null;
public Integer exp_reward = null;
public Integer finishes_quest = null;
@Override
public String getDesc() {
return progress+" - "+(exp_reward != null ? "["+exp_reward+"XP]" : "")+((finishes_quest != null) && (finishes_quest == 1) ? "[END]" : "")+log_text;
}
public QuestStage(Quest parent) {
this.parent = parent;
}
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
//Nothing to link to :D
this.state = State.linked;
}
public QuestStage clone(Quest cloneParent) {
QuestStage clone = new QuestStage(cloneParent);
clone.progress = progress != null ? new Integer(progress) : null;
clone.log_text = log_text != null ? new String(log_text) : null;
clone.exp_reward = exp_reward != null ? new Integer(exp_reward) : null;
clone.finishes_quest = finishes_quest != null ? new Integer(finishes_quest) : null;
clone.id = this.id;
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
// Nothing to link to.
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map jsonObj) {
progress = JSONElement.getInteger((Number) jsonObj.get("progress"));
this.id = ((Quest) parent).id + ":" + progress;
log_text = (String) jsonObj.get("logText");
exp_reward = JSONElement.getInteger((Number) jsonObj.get("rewardExperience"));
finishes_quest = JSONElement.getInteger((Number) jsonObj.get("finishesQuest"));
state = State.parsed;
}
@Override
public String getProjectFilename() {
return ((Quest)parent).getProjectFilename();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public Map toJson() {
Map stageJson = new LinkedHashMap();
if (progress != null) stageJson.put("progress", progress);
if (log_text != null) stageJson.put("logText", log_text);
if (exp_reward != null) stageJson.put("rewardExperience", exp_reward);
if (finishes_quest != null) stageJson.put("finishesQuest", finishes_quest);
return stageJson;
}
@Override
public String getDesc() {
return progress + " - " + (exp_reward != null ? "[" + exp_reward + "XP]" : "") + ((finishes_quest != null) && (finishes_quest == 1) ? "[END]" : "") + log_text;
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
//Nothing to link to :D
this.state = State.linked;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
// Nothing to link to.
}
@Override
public String getProjectFilename() {
return ((Quest) parent).getProjectFilename();
}
@Override
public GameDataElement clone() {
return null;
}
@Override
public Image getIcon() {
return DefaultIcons.getQuestIcon();
}
public Image getImage() {
return DefaultIcons.getQuestImage();
}
@Override
public GameDataElement clone() {
return null;
}
@Override
public Image getIcon() {
return DefaultIcons.getQuestIcon();
}
public Image getImage() {
return DefaultIcons.getQuestImage();
}
}

View File

@@ -1,180 +1,230 @@
package com.gpl.rpg.atcontentstudio.model.gamedata;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.Project;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.Project;
public class Requirement extends JSONElement {
private static final long serialVersionUID = 7295593297142310955L;
private static Map<RequirementType, List<RequirementType>> COMPATIBLE_TYPES = new LinkedHashMap<RequirementType, List<RequirementType>>();
static {
List<RequirementType> questTypes = new ArrayList<RequirementType>();
questTypes.add(RequirementType.questProgress);
questTypes.add(RequirementType.questLatestProgress);
COMPATIBLE_TYPES.put(RequirementType.questProgress, questTypes);
COMPATIBLE_TYPES.put(RequirementType.questLatestProgress, questTypes);
List<RequirementType> countedItemTypes = new ArrayList<RequirementType>();
countedItemTypes.add(RequirementType.inventoryRemove);
countedItemTypes.add(RequirementType.inventoryKeep);
countedItemTypes.add(RequirementType.usedItem);
COMPATIBLE_TYPES.put(RequirementType.inventoryRemove, countedItemTypes);
COMPATIBLE_TYPES.put(RequirementType.inventoryKeep, countedItemTypes);
COMPATIBLE_TYPES.put(RequirementType.usedItem, countedItemTypes);
}
//Available from parsed state
public RequirementType type = null;
public String required_obj_id = null;
public Integer required_value = null;
public Boolean negated = null;
//Available from linked state
public GameDataElement required_obj = null;
public enum RequirementType {
questProgress,
questLatestProgress,
inventoryRemove,
inventoryKeep,
wear,
skillLevel,
killedMonster,
timerElapsed,
usedItem,
spentGold,
consumedBonemeals,
hasActorCondition
}
@Override
public String getDesc() {
return ((negated != null && negated) ? "NOT " : "")+required_obj_id+(required_value == null ? "" : ":"+required_value.toString());
}
private static final long serialVersionUID = 7295593297142310955L;
@Override
public void parse() {
throw new Error("Thou shalt not reach this method.");
}
private static Map<RequirementType, List<RequirementType>> COMPATIBLE_TYPES = new LinkedHashMap<RequirementType, List<RequirementType>>();
@SuppressWarnings("rawtypes")
@Override
public Map toJson() {
throw new Error("Thou shalt not reach this method.");
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map jsonObj) {
throw new Error("Thou shalt not reach this method.");
}
static {
List<RequirementType> questTypes = new ArrayList<RequirementType>();
questTypes.add(RequirementType.questProgress);
questTypes.add(RequirementType.questLatestProgress);
COMPATIBLE_TYPES.put(RequirementType.questProgress, questTypes);
COMPATIBLE_TYPES.put(RequirementType.questLatestProgress, questTypes);
@Override
public void link() {
if (this.state == State.created || this.state == State.modified || this.state == State.saved) {
//This type of state is unrelated to parsing/linking.
return;
}
if (this.state == State.init) {
//Not parsed yet.
this.parse();
} else if (this.state == State.linked) {
//Already linked.
return;
}
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking requirement "+getDesc()+". No parent project found.");
return;
}
switch (type) {
case hasActorCondition:
this.required_obj = proj.getActorCondition(required_obj_id);
break;
case inventoryKeep:
case inventoryRemove:
case usedItem:
case wear:
this.required_obj = proj.getItem(required_obj_id);
break;
case killedMonster:
this.required_obj = proj.getNPC(required_obj_id);
break;
case questLatestProgress:
case questProgress:
this.required_obj = proj.getQuest(required_obj_id);
if (this.required_obj != null && this.required_value != null) {
QuestStage stage = ((Quest)this.required_obj).getStage(this.required_value);
if (stage != null) {
stage.addBacklink((GameDataElement) this.parent);
}
}
break;
case consumedBonemeals:
case skillLevel:
case spentGold:
case timerElapsed:
break;
}
if (this.required_obj != null) this.required_obj.addBacklink((GameDataElement) this.parent);
this.state = State.linked;
}
@Override
public GameDataElement clone() {
return clone(null);
}
public GameDataElement clone(GameDataElement parent) {
Requirement clone = new Requirement();
clone.parent = parent;
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.required_obj_id = this.required_obj_id;
clone.required_value = this.required_value;
clone.required_obj = this.required_obj;
clone.type = this.type;
if (clone.required_obj != null && parent != null) {
clone.required_obj.addBacklink(parent);
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (this.required_obj == oldOne) {
oldOne.removeBacklink((GameDataElement) this.parent);
this.required_obj = newOne;
if (newOne != null) newOne.addBacklink((GameDataElement) this.parent);
}
if (oldOne instanceof QuestStage) {
if (this.required_obj != null && this.required_obj.equals(oldOne.parent) && this.required_value != null && this.required_value.equals(((QuestStage) oldOne).progress)) {
oldOne.removeBacklink((GameDataElement) this.parent);
if (newOne != null) newOne.addBacklink((GameDataElement) this.parent);
}
}
}
@Override
public String getProjectFilename() {
throw new Error("Thou shalt not reach this method.");
}
public void changeType(RequirementType destType) {
if (COMPATIBLE_TYPES.get(type) == null || !COMPATIBLE_TYPES.get(type).contains(destType)) {
required_obj = null;
required_obj_id = null;
required_value = null;
}
type = destType;
}
List<RequirementType> countedItemTypes = new ArrayList<RequirementType>();
countedItemTypes.add(RequirementType.inventoryRemove);
countedItemTypes.add(RequirementType.inventoryKeep);
countedItemTypes.add(RequirementType.usedItem);
countedItemTypes.add(RequirementType.wear);
countedItemTypes.add(RequirementType.wearRemove);
COMPATIBLE_TYPES.put(RequirementType.inventoryRemove, countedItemTypes);
COMPATIBLE_TYPES.put(RequirementType.inventoryKeep, countedItemTypes);
COMPATIBLE_TYPES.put(RequirementType.usedItem, countedItemTypes);
COMPATIBLE_TYPES.put(RequirementType.wear, countedItemTypes);
COMPATIBLE_TYPES.put(RequirementType.wearRemove, countedItemTypes);
}
//Available from parsed state
public RequirementType type = null;
public String required_obj_id = null;
public Integer required_value = null;
public Boolean negated = null;
//Available from linked state
public GameDataElement required_obj = null;
public enum RequirementType {
questProgress,
questLatestProgress,
inventoryRemove,
inventoryKeep,
wear,
skillLevel,
killedMonster,
timerElapsed,
usedItem,
spentGold,
consumedBonemeals,
hasActorCondition,
factionScore,
random,
factionScoreEquals,
wearRemove,
date,
dateEquals,
time,
timeEquals
}
public enum SkillID {
weaponChance, weaponDmg, barter, dodge, barkSkin, moreCriticals, betterCriticals, speed // Raises max ap
, coinfinder, moreExp, cleave // +10ap on kill
, eater // +1hp per kill
, fortitude // +N hp per levelup
, evasion // increase successful flee chance & reduce chance of monster attack
, regeneration // +N hp per round
, lowerExploss, magicfinder, resistanceMental // lowers chance to get negative active conditions by monsters (Mental like Dazed)
, resistancePhysical // lowers chance to get negative active conditions by monsters (Physical Capacity like Minor fatigue)
, resistanceBlood // lowers chance to get negative active conditions by monsters (Blood Disorder like Weak Poison)
, shadowBless, sporeImmunity, crit1 // lowers atk ability
, crit2 // lowers def ability ,rejuvenation // Reduces magnitudes of conditions
, rejuvenation // Reduces magnitudes of conditions
, taunt // Causes AP loss of attackers that miss
, concussion // AC loss for monsters with (AC-BC)>N
, weaponProficiencyDagger, weaponProficiency1hsword, weaponProficiency2hsword, weaponProficiencyAxe, weaponProficiencyBlunt, weaponProficiencyUnarmed, weaponProficiencyPole, armorProficiencyShield, armorProficiencyUnarmored, armorProficiencyLight, armorProficiencyHeavy, fightstyleDualWield, fightstyle2hand, fightstyleWeaponShield, specializationDualWield, specialization2hand, specializationWeaponShield
}
@Override
public String getDesc() {
String obj_id = "";
if (required_obj_id != null) {
obj_id = required_obj_id;
if (type != null && type == RequirementType.random) {
obj_id = " Chance " + obj_id + (required_obj_id.contains("/") ? "" : "%");
} else {
obj_id += ":";
}
}
return ((negated != null && negated) ? "NOT " : "")
+ (type == null ? "" : type.toString() + ":")
+ obj_id
+ (required_value == null ? "" : required_value.toString());
}
@Override
public void parse() {
throw new Error("Thou shalt not reach this method.");
}
@SuppressWarnings("rawtypes")
@Override
public Map toJson() {
throw new Error("Thou shalt not reach this method.");
}
@SuppressWarnings("rawtypes")
@Override
public void parse(Map jsonObj) {
throw new Error("Thou shalt not reach this method.");
}
@Override
public void link() {
if (shouldSkipParseOrLink()) {
return;
}
ensureParseIfNeeded();
Project proj = getProject();
if (proj == null) {
Notification.addError("Error linking requirement " + getDesc() + ". No parent project found.");
return;
}
switch (type) {
case hasActorCondition:
this.required_obj = proj.getActorCondition(required_obj_id);
break;
case inventoryKeep:
case inventoryRemove:
case usedItem:
case wear:
case wearRemove:
this.required_obj = proj.getItem(required_obj_id);
break;
case killedMonster:
this.required_obj = proj.getNPC(required_obj_id);
break;
case questLatestProgress:
case questProgress:
this.required_obj = proj.getQuest(required_obj_id);
if (this.required_obj != null && this.required_value != null) {
QuestStage stage = ((Quest) this.required_obj).getStage(this.required_value);
if (stage != null) {
stage.addBacklink((GameDataElement) this.parent);
}
}
break;
case consumedBonemeals:
case skillLevel:
case spentGold:
case timerElapsed:
case factionScore:
case factionScoreEquals:
case random:
case date:
case dateEquals:
case time:
case timeEquals:
break;
}
if (this.required_obj != null) this.required_obj.addBacklink((GameDataElement) this.parent);
this.state = State.linked;
}
@Override
public GameDataElement clone() {
return clone(null);
}
public GameDataElement clone(GameDataElement parent) {
Requirement clone = new Requirement();
clone.parent = parent;
clone.jsonFile = this.jsonFile;
clone.state = this.state;
clone.required_obj_id = this.required_obj_id;
clone.required_value = this.required_value;
clone.negated = this.negated;
clone.required_obj = this.required_obj;
clone.type = this.type;
if (clone.required_obj != null && parent != null) {
clone.required_obj.addBacklink(parent);
}
return clone;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (this.required_obj == oldOne) {
oldOne.removeBacklink((GameDataElement) this.parent);
this.required_obj = newOne;
if (newOne != null) newOne.addBacklink((GameDataElement) this.parent);
}
if (oldOne instanceof QuestStage) {
if (this.required_obj != null && this.required_obj.equals(oldOne.parent) && this.required_value != null && this.required_value.equals(((QuestStage) oldOne).progress)) {
oldOne.removeBacklink((GameDataElement) this.parent);
if (newOne != null) newOne.addBacklink((GameDataElement) this.parent);
}
}
}
@Override
public String getProjectFilename() {
throw new Error("Thou shalt not reach this method.");
}
public void changeType(RequirementType destType) {
if (COMPATIBLE_TYPES.get(type) == null || !COMPATIBLE_TYPES.get(type).contains(destType)) {
required_obj = null;
required_obj_id = null;
required_value = null;
}
if (destType == RequirementType.random) {
required_obj_id = "50/100";
}
type = destType;
}
}

View File

@@ -1,45 +1,46 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
public class ContainerArea extends MapObject {
public Droplist droplist = null;
public ContainerArea(tiled.core.MapObject obj) {}
@Override
public void link() {
droplist = parentMap.getProject().getDroplist(name);
if (droplist != null) {
droplist.addBacklink(parentMap);
}
}
@Override
public Image getIcon() {
if (droplist != null) return DefaultIcons.getContainerIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == droplist) {
oldOne.removeBacklink(parentMap);
droplist = (Droplist) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (droplist != null) {
tmxObject.setName(droplist.id);
}
}
public Droplist droplist = null;
public ContainerArea(tiled.core.MapObject obj) {
}
@Override
public void link() {
droplist = parentMap.getProject().getDroplist(name);
if (droplist != null) {
droplist.addBacklink(parentMap);
}
}
@Override
public Image getIcon() {
if (droplist != null) return DefaultIcons.getContainerIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == droplist) {
oldOne.removeBacklink(parentMap);
droplist = (Droplist) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (droplist != null) {
tmxObject.setName(droplist.id);
}
}
}

View File

@@ -1,110 +1,117 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
public class KeyArea extends MapObject {
public String dialogue_id = null;
public Dialogue dialogue = null;
public Requirement requirement = null;
public boolean oldSchoolRequirement = true;
public KeyArea(tiled.core.MapObject obj) {
dialogue_id = obj.getProperties().getProperty("phrase");
String requireType = obj.getProperties().getProperty("requireType");
String requireId = obj.getProperties().getProperty("requireId");
String requireValue = obj.getProperties().getProperty("requireValue");
if (requireId == null) {
String[] fields = obj.getName().split(":");
if (fields.length == 2) {
requireType = Requirement.RequirementType.questProgress.toString();
requireValue = fields[1];
requireId = fields[0];
} else if (fields.length == 3) {
requireValue = fields[2];
requireType = fields[0];
requireId = fields[1];
}
oldSchoolRequirement = true;
} else {
oldSchoolRequirement = false;
}
requirement = new Requirement();
if (requireType != null) requirement.type = Requirement.RequirementType.valueOf(requireType);
requirement.required_obj_id = requireId;
if (requireValue != null) requirement.required_value = Integer.parseInt(requireValue);
requirement.state = GameDataElement.State.parsed;
}
@Override
public void link() {
if (dialogue_id != null) dialogue = parentMap.getProject().getDialogue(dialogue_id);
if (dialogue != null) {
dialogue.addBacklink(parentMap);
}
requirement.parent = parentMap;
requirement.link();
}
@Override
public Image getIcon() {
if (dialogue != null && requirement != null) return DefaultIcons.getKeyIcon();
return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
requirement.elementChanged(oldOne, newOne);
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (dialogue != null) {
tmxObject.getProperties().setProperty("phrase", dialogue.id);
} else if (dialogue_id != null) {
tmxObject.getProperties().setProperty("phrase", dialogue_id);
}
if (requirement != null) {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
tmxObject.setName(requirement.required_obj_id+":"+Integer.toString(requirement.required_value));
} else {
if (requirement.type != null) {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
}
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
}
}
}
}
public String dialogue_id;
public Dialogue dialogue = null;
public Requirement requirement;
public boolean oldSchoolRequirement;
public void updateNameFromRequirementChange() {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
name = requirement.required_obj_id+":"+Integer.toString(requirement.required_value);
} else if (oldSchoolRequirement) {
int i = 0;
String futureName = requirement.type.toString() + "#" + Integer.toString(i);
while (parentMap.getMapObject(futureName) != null) {
i++;
futureName = requirement.type.toString() + "#" + Integer.toString(i);
}
this.name = futureName;
}
}
public KeyArea(tiled.core.MapObject obj) {
dialogue_id = obj.getProperties().getProperty("phrase");
String requireType = obj.getProperties().getProperty("requireType");
String requireId = obj.getProperties().getProperty("requireId");
String requireValue = obj.getProperties().getProperty("requireValue");
String requireNegation = obj.getProperties().getProperty("requireNegation");
oldSchoolRequirement = false;
if (requireType == null) {
String[] fields = obj.getName().split(":");
if (fields.length == 2) {
requireType = Requirement.RequirementType.questProgress.toString();
requireValue = fields[1];
requireId = fields[0];
oldSchoolRequirement = true;
} else if (fields.length == 3) {
requireValue = fields[2];
requireType = fields[0];
requireId = fields[1];
oldSchoolRequirement = true;
}
}
requirement = new Requirement();
if (requireType != null) requirement.type = Requirement.RequirementType.valueOf(requireType);
requirement.required_obj_id = requireId;
if (requireValue != null) requirement.required_value = Integer.parseInt(requireValue);
if (requireNegation != null) requirement.negated = Boolean.parseBoolean(requireNegation);
requirement.state = GameDataElement.State.parsed;
}
@Override
public void link() {
if (dialogue_id != null) dialogue = parentMap.getProject().getDialogue(dialogue_id);
if (dialogue != null) {
dialogue.addBacklink(parentMap);
}
requirement.parent = parentMap;
requirement.link();
}
@Override
public Image getIcon() {
if (dialogue != null && requirement != null) return DefaultIcons.getKeyIcon();
return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
requirement.elementChanged(oldOne, newOne);
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (dialogue != null) {
tmxObject.getProperties().setProperty("phrase", dialogue.id);
} else if (dialogue_id != null) {
tmxObject.getProperties().setProperty("phrase", dialogue_id);
}
if (requirement != null) {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
tmxObject.setName(requirement.required_obj_id + ":" + ((requirement.required_value == null) ? "" : Integer.toString(requirement.required_value)));
} else {
if (requirement.type != null) {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
}
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
}
if (requirement.negated != null) {
tmxObject.getProperties().setProperty("requireNegation", Boolean.toString(requirement.negated));
}
}
}
}
public void updateNameFromRequirementChange() {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
name = (requirement.negated != null && requirement.negated) ? "NOT " : "" + requirement.required_obj_id + ":" + ((requirement.required_value == null) ? "" : Integer.toString(
requirement.required_value));
} else if (oldSchoolRequirement) {
int i = 0;
String futureName = requirement.type.toString() + "#" + Integer.toString(i);
while (parentMap.getMapObject(futureName) != null) {
i++;
futureName = requirement.type.toString() + "#" + Integer.toString(i);
}
this.name = futureName;
}
}
}

View File

@@ -1,58 +1,57 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
public class MapChange extends MapObject {
public String map_id = null;
public TMXMap map = null;
public String place_id = null;
public MapChange(tiled.core.MapObject obj) {
this.map_id = obj.getProperties().getProperty("map");
this.place_id = obj.getProperties().getProperty("place");
}
public String map_id;
public TMXMap map = null;
public String place_id;
@Override
public void link() {
if (map_id != null) this.map = parentMap.getProject().getMap(map_id);
if (map != null) {
map.addBacklink(parentMap);
}
//TODO reinstate this if data validation system ever exist.
public MapChange(tiled.core.MapObject obj) {
this.map_id = obj.getProperties().getProperty("map");
this.place_id = obj.getProperties().getProperty("place");
}
@Override
public void link() {
if (map_id != null) this.map = parentMap.getProject().getMap(map_id);
if (map != null) {
map.addBacklink(parentMap);
}
//TODO reinstate this if data validation system ever exist.
// else Notification.addWarn("Incomplete mapchange area \""+name+"\" in map \""+parentMap.id+"\". This is OK if it's an arrival only (no exit through this point).");
}
@Override
public Image getIcon() {
if (name != null) return DefaultIcons.getTiledIconIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == map) {
oldOne.removeBacklink(parentMap);
map = (TMXMap) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (map != null) {
tmxObject.getProperties().setProperty("map", map.id);
} else if (map_id != null) {
tmxObject.getProperties().setProperty("map", map_id);
}
if (place_id != null) {
tmxObject.getProperties().setProperty("place", place_id);
}
}
}
@Override
public Image getIcon() {
if (name != null) return DefaultIcons.getTiledIconIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == map) {
oldOne.removeBacklink(parentMap);
map = (TMXMap) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (map != null) {
tmxObject.getProperties().setProperty("map", map.id);
} else if (map_id != null) {
tmxObject.getProperties().setProperty("map", map_id);
}
if (place_id != null) {
tmxObject.getProperties().setProperty("place", place_id);
}
}
}

View File

@@ -1,171 +1,171 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import java.awt.*;
public abstract class MapObject {
public int x, y, w, h;
public String name;
public TMXMap parentMap;
public Types type;
protected static enum Types {
mapchange,
spawn,
rest,
key,
replace,
script,
container,
sign
}
public static MapObject buildObject(tiled.core.MapObject obj, TMXMap parentMap) {
MapObject result = null;
if (obj.getType() != null && !obj.getType().equals("") && Types.valueOf(obj.getType()) != null) {
switch (Types.valueOf(obj.getType())) {
case key:
result = new KeyArea(obj);
result.type = Types.key;
break;
case mapchange:
result = new MapChange(obj);
result.type = Types.mapchange;
break;
case replace:
result = new ReplaceArea(obj);
result.type = Types.replace;
break;
case rest:
result = new RestArea(obj);
result.type = Types.rest;
break;
case script:
result = new ScriptArea(obj);
result.type = Types.script;
break;
case sign:
result = new SignArea(obj);
result.type = Types.sign;
break;
case spawn:
result = new SpawnArea(obj);
result.type = Types.spawn;
break;
case container:
result = new ContainerArea(obj);
result.type = Types.container;
break;
}
} else {
Notification.addWarn("Unknown map object type: "+obj.getType()+"with name "+obj.getName()+" in map "+parentMap.id);
}
if (result != null) {
result.x = obj.getX();
result.y = obj.getY();
result.w = obj.getWidth();
result.h = obj.getHeight();
result.name = obj.getName();
result.parentMap = parentMap;
}
return result;
}
public abstract void link();
public int x, y, w, h;
public String name;
public abstract Image getIcon();
public TMXMap parentMap;
public abstract void elementChanged(GameDataElement oldOne, GameDataElement newOne);
public Types type;
public tiled.core.MapObject toTmxObject() {
tiled.core.MapObject tmxObject = new tiled.core.MapObject(x, y, w, h);
tmxObject.setName(name);
tmxObject.setType(type.toString());
savePropertiesInTmxObject(tmxObject);
return tmxObject;
}
public abstract void savePropertiesInTmxObject(tiled.core.MapObject tmxObject);
public static MapObject newMapchange(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Mapchange");
MapObject result = new MapChange(obj);
result.type = Types.mapchange;
initObj(result, obj, parentMap);
return result;
}
protected static enum Types {
mapchange,
spawn,
rest,
key,
replace,
script,
container,
sign
}
public static MapObject newSpawnArea(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Spawnarea");
MapObject result = new SpawnArea(obj);
result.type = Types.spawn;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newRest(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Rest");
MapObject result = new RestArea(obj);
result.type = Types.rest;
initObj(result, obj, parentMap);
return result;
}
public static MapObject buildObject(tiled.core.MapObject obj, TMXMap parentMap) {
MapObject result = null;
if (obj.getType() != null && !obj.getType().equals("") && Types.valueOf(obj.getType()) != null) {
switch (Types.valueOf(obj.getType())) {
case key:
result = new KeyArea(obj);
result.type = Types.key;
break;
case mapchange:
result = new MapChange(obj);
result.type = Types.mapchange;
break;
case replace:
result = new ReplaceArea(obj);
result.type = Types.replace;
break;
case rest:
result = new RestArea(obj);
result.type = Types.rest;
break;
case script:
result = new ScriptArea(obj);
result.type = Types.script;
break;
case sign:
result = new SignArea(obj);
result.type = Types.sign;
break;
case spawn:
result = new SpawnArea(obj);
result.type = Types.spawn;
break;
case container:
result = new ContainerArea(obj);
result.type = Types.container;
break;
}
} else {
Notification.addWarn("Unknown map object type: " + obj.getType() + "with name " + obj.getName() + " in map " + parentMap.id);
}
if (result != null) {
result.x = obj.getX();
result.y = obj.getY();
result.w = obj.getWidth();
result.h = obj.getHeight();
result.name = obj.getName();
result.parentMap = parentMap;
}
return result;
}
public static MapObject newKey(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Key");
MapObject result = new KeyArea(obj);
result.type = Types.key;
initObj(result, obj, parentMap);
return result;
}
public abstract void link();
public static MapObject newReplace(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Replace");
MapObject result = new ReplaceArea(obj);
result.type = Types.replace;
initObj(result, obj, parentMap);
return result;
}
public abstract Image getIcon();
public static MapObject newScript(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Script");
MapObject result = new ScriptArea(obj);
result.type = Types.script;
initObj(result, obj, parentMap);
return result;
}
public abstract void elementChanged(GameDataElement oldOne, GameDataElement newOne);
public tiled.core.MapObject toTmxObject() {
tiled.core.MapObject tmxObject = new tiled.core.MapObject(x, y, w, h);
tmxObject.setName(name);
tmxObject.setType(type.toString());
savePropertiesInTmxObject(tmxObject);
return tmxObject;
}
public abstract void savePropertiesInTmxObject(tiled.core.MapObject tmxObject);
public static MapObject newMapchange(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Mapchange");
MapObject result = new MapChange(obj);
result.type = Types.mapchange;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newSpawnArea(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Spawnarea");
MapObject result = new SpawnArea(obj);
result.type = Types.spawn;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newRest(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Rest");
MapObject result = new RestArea(obj);
result.type = Types.rest;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newKey(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Key");
MapObject result = new KeyArea(obj);
result.type = Types.key;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newReplace(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Replace");
MapObject result = new ReplaceArea(obj);
result.type = Types.replace;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newScript(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Script");
MapObject result = new ScriptArea(obj);
result.type = Types.script;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newContainer(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Container");
MapObject result = new ContainerArea(obj);
result.type = Types.container;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newSign(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Sign");
MapObject result = new SignArea(obj);
result.type = Types.sign;
initObj(result, obj, parentMap);
return result;
}
private static MapObject initObj(MapObject result, tiled.core.MapObject obj, TMXMap parentMap) {
result.x = obj.getX();
result.y = obj.getY();
result.w = obj.getWidth();
result.h = obj.getHeight();
result.name = obj.getName();
result.parentMap = parentMap;
return result;
}
public static MapObject newContainer(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Container");
MapObject result = new ContainerArea(obj);
result.type = Types.container;
initObj(result, obj, parentMap);
return result;
}
public static MapObject newSign(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Sign");
MapObject result = new SignArea(obj);
result.type = Types.sign;
initObj(result, obj, parentMap);
return result;
}
private static MapObject initObj(MapObject result, tiled.core.MapObject obj, TMXMap parentMap) {
result.x = obj.getX();
result.y = obj.getY();
result.w = obj.getWidth();
result.h = obj.getHeight();
result.name = obj.getName();
result.parentMap = parentMap;
return result;
}
}

View File

@@ -1,60 +1,60 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import java.util.ArrayList;
import java.util.List;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
public class MapObjectGroup {
public tiled.core.ObjectGroup tmxGroup;
public TMXMap parentMap;
public String name;
public boolean visible;
public List<MapObject> mapObjects = new ArrayList<MapObject>();
public Boolean active;
public MapObjectGroup(tiled.core.ObjectGroup layer, TMXMap map) {
this.tmxGroup = layer;
this.name = layer.getName();
this.visible = layer.isVisible();
this.parentMap = map;
if (layer.getProperties().get("active") != null) {
active = new Boolean(((String) layer.getProperties().get("active")));
} else {
active = true;
}
for (tiled.core.MapObject obj : layer.getObjectsList()) {
mapObjects.add(MapObject.buildObject(obj, map));
}
}
public void link() {
for (MapObject obj : mapObjects) {
obj.link();
}
}
public tiled.core.ObjectGroup tmxGroup;
public TMXMap parentMap;
public String name;
public boolean visible;
public List<MapObject> mapObjects = new ArrayList<MapObject>();
public Boolean active;
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
for (MapObject object : mapObjects) {
object.elementChanged(oldOne, newOne);
}
}
public MapObjectGroup(tiled.core.ObjectGroup layer, TMXMap map) {
this.tmxGroup = layer;
this.name = layer.getName();
this.visible = layer.isVisible();
this.parentMap = map;
if (layer.getProperties().get("active") != null) {
active = new Boolean(((String) layer.getProperties().get("active")));
} else {
active = true;
}
for (tiled.core.MapObject obj : layer.getObjectsList()) {
mapObjects.add(MapObject.buildObject(obj, map));
}
}
public void pushBackToTiledProperties() {
if (tmxGroup != null) {
tmxGroup.clear();
} else {
tmxGroup = new tiled.core.ObjectGroup();
}
tmxGroup.setVisible(visible);
tmxGroup.setName(name);
if (!active) {
tmxGroup.getProperties().put("active", Boolean.toString(active));
}
for (MapObject object : mapObjects) {
tmxGroup.addObject(object.toTmxObject());
}
}
public void link() {
for (MapObject obj : mapObjects) {
obj.link();
}
}
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
for (MapObject object : mapObjects) {
object.elementChanged(oldOne, newOne);
}
}
public void pushBackToTiledProperties() {
if (tmxGroup != null) {
tmxGroup.clear();
} else {
tmxGroup = new tiled.core.ObjectGroup();
}
tmxGroup.setVisible(visible);
tmxGroup.setName(name);
if (!active) {
tmxGroup.getProperties().put("active", Boolean.toString(active));
}
for (MapObject object : mapObjects) {
tmxGroup.addObject(object.toTmxObject());
}
}
}

View File

@@ -1,141 +1,134 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class ReplaceArea extends MapObject {
public Requirement requirement = null;
public boolean oldSchoolRequirement = false;
public List<ReplaceArea.Replacement> replacements = null;
public Requirement requirement;
public boolean oldSchoolRequirement = false;
public ReplaceArea(tiled.core.MapObject obj) {
// String requireType = obj.getProperties().getProperty("requireType");
String requireId = obj.getProperties().getProperty("requireId");
String requireValue = obj.getProperties().getProperty("requireValue");
if (requireId == null) {
String[] fields = obj.getName().split(":");
if (fields.length == 2) {
// requireType = Requirement.RequirementType.questProgress.toString();
requireValue = fields[1];
requireId = fields[0];
oldSchoolRequirement = true;
} /*else if (fields.length == 3) {
public List<ReplaceArea.Replacement> replacements = null;
public ReplaceArea(tiled.core.MapObject obj) {
String requireType = obj.getProperties().getProperty("requireType");
String requireId = obj.getProperties().getProperty("requireId");
String requireValue = obj.getProperties().getProperty("requireValue");
String requireNegation = obj.getProperties().getProperty("requireNegation");
if (requireType == null) {
String[] fields = obj.getName().split(":");
if (fields.length == 2) {
requireType = Requirement.RequirementType.questProgress.toString();
requireValue = fields[1];
requireId = fields[0];
oldSchoolRequirement = true;
} /*else if (fields.length == 3) {
requireValue = fields[2];
requireType = fields[0];
requireId = fields[1];
}*/
}
requirement = new Requirement();
//Replace areas only support questProgress requirements ATM
//requirement.type = Requirement.RequirementType.valueOf(requireType);
requirement.type = Requirement.RequirementType.questProgress;
requirement.required_obj_id = requireId;
if (requireValue != null) requirement.required_value = Integer.parseInt(requireValue);
requirement.state = GameDataElement.State.parsed;
for (Object s : obj.getProperties().keySet()) {
if (!TMXMap.isPaintedLayerName(s.toString())) continue;
if (replacements == null) replacements = new ArrayList<ReplaceArea.Replacement>();
replacements.add(new Replacement(s.toString(), obj.getProperties().getProperty(s.toString())));
}
}
}
requirement = new Requirement();
if (requireType != null) requirement.type = Requirement.RequirementType.valueOf(requireType);
requirement.required_obj_id = requireId;
if (requireValue != null) requirement.required_value = Integer.parseInt(requireValue);
if (requireNegation != null) requirement.negated = Boolean.parseBoolean(requireNegation);
requirement.state = GameDataElement.State.parsed;
@Override
public void link() {
requirement.parent = parentMap;
requirement.link();
}
@Override
public Image getIcon() {
return DefaultIcons.getReplaceIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
requirement.elementChanged(oldOne, newOne);
}
public ReplaceArea.Replacement addReplacement(String source, String target) {
Replacement repl = new Replacement(source, target);
addReplacement(repl);
return repl;
}
public void addReplacement(ReplaceArea.Replacement repl) {
if (replacements == null) replacements = new ArrayList<ReplaceArea.Replacement>();
replacements.add(repl);
}
// public void removeReplacement(String source, String target) {
// replacedLayers.remove(source);
// }
public void removeReplacement(Replacement repl) {
replacements.remove(repl);
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (replacements != null) {
for(Replacement r : replacements)
tmxObject.getProperties().setProperty(r.sourceLayer, r.targetLayer);
}
if (requirement != null) {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
tmxObject.setName(requirement.required_obj_id+":"+Integer.toString(requirement.required_value));
} else {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
}
}
}
}
//Don't use yet !
public void updateNameFromRequirementChange() {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
name = requirement.required_obj_id+":"+Integer.toString(requirement.required_value);
} else if (oldSchoolRequirement) {
int i = 0;
String futureName = requirement.type.toString() + "#" + Integer.toString(i);
while (parentMap.getMapObject(futureName) != null) {
i++;
futureName = requirement.type.toString() + "#" + Integer.toString(i);
}
this.name = futureName;
}
}
public class Replacement {
public String sourceLayer, targetLayer;
public Replacement(String source, String target) {
this.sourceLayer = source;
this.targetLayer = target;
}
}
for (Object s : obj.getProperties().keySet()) {
if (!TMXMap.isPaintedLayerName(s.toString())) continue;
if (replacements == null) replacements = new ArrayList<ReplaceArea.Replacement>();
replacements.add(new Replacement(s.toString(), obj.getProperties().getProperty(s.toString())));
}
public boolean hasReplacementFor(String name) {
if (name == null) return false;
for (Replacement repl : replacements) {
if (name.equalsIgnoreCase(repl.sourceLayer)) return true;
}
return false;
}
}
@Override
public void link() {
requirement.parent = parentMap;
requirement.link();
}
@Override
public Image getIcon() {
return DefaultIcons.getReplaceIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
requirement.elementChanged(oldOne, newOne);
}
public ReplaceArea.Replacement createReplacement(String source, String target) {
Replacement repl = new Replacement(source, target);
return repl;
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (replacements != null) {
for (Replacement r : replacements)
tmxObject.getProperties().setProperty(r.sourceLayer, r.targetLayer);
}
if (requirement != null) {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
tmxObject.setName(requirement.required_obj_id + ":" + ((requirement.required_value == null) ? "" : Integer.toString(requirement.required_value)));
} else {
if (requirement.type != null) {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
}
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
}
if (requirement.negated != null) {
tmxObject.getProperties().setProperty("requireNegation", Boolean.toString(requirement.negated));
}
}
}
}
//Don't use yet !
public void updateNameFromRequirementChange() {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
name = (requirement.negated != null && requirement.negated) ? "NOT " : "" + requirement.required_obj_id + ":" + ((requirement.required_value == null) ? "" : Integer.toString(
requirement.required_value));
} else if (oldSchoolRequirement) {
int i = 0;
String futureName = requirement.type.toString() + "#" + Integer.toString(i);
while (parentMap.getMapObject(futureName) != null) {
i++;
futureName = requirement.type.toString() + "#" + Integer.toString(i);
}
this.name = futureName;
}
}
public class Replacement {
public String sourceLayer, targetLayer;
public Replacement(String source, String target) {
this.sourceLayer = source;
this.targetLayer = target;
}
}
public boolean hasReplacementFor(String name) {
if (name == null) return false;
for (Replacement repl : replacements) {
if (name.equalsIgnoreCase(repl.sourceLayer)) return true;
}
return false;
}
}

View File

@@ -1,31 +1,33 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
public class RestArea extends MapObject {
public RestArea(tiled.core.MapObject obj) {}
public RestArea(tiled.core.MapObject obj) {
}
@Override
public void link() {
}
@Override
public Image getIcon() {
return DefaultIcons.getRestIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
}
@Override
public void link() {}
@Override
public Image getIcon() {
return DefaultIcons.getRestIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
}
}

View File

@@ -1,61 +1,61 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class ScriptArea extends MapObject {
public Dialogue dialogue = null;
public EvaluationTrigger trigger_type = null;
public enum EvaluationTrigger {
enter,
step,
round,
always
}
import java.awt.*;
public ScriptArea(tiled.core.MapObject obj) {
String triggerTypeId = obj.getProperties().getProperty("when");
if (triggerTypeId != null) {
trigger_type = EvaluationTrigger.valueOf(triggerTypeId);
}
}
@Override
public void link() {
if (name != null) dialogue = parentMap.getProject().getDialogue(name);
if (dialogue != null) {
dialogue.addBacklink(parentMap);
}
}
@Override
public Image getIcon() {
if (dialogue != null) return DefaultIcons.getScriptIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (dialogue != null) {
tmxObject.setName(dialogue.id);
}
if (trigger_type != null) {
tmxObject.getProperties().setProperty("when", trigger_type.toString());
}
}
public class ScriptArea extends MapObject {
public Dialogue dialogue = null;
public EvaluationTrigger trigger_type = null;
public enum EvaluationTrigger {
enter,
step,
round,
always
}
public ScriptArea(tiled.core.MapObject obj) {
String triggerTypeId = obj.getProperties().getProperty("when");
if (triggerTypeId != null) {
trigger_type = EvaluationTrigger.valueOf(triggerTypeId);
}
}
@Override
public void link() {
if (name != null) dialogue = parentMap.getProject().getDialogue(name);
if (dialogue != null) {
dialogue.addBacklink(parentMap);
}
}
@Override
public Image getIcon() {
if (dialogue != null) return DefaultIcons.getScriptIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (dialogue != null) {
tmxObject.setName(dialogue.id);
}
if (trigger_type != null) {
tmxObject.getProperties().setProperty("when", trigger_type.toString());
}
}
}

View File

@@ -1,47 +1,47 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
public class SignArea extends MapObject {
public Dialogue dialogue = null;
public SignArea(tiled.core.MapObject obj) {
}
public Dialogue dialogue = null;
public SignArea(tiled.core.MapObject obj) {
}
@Override
public void link() {
if (name != null) dialogue = parentMap.getProject().getDialogue(name);
if (dialogue != null) {
dialogue.addBacklink(parentMap);
}
}
@Override
public Image getIcon() {
if (dialogue != null) return DefaultIcons.getSignIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (dialogue != null) {
tmxObject.setName(dialogue.id);
}
}
@Override
public void link() {
if (name != null) dialogue = parentMap.getProject().getDialogue(name);
if (dialogue != null) {
dialogue.addBacklink(parentMap);
}
}
@Override
public Image getIcon() {
if (dialogue != null) return DefaultIcons.getSignIcon();
else return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (dialogue != null) {
tmxObject.setName(dialogue.id);
}
}
}

View File

@@ -1,89 +1,95 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class SpawnArea extends MapObject {
public int quantity = 1;
public int spawnchance = 10;
public boolean active = true;
public String spawngroup_id;
public List<NPC> spawnGroup = new ArrayList<NPC>();
public SpawnArea(tiled.core.MapObject obj) {
if (obj.getProperties().getProperty("quantity") != null) {
this.quantity = Integer.parseInt(obj.getProperties().getProperty("quantity"));
}
if (obj.getProperties().getProperty("spawnchance") != null) {
this.spawnchance = Integer.parseInt(obj.getProperties().getProperty("spawnchance"));
}
if (obj.getProperties().getProperty("active") != null) {
this.active = Boolean.parseBoolean(obj.getProperties().getProperty("active"));
}
if (obj.getProperties().getProperty("spawngroup") != null) {
this.spawngroup_id = obj.getProperties().getProperty("spawngroup");
} else if (obj.getName() != null ){
this.spawngroup_id = obj.getName();
}
}
public int quantity = 1;
public int respawnSpeed = 10;
public boolean active = true;
public boolean ignoreAreas = false;
public String spawngroup_id;
public List<NPC> spawnGroup = new ArrayList<NPC>();
@Override
public void link() {
if (spawngroup_id != null) {
spawnGroup = parentMap.getProject().getSpawnGroup(spawngroup_id);
} else {
spawnGroup = new ArrayList<NPC>();
}
if (spawnGroup != null) {
for (NPC npc : spawnGroup) {
npc.addBacklink(parentMap);
}
}
}
@Override
public Image getIcon() {
if (spawnGroup != null && !spawnGroup.isEmpty()) {
return spawnGroup.get(0).getIcon();
}
return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
int replacedIndex = -1;
for (NPC npc : spawnGroup) {
if (npc == oldOne) {
replacedIndex = spawnGroup.indexOf(npc);
}
}
if (replacedIndex >= 0) {
oldOne.removeBacklink(parentMap);
spawnGroup.set(replacedIndex, (NPC) newOne);
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (spawngroup_id != null) {
tmxObject.getProperties().setProperty("spawngroup", spawngroup_id);
}
if (quantity != 1) {
tmxObject.getProperties().setProperty("quantity", Integer.toString(quantity));
}
if (spawnchance != 10) {
tmxObject.getProperties().setProperty("spawnchance", Integer.toString(spawnchance));
}
if (!this.active) {
tmxObject.getProperties().setProperty("active", Boolean.toString(active));
}
}
public SpawnArea(tiled.core.MapObject obj) {
if (obj.getProperties().getProperty("quantity") != null) {
this.quantity = Integer.parseInt(obj.getProperties().getProperty("quantity"));
}
if (obj.getProperties().getProperty("respawnspeed") != null) {
this.respawnSpeed = Integer.parseInt(obj.getProperties().getProperty("respawnspeed"));
}
if (obj.getProperties().getProperty("active") != null) {
this.active = Boolean.parseBoolean(obj.getProperties().getProperty("active"));
}
if (obj.getProperties().getProperty("ignoreAreas") != null) {
this.ignoreAreas = Boolean.parseBoolean(obj.getProperties().getProperty("ignoreAreas"));
}
if (obj.getProperties().getProperty("spawngroup") != null) {
this.spawngroup_id = obj.getProperties().getProperty("spawngroup");
} else if (obj.getName() != null) {
this.spawngroup_id = obj.getName();
}
}
@Override
public void link() {
if (spawngroup_id != null) {
spawnGroup = parentMap.getProject().getSpawnGroup(spawngroup_id);
} else {
spawnGroup = new ArrayList<NPC>();
}
if (spawnGroup != null) {
for (NPC npc : spawnGroup) {
npc.addBacklink(parentMap);
}
}
}
@Override
public Image getIcon() {
if (spawnGroup != null && !spawnGroup.isEmpty()) {
return spawnGroup.get(0).getIcon();
}
return DefaultIcons.getNullifyIcon();
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
int replacedIndex = -1;
for (NPC npc : spawnGroup) {
if (npc == oldOne) {
replacedIndex = spawnGroup.indexOf(npc);
}
}
if (replacedIndex >= 0) {
oldOne.removeBacklink(parentMap);
spawnGroup.set(replacedIndex, (NPC) newOne);
if (newOne != null) newOne.addBacklink(parentMap);
}
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (spawngroup_id != null) {
tmxObject.getProperties().setProperty("spawngroup", spawngroup_id);
}
if (quantity != 1) {
tmxObject.getProperties().setProperty("quantity", Integer.toString(quantity));
}
if (respawnSpeed != 10) {
tmxObject.getProperties().setProperty("respawnspeed", Integer.toString(respawnSpeed));
}
if (!this.active) {
tmxObject.getProperties().setProperty("active", Boolean.toString(active));
}
if (this.ignoreAreas) {
tmxObject.getProperties().setProperty("ignoreAreas", Boolean.toString(ignoreAreas));
}
}
}

View File

@@ -1,476 +1,476 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.tree.TreeNode;
import tiled.io.TMXMapReader;
import tiled.io.TMXMapWriter;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.*;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import tiled.io.TMXMapReader;
import tiled.io.TMXMapWriter;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.io.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class TMXMap extends GameDataElement {
private static final long serialVersionUID = 1609502879500898837L;
public static final String GROUND_LAYER_NAME = "Ground";
public static final String OBJECTS_LAYER_NAME = "Objects";
public static final String ABOVE_LAYER_NAME = "Above";
public static final String WALKABLE_LAYER_NAME = "Walkable";
public enum ColorFilter {
none,
black20,
black40,
black60,
black80,
invert,
bw,
redtint,
greentint,
bluetint
}
public File tmxFile = null;
public tiled.core.Map tmxMap = null;
public Set<Spritesheet> usedSpritesheets = null;
public List<MapObjectGroup> groups = null;
public ProjectTreeNode parent;
public Integer outside = null;
public ColorFilter colorFilter = null;
private static final long serialVersionUID = 1609502879500898837L;
public boolean changedOnDisk = false;
public int dismissNextChangeNotif = 0;
public static final String GROUND_LAYER_NAME = "Ground";
public static final String OBJECTS_LAYER_NAME = "Objects";
public static final String ABOVE_LAYER_NAME = "Above";
public static final String TOP_LAYER_NAME = "Top";
public static final String WALKABLE_LAYER_NAME = "Walkable";
public TMXMap(TMXMapSet parent, File f) {
this.parent = parent;
this.tmxFile = f;
String name = f.getName();
id = name.substring(0, name.length() - 4);
}
public void parse() {
if (this.state == GameDataElement.State.init) {
if (tmxMap != null) return;
usedSpritesheets = new HashSet<Spritesheet>();
try {
tmxMap = new TMXMapReader().readMap(tmxFile.getAbsolutePath(), this);
if (tmxMap.getProperties().get("outdoors") != null) {
outside = new Integer(((String) tmxMap.getProperties().get("outdoors")));
}
if (tmxMap.getProperties().get("colorfilter") != null) {
colorFilter = ColorFilter.valueOf(((String) tmxMap.getProperties().get("colorfilter")));
}
} catch (FileNotFoundException e) {
Notification.addError("Impossible to load TMX map file "+tmxFile.getAbsolutePath());
} catch (Exception e) {
Notification.addError("Error while loading TMX map file "+tmxFile.getAbsolutePath()+": "+e.getMessage());
e.printStackTrace();
}
for (tiled.core.MapLayer layer : tmxMap.getLayers()) {
if (layer instanceof tiled.core.ObjectGroup) {
if (groups == null) {
groups = new ArrayList<MapObjectGroup>();
}
MapObjectGroup group = new MapObjectGroup((tiled.core.ObjectGroup) layer, this);
groups.add(group);
}
}
for (Spritesheet s : usedSpritesheets) {
s.addBacklink(this);
}
state = State.parsed;
}
}
public void create() {
if (tmxMap != null) return;
tmxMap = new tiled.core.Map(30, 30);
}
public TMXMap clone() {
TMXMap clone = new TMXMap((TMXMapSet) this.parent, this.tmxFile);
try {
clone.usedSpritesheets = new HashSet<Spritesheet>();
clone.tmxMap = new TMXMapReader().readMap(new StringReader(this.toXml()), clone);
if (clone.tmxMap.getProperties().get("outdoors") != null) {
clone.outside = new Integer(((String) clone.tmxMap.getProperties().get("outdoors")));
}
if (clone.tmxMap.getProperties().get("colorfilter") != null) {
clone.colorFilter = ColorFilter.valueOf(((String) tmxMap.getProperties().get("colorfilter")));
}
for (tiled.core.MapLayer layer : clone.tmxMap.getLayers()) {
if (layer instanceof tiled.core.ObjectGroup) {
if (clone.groups == null) {
clone.groups = new ArrayList<MapObjectGroup>();
}
MapObjectGroup group = new MapObjectGroup((tiled.core.ObjectGroup) layer, this);
group.link();
clone.groups.add(group);
}
}
for (Spritesheet s : usedSpritesheets) {
s.addBacklink(clone);
}
} catch (Exception e) {
Notification.addError("Error while cloning map "+this.id+" : "+e.getMessage());
e.printStackTrace();
}
return clone;
}
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
public enum ColorFilter {
none,
black20,
black40,
black60,
black80,
invert,
bw,
redtint,
greentint,
bluetint
}
@Override
public boolean getAllowsChildren() {
return false;
}
public File tmxFile;
public tiled.core.Map tmxMap = null;
public Set<Spritesheet> usedSpritesheets = null;
public List<MapObjectGroup> groups = null;
@Override
public TreeNode getChildAt(int arg0) {
return null;
}
public ProjectTreeNode parent;
public Integer outside = null;
public ColorFilter colorFilter = null;
@Override
public int getChildCount() {
return 0;
}
public boolean changedOnDisk = false;
public int dismissNextChangeNotif = 0;
@Override
public int getIndex(TreeNode arg0) {
return 0;
}
public TMXMap(TMXMapSet parent, File f) {
this.parent = parent;
this.tmxFile = f;
String name = f.getName();
id = name.substring(0, name.length() - 4);
}
@Override
public TreeNode getParent() {
return parent;
}
public void parse() {
if (this.state == GameDataElement.State.init) {
if (tmxMap != null) return;
usedSpritesheets = new HashSet<Spritesheet>();
try {
tmxMap = new TMXMapReader().readMap(tmxFile.getAbsolutePath(), this);
if (tmxMap.getProperties().get("outdoors") != null) {
outside = new Integer(((String) tmxMap.getProperties().get("outdoors")));
}
if (tmxMap.getProperties().get("colorfilter") != null) {
colorFilter = ColorFilter.valueOf(((String) tmxMap.getProperties().get("colorfilter")));
}
} catch (FileNotFoundException e) {
Notification.addError("Impossible to load TMX map file " + tmxFile.getAbsolutePath());
} catch (Exception e) {
Notification.addError("Error while loading TMX map file " + tmxFile.getAbsolutePath() + ": " + e.getMessage());
e.printStackTrace();
}
for (tiled.core.MapLayer layer : tmxMap.getLayers()) {
if (layer instanceof tiled.core.ObjectGroup) {
if (groups == null) {
groups = new ArrayList<MapObjectGroup>();
}
MapObjectGroup group = new MapObjectGroup((tiled.core.ObjectGroup) layer, this);
groups.add(group);
}
}
for (Spritesheet s : usedSpritesheets) {
s.addBacklink(this);
}
state = State.parsed;
}
}
@Override
public boolean isLeaf() {
return true;
}
public void create() {
if (tmxMap != null) return;
tmxMap = new tiled.core.Map(30, 30);
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenAdded(path);
}
public TMXMap clone() {
TMXMap clone = new TMXMap((TMXMapSet) this.parent, this.tmxFile);
try {
clone.usedSpritesheets = new HashSet<Spritesheet>();
clone.tmxMap = new TMXMapReader().readMap(new StringReader(this.toXml()), clone);
if (clone.tmxMap.getProperties().get("outdoors") != null) {
clone.outside = new Integer(((String) clone.tmxMap.getProperties().get("outdoors")));
}
if (clone.tmxMap.getProperties().get("colorfilter") != null) {
clone.colorFilter = ColorFilter.valueOf(((String) tmxMap.getProperties().get("colorfilter")));
}
for (tiled.core.MapLayer layer : clone.tmxMap.getLayers()) {
if (layer instanceof tiled.core.ObjectGroup) {
if (clone.groups == null) {
clone.groups = new ArrayList<MapObjectGroup>();
}
MapObjectGroup group = new MapObjectGroup((tiled.core.ObjectGroup) layer, this);
group.link();
clone.groups.add(group);
}
}
for (Spritesheet s : usedSpritesheets) {
s.addBacklink(clone);
}
} catch (Exception e) {
Notification.addError("Error while cloning map " + this.id + " : " + e.getMessage());
e.printStackTrace();
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenChanged(path);
}
return clone;
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenRemoved(path);
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+id;
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@Override
public Image getIcon() {
return DefaultIcons.getTiledIconIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getTiledIconIcon();
}
@Override
public Image getClosedIcon() {return null;}
@Override
public Image getOpenIcon() {return null;}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@Override
public boolean getAllowsChildren() {
return false;
}
public String toXml() {
if (outside != null && outside == 1) {
tmxMap.getProperties().put("outdoors", Integer.toString(outside));
} else {
tmxMap.getProperties().remove("outdoors");
}
if (colorFilter != null) {
tmxMap.getProperties().put("colorfilter", colorFilter.toString());
} else {
tmxMap.getProperties().remove("colorfilter");
}
for (MapObjectGroup group : groups) {
group.pushBackToTiledProperties();
if (!tmxMap.containsLayer(group.tmxGroup)) {
tmxMap.addLayer(group.tmxGroup);
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
TMXMapWriter writer = new TMXMapWriter();
writer.settings.layerCompressionMethod = TMXMapWriter.Settings.LAYER_COMPRESSION_METHOD_ZLIB;
if (getDataType() == GameSource.Type.source) {
writer.writeMap(tmxMap, baos, tmxFile.getAbsolutePath());
} else {
writer.writeMap(tmxMap, baos, getProject().baseContent.gameMaps.mapFolder.getAbsolutePath()+File.separator+"placeholder.tmx");
}
} catch (Exception e) {
Notification.addError("Error while converting map "+getDesc()+" to XML: "+e.getMessage());
e.printStackTrace();
}
return baos.toString();
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public TreeNode getChildAt(int arg0) {
return null;
}
public void save() {
if (writable) {
String xml = toXml();
try {
//TODO: check in fileutils, to test the workspace's filesystem once at startup, and figure out how many of these can occur, instead of hard-coded '2'
dismissNextChangeNotif += 2;
FileWriter w = new FileWriter(tmxFile);
w.write(xml);
w.close();
this.state = State.saved;
changedOnDisk = false;
Notification.addSuccess("TMX file "+tmxFile.getAbsolutePath()+" saved.");
} catch (IOException e) {
Notification.addError("Error while writing TMX file "+tmxFile.getAbsolutePath()+" : "+e.getMessage());
e.printStackTrace();
}
}
}
@Override
public List<SaveEvent> attemptSave() {
//TODO check cases where map should be moved from altered/created to created/altered....
save();
return null;
}
@Override
public int getChildCount() {
return 0;
}
public void delete() {
if (writable) {
if (tmxFile.exists()) {
if (tmxFile.delete()) {
Notification.addSuccess("TMX file "+tmxFile.getAbsolutePath()+" deleted.");
} else {
Notification.addError("Error while deleting TMX file "+tmxFile.getAbsolutePath());
}
}
((TMXMapSet)parent).tmxMaps.remove(this);
//TODO clear blacklinks ?
}
}
@Override
public int getIndex(TreeNode arg0) {
return 0;
}
@Override
public void link() {
if (this.state == GameDataElement.State.init) {
parse();
}
if (this.state == GameDataElement.State.parsed) {
if (groups != null) {
for (MapObjectGroup group : groups) {
group.link();
}
}
}
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
for (MapObjectGroup group : groups) {
group.elementChanged(oldOne, newOne);
}
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public String getProjectFilename() {
return tmxFile.getName();
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenAdded(path);
}
public void addLayer(tiled.core.MapLayer layer) {
tmxMap.addLayer(layer);
if (layer instanceof tiled.core.ObjectGroup) {
groups.add(new MapObjectGroup((tiled.core.ObjectGroup) layer, this));
}
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenChanged(path);
}
public void removeLayer(tiled.core.MapLayer layer) {
tmxMap.removeLayer(tmxMap.getLayerIndex(layer));
if (layer instanceof tiled.core.ObjectGroup) {
MapObjectGroup toRemove = null;
for (MapObjectGroup group : groups) {
if (group.tmxGroup == layer) {
toRemove = group;
}
}
if (toRemove != null) {
groups.remove(toRemove);
}
}
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenRemoved(path);
}
public MapObjectGroup getGroup(tiled.core.ObjectGroup selectedLayer) {
for (MapObjectGroup group : groups) {
if (group.tmxGroup == selectedLayer) {
return group;
}
}
return null;
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + id;
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public Image getIcon() {
return DefaultIcons.getTiledIconIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getTiledIconIcon();
}
@Override
public Image getClosedIcon() {
return null;
}
@Override
public Image getOpenIcon() {
return null;
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
public String toXml() {
if (outside != null && outside == 1) {
tmxMap.getProperties().put("outdoors", Integer.toString(outside));
} else {
tmxMap.getProperties().remove("outdoors");
}
if (colorFilter != null) {
tmxMap.getProperties().put("colorfilter", colorFilter.toString());
} else {
tmxMap.getProperties().remove("colorfilter");
}
for (MapObjectGroup group : groups) {
group.pushBackToTiledProperties();
if (!tmxMap.containsLayer(group.tmxGroup)) {
tmxMap.addLayer(group.tmxGroup);
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
TMXMapWriter writer = new TMXMapWriter();
writer.settings.layerCompressionMethod = TMXMapWriter.Settings.LAYER_COMPRESSION_METHOD_ZLIB;
if (getDataType() == GameSource.Type.source) {
writer.writeMap(tmxMap, baos, tmxFile.getAbsolutePath());
} else {
writer.writeMap(tmxMap, baos, ((TMXMapSet) this.parent).mapFolder.getAbsolutePath() + File.separator + "placeholder.tmx");
}
} catch (Exception e) {
Notification.addError("Error while converting map " + getDesc() + " to XML: " + e.getMessage());
e.printStackTrace();
}
return baos.toString();
}
@Override
public boolean isEmpty() {
return false;
}
public void save() {
if (writable) {
String xml = toXml();
try {
//TODO: check in fileutils, to test the workspace's filesystem once at startup, and figure out how many of these can occur, instead of hard-coded '2'
dismissNextChangeNotif += 2;
FileWriter w = new FileWriter(tmxFile);
w.write(xml);
w.close();
this.state = State.saved;
changedOnDisk = false;
Notification.addSuccess("TMX file " + tmxFile.getAbsolutePath() + " saved.");
} catch (IOException e) {
Notification.addError("Error while writing TMX file " + tmxFile.getAbsolutePath() + " : " + e.getMessage());
e.printStackTrace();
}
}
}
@Override
public List<SaveEvent> attemptSave() {
//TODO check cases where map should be moved from altered/created to created/altered....
save();
return null;
}
public void delete() {
if (writable) {
if (tmxFile.exists()) {
if (tmxFile.delete()) {
Notification.addSuccess("TMX file " + tmxFile.getAbsolutePath() + " deleted.");
} else {
Notification.addError("Error while deleting TMX file " + tmxFile.getAbsolutePath());
}
}
((TMXMapSet) parent).tmxMaps.remove(this);
//TODO clear blacklinks ?
}
}
@Override
public void link() {
if (this.state == GameDataElement.State.init) {
parse();
}
if (this.state == GameDataElement.State.parsed) {
if (groups != null) {
for (MapObjectGroup group : groups) {
group.link();
}
}
}
}
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
for (MapObjectGroup group : groups) {
group.elementChanged(oldOne, newOne);
}
}
@Override
public String getProjectFilename() {
return tmxFile.getName();
}
public void addLayer(tiled.core.MapLayer layer) {
tmxMap.addLayer(layer);
if (layer instanceof tiled.core.ObjectGroup) {
groups.add(new MapObjectGroup((tiled.core.ObjectGroup) layer, this));
}
}
public void removeLayer(tiled.core.MapLayer layer) {
tmxMap.removeLayer(tmxMap.getLayerIndex(layer));
if (layer instanceof tiled.core.ObjectGroup) {
MapObjectGroup toRemove = null;
for (MapObjectGroup group : groups) {
if (group.tmxGroup == layer) {
toRemove = group;
}
}
if (toRemove != null) {
groups.remove(toRemove);
}
}
}
public MapObjectGroup getGroup(tiled.core.ObjectGroup selectedLayer) {
for (MapObjectGroup group : groups) {
if (group.tmxGroup == selectedLayer) {
return group;
}
}
return null;
}
public List<String> getMapchangesNames() {
List<String> result = new ArrayList<String>();
result.add(null);
for (MapObjectGroup group : groups) {
for (MapObject obj : group.mapObjects) {
if (obj.type == MapObject.Types.mapchange) {
result.add(obj.name);
}
}
}
return result;
}
public MapObject getMapObject(String name) {
MapObject result = null;
for (MapObjectGroup group : groups) {
for (MapObject obj : group.mapObjects) {
if (obj.name.equals(name)) {
result = obj;
break;
}
}
}
return result;
}
public static boolean isPaintedLayerName(String name) {
return GROUND_LAYER_NAME.equalsIgnoreCase(name) ||
OBJECTS_LAYER_NAME.equalsIgnoreCase(name) ||
ABOVE_LAYER_NAME.equalsIgnoreCase(name) ||
TOP_LAYER_NAME.equalsIgnoreCase(name) ||
WALKABLE_LAYER_NAME.equalsIgnoreCase(name);
}
public void reload() {
tmxMap = null;
for (Spritesheet s : usedSpritesheets) {
s.elementChanged(this, null);
}
usedSpritesheets.clear();
for (MapObjectGroup g : groups) {
for (MapObject o : g.mapObjects) {
if (o instanceof ContainerArea) {
if (((ContainerArea) o).droplist != null) ((ContainerArea) o).droplist.elementChanged(this, null);
} else if (o instanceof KeyArea) {
if (((KeyArea) o).dialogue != null) ((KeyArea) o).dialogue.elementChanged(this, null);
if (((KeyArea) o).requirement != null && ((KeyArea) o).requirement.required_obj != null)
((KeyArea) o).requirement.required_obj.elementChanged(this, null);
} else if (o instanceof MapChange) {
if (((MapChange) o).map != null) ((MapChange) o).map.elementChanged(this, null);
} else if (o instanceof ReplaceArea) {
if (((ReplaceArea) o).requirement != null && ((ReplaceArea) o).requirement.required_obj != null)
((ReplaceArea) o).requirement.required_obj.elementChanged(this, null);
} else if (o instanceof RestArea) {
} else if (o instanceof ScriptArea) {
if (((ScriptArea) o).dialogue != null) ((ScriptArea) o).dialogue.elementChanged(this, null);
} else if (o instanceof SignArea) {
if (((SignArea) o).dialogue != null) ((SignArea) o).dialogue.elementChanged(this, null);
} else if (o instanceof SpawnArea) {
if (((SpawnArea) o).spawnGroup != null) {
for (NPC n : ((SpawnArea) o).spawnGroup) {
n.elementChanged(this, null);
}
}
}
}
}
groups.clear();
outside = null;
colorFilter = null;
state = GameDataElement.State.init;
this.link();
changedOnDisk = false;
for (MapChangedOnDiskListener l : listeners) {
l.mapReloaded();
}
}
public void mapChangedOnDisk() {
if (dismissNextChangeNotif > 0) {
dismissNextChangeNotif--;
} else {
changedOnDisk = true;
for (MapChangedOnDiskListener l : listeners) {
l.mapChanged();
}
}
}
public interface MapChangedOnDiskListener {
public void mapChanged();
public void mapReloaded();
}
private List<MapChangedOnDiskListener> listeners = new CopyOnWriteArrayList<TMXMap.MapChangedOnDiskListener>();
public void addMapChangedOnDiskListener(MapChangedOnDiskListener l) {
listeners.add(l);
}
public void removeMapChangedOnDiskListener(MapChangedOnDiskListener l) {
listeners.remove(l);
}
public List<String> getMapchangesNames() {
List<String> result = new ArrayList<String>();
result.add(null);
for (MapObjectGroup group : groups) {
for (MapObject obj : group.mapObjects) {
if (obj.type == MapObject.Types.mapchange) {
result.add(obj.name);
}
}
}
return result;
}
public MapObject getMapObject(String name) {
MapObject result = null;
for (MapObjectGroup group : groups) {
for (MapObject obj : group.mapObjects) {
if (obj.name.equals(name)) {
result = obj;
break;
}
}
}
return result;
}
public static boolean isPaintedLayerName(String name) {
return GROUND_LAYER_NAME.equalsIgnoreCase(name) ||
OBJECTS_LAYER_NAME.equalsIgnoreCase(name) ||
ABOVE_LAYER_NAME.equalsIgnoreCase(name) ||
WALKABLE_LAYER_NAME.equalsIgnoreCase(name);
}
public void reload() {
tmxMap = null;
for (Spritesheet s : usedSpritesheets) {
s.elementChanged(this, null);
}
usedSpritesheets.clear();
for (MapObjectGroup g : groups) {
for (MapObject o : g.mapObjects) {
if (o instanceof ContainerArea) {
if (((ContainerArea)o).droplist != null) ((ContainerArea)o).droplist.elementChanged(this, null);
} else if (o instanceof KeyArea) {
if (((KeyArea)o).dialogue != null) ((KeyArea)o).dialogue.elementChanged(this, null);
if (((KeyArea)o).requirement != null && ((KeyArea)o).requirement.required_obj != null) ((KeyArea)o).requirement.required_obj.elementChanged(this, null);
} else if (o instanceof MapChange) {
if (((MapChange)o).map != null) ((MapChange)o).map.elementChanged(this, null);
} else if (o instanceof ReplaceArea) {
if (((ReplaceArea)o).requirement != null && ((ReplaceArea)o).requirement.required_obj != null) ((ReplaceArea)o).requirement.required_obj.elementChanged(this, null);
} else if (o instanceof RestArea) {
} else if (o instanceof ScriptArea) {
if (((ScriptArea)o).dialogue != null) ((ScriptArea)o).dialogue.elementChanged(this, null);
} else if (o instanceof SignArea) {
if (((SignArea)o).dialogue != null) ((SignArea)o).dialogue.elementChanged(this, null);
} else if (o instanceof SpawnArea) {
if (((SpawnArea)o).spawnGroup != null) {
for (NPC n : ((SpawnArea)o).spawnGroup) {
n.elementChanged(this, null);
}
}
}
}
}
groups.clear();
outside = null;
colorFilter = null;
state = GameDataElement.State.init;
this.link();
changedOnDisk = false;
for (MapChangedOnDiskListener l : listeners) {
l.mapReloaded();
}
}
public void mapChangedOnDisk() {
if (dismissNextChangeNotif > 0) {
dismissNextChangeNotif--;
} else {
changedOnDisk = true;
for (MapChangedOnDiskListener l : listeners) {
l.mapChanged();
}
}
}
public interface MapChangedOnDiskListener {
public void mapChanged();
public void mapReloaded();
}
private List<MapChangedOnDiskListener> listeners = new CopyOnWriteArrayList<TMXMap.MapChangedOnDiskListener>();
public void addMapChangedOnDiskListener(MapChangedOnDiskListener l) {
listeners.add(l);
}
public void removeMapChangedOnDiskListener(MapChangedOnDiskListener l) {
listeners.remove(l);
}
}

View File

@@ -1,23 +1,5 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
@@ -28,244 +10,272 @@ import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class TMXMapSet implements ProjectTreeNode {
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res"+File.separator+"xml"+File.separator;
public static final String DEFAULT_REL_PATH_IN_PROJECT = "maps"+File.separator;
public static final String DEFAULT_REL_PATH_TO_DRAWABLE = ".."+File.separator+"drawable"+File.separator;
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res" + File.separator + "xml" + File.separator;
public static final String DEFAULT_REL_PATH_IN_PROJECT = "maps" + File.separator;
public static final String DEFAULT_REL_PATH_TO_DRAWABLE = ".." + File.separator + "drawable" + File.separator;
public static final String GAME_MAPS_ARRAY_NAME = "loadresource_maps";
public static final String DEBUG_SUFFIX = "_debug";
public static final String RESOURCE_PREFIX = "@xml/";
public static final String FILENAME_SUFFIX = ".tmx";
public File mapFolder = null;
public List<TMXMap> tmxMaps;
public ProjectTreeNode parent;
public TMXMapSet(GameSource source) {
this.parent = source;
if (source.type == GameSource.Type.source) {
this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
}
else if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_PROJECT);
if (!this.mapFolder.exists()) {
this.mapFolder.mkdirs();
}
FileUtils.makeSymlink(getProject().baseContent.gameSprites.drawableFolder, new File(mapFolder.getAbsolutePath()+File.separator+DEFAULT_REL_PATH_TO_DRAWABLE));
}
this.tmxMaps = new ArrayList<TMXMap>();
if (source.type == GameSource.Type.source && (source.parent.sourceSetToUse == ResourceSet.debugData || source.parent.sourceSetToUse == ResourceSet.gameData)) {
String suffix = (source.parent.sourceSetToUse == ResourceSet.debugData) ? DEBUG_SUFFIX : "";
if (source.referencedSourceFiles.get(GAME_MAPS_ARRAY_NAME+suffix) != null) {
for (String resource : source.referencedSourceFiles.get(GAME_MAPS_ARRAY_NAME+suffix)) {
File f = new File(mapFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
TMXMap map = new TMXMap(this, f);
tmxMaps.add(map);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
} else if (this.mapFolder != null) {
for (File f : this.mapFolder.listFiles()) {
if (f.getName().endsWith(".tmx") || f.getName().endsWith(".TMX")) {
TMXMap map = new TMXMap(this, f);
if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
map.writable = true;
}
tmxMaps.add(map);
}
}
}
Collections.sort(tmxMaps, new Comparator<TMXMap>() {
@Override
public int compare(TMXMap o1, TMXMap o2) {
return o1.id.compareTo(o2.id);
}
});
if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
final Path folderPath = Paths.get(mapFolder.getAbsolutePath());
Thread watcher = new Thread("Map folder watcher for "+source.type) {
public void run() {
WatchService watchService;
public static final String GAME_MAPS_ARRAY_NAME = "loadresource_maps";
public static final String DEBUG_SUFFIX = "_debug";
public static final String RESOURCE_PREFIX = "@xml/";
public static final String FILENAME_SUFFIX = ".tmx";
while(getProject().open) {
try {
watchService = FileSystems.getDefault().newWatchService();
WatchKey watchKey = folderPath.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey wk;
validService: while(getProject().open) {
wk = watchService.take();
for (WatchEvent<?> event : wk.pollEvents()) {
Path changed = (Path) event.context();
String name = changed.getFileName().toString();
String id = name.substring(0, name.length() - 4);
TMXMap map = getMap(id);
if (map != null) {
map.mapChangedOnDisk();
}
}
if(!wk.reset()) {
watchService.close();
break validService;
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
};
watcher.start();
}
}
@Override
public Enumeration<TMXMap> children() {
return Collections.enumeration(tmxMaps);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return tmxMaps.get(arg0);
}
@Override
public int getChildCount() {
return tmxMaps.size();
}
@Override
public int getIndex(TreeNode arg0) {
return tmxMaps.indexOf(arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (TMXMap map : tmxMaps) {
map.notifyCreated();
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+"TMX Maps";
}
@Override
public Project getProject() {
return parent.getProject();
}
public File mapFolder = null;
public List<TMXMap> tmxMaps;
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getTmxClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getTmxClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getTmxOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@Override
public boolean isEmpty() {
return tmxMaps.isEmpty();
}
public ProjectTreeNode parent;
public TMXMap getMap(String id) {
if (tmxMaps == null) return null;
for (TMXMap map : tmxMaps) {
if (id.equals(map.id)){
return map;
}
}
return null;
}
public TMXMapSet(GameSource source) {
this.parent = source;
if (source.type == GameSource.Type.source) {
this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
} else if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_PROJECT);
if (!this.mapFolder.exists()) {
this.mapFolder.mkdirs();
}
FileUtils.makeSymlink(getProject().baseContent.gameSprites.drawableFolder, new File(mapFolder.getAbsolutePath() + File.separator + DEFAULT_REL_PATH_TO_DRAWABLE));
}
this.tmxMaps = new ArrayList<TMXMap>();
public void addMap(TMXMap node) {
ProjectTreeNode higherEmptyParent = this;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode)higherEmptyParent.getParent()).isEmpty()) higherEmptyParent = (ProjectTreeNode)higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
tmxMaps.add(node);
if (node.tmxFile != null) {
//Altered node.
node.tmxFile = new File(this.mapFolder, node.tmxFile.getName());
} else {
//Created node.
node.tmxFile = new File(this.mapFolder, node.id+".tmx");
}
node.parent = this;
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
if (source.type == GameSource.Type.source && (source.parent.sourceSetToUse == ResourceSet.debugData || source.parent.sourceSetToUse == ResourceSet.gameData)) {
String suffix = (source.parent.sourceSetToUse == ResourceSet.debugData) ? DEBUG_SUFFIX : "";
if (source.referencedSourceFiles.get(GAME_MAPS_ARRAY_NAME + suffix) != null) {
for (String resource : source.referencedSourceFiles.get(GAME_MAPS_ARRAY_NAME + suffix)) {
File f = new File(mapFolder, resource.replaceAll(RESOURCE_PREFIX, "") + FILENAME_SUFFIX);
if (f.exists()) {
TMXMap map = new TMXMap(this, f);
tmxMaps.add(map);
} else {
Notification.addWarn("Unable to locate resource " + resource + " in the game source for project " + getProject().name);
}
}
}
} else if (this.mapFolder != null) {
for (File f : this.mapFolder.listFiles()) {
if (f.getName().endsWith(".tmx") || f.getName().endsWith(".TMX")) {
TMXMap map = new TMXMap(this, f);
if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
map.writable = true;
}
tmxMaps.add(map);
}
}
}
Collections.sort(tmxMaps, new Comparator<TMXMap>() {
@Override
public int compare(TMXMap o1, TMXMap o2) {
return o1.id.compareTo(o2.id);
}
});
if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
final Path folderPath = Paths.get(mapFolder.getAbsolutePath());
Thread watcher = new Thread("Map folder watcher for " + getProject().name + "/" + source.type) {
public void run() {
WatchService watchService;
while (getProject().open) {
try {
watchService = FileSystems.getDefault().newWatchService();
/*WatchKey watchKey = */
folderPath.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE);
WatchKey wk;
validService:
while (getProject().open) {
wk = watchService.poll(10, TimeUnit.SECONDS);
if (wk != null) {
for (WatchEvent<?> event : wk.pollEvents()) {
Path changed = (Path) event.context();
String name = changed.getFileName().toString();
String id = name.substring(0, name.length() - 4);
TMXMap map = getMap(id);
if (map != null) {
map.mapChangedOnDisk();
}
}
if (!wk.reset()) {
watchService.close();
break validService;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
watcher.start();
}
}
@Override
public Enumeration<TMXMap> children() {
return Collections.enumeration(tmxMaps);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return tmxMaps.get(arg0);
}
@Override
public int getChildCount() {
return tmxMaps.size();
}
@Override
public int getIndex(TreeNode arg0) {
return tmxMaps.indexOf(arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@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) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (TMXMap map : tmxMaps) {
map.notifyCreated();
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + "TMX Maps";
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getTmxClosedIcon();
}
@Override
public Image getLeafIcon() {
return DefaultIcons.getTmxClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getTmxOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@Override
public boolean isEmpty() {
return tmxMaps.isEmpty();
}
public TMXMap getMap(String id) {
if (tmxMaps == null) return null;
for (TMXMap map : tmxMaps) {
if (id.equals(map.id)) {
return map;
}
}
return null;
}
public void addMap(TMXMap node) {
ProjectTreeNode higherEmptyParent = this;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode) higherEmptyParent.getParent()).isEmpty())
higherEmptyParent = (ProjectTreeNode) higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
tmxMaps.add(node);
if (node.tmxFile != null) {
//Altered node.
node.tmxFile = new File(this.mapFolder, node.tmxFile.getName());
} else {
//Created node.
node.tmxFile = new File(this.mapFolder, node.id + ".tmx");
}
node.parent = this;
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
public TMXMap get(int index) {
return tmxMaps.get(index);
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : tmxMaps) {
if (node.needsSaving()) return true;
}
return false;
}
public TMXMap get(int index) {
return tmxMaps.get(index);
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : tmxMaps) {
if (node.needsSaving()) return true;
}
return false;
}
}

View File

@@ -1,40 +1,5 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.awt.Point;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
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.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
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.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
@@ -42,250 +7,272 @@ import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
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 javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.io.*;
import java.util.List;
import java.util.*;
public class Worldmap extends ArrayList<WorldmapSegment> implements ProjectTreeNode {
private static final long serialVersionUID = 4590409256594556179L;
private static final long serialVersionUID = 4590409256594556179L;
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res/xml/worldmap.xml";
public static final String DEFAULT_REL_PATH_IN_PROJECT = "maps"+File.separator+"worldmap.xml";
public File worldmapFile;
public GameSource parent;
public Map<String, Map<String, Point>> segments = new LinkedHashMap<String, Map<String,Point>>();
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res/xml/worldmap.xml";
public static final String DEFAULT_REL_PATH_IN_PROJECT = "maps" + File.separator + "worldmap.xml";
public Worldmap(GameSource gameSource) {
this.parent = gameSource;
if (getDataType() == Type.source) {
worldmapFile = new File(parent.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
} else {
worldmapFile = new File(parent.baseFolder, DEFAULT_REL_PATH_IN_PROJECT);
}
if (worldmapFile.exists()) {
loadFromFile(worldmapFile);
}
if (getDataType() == Type.source) {
for (WorldmapSegment segment : this) {
segment.writable = false;
}
} else {
for (WorldmapSegment segment : this) {
segment.writable = true;
}
}
}
public File worldmapFile;
public GameSource parent;
private void loadFromFile(File file) {
if (!file.exists()) return;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc;
try {
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource insrc = new InputSource(new FileInputStream(file));
insrc.setSystemId("http://worldmap/");
insrc.setEncoding("UTF-8");
doc = builder.parse(insrc);
Element root = (Element) doc.getElementsByTagName("worldmap").item(0);
if (root != null) {
NodeList segmentsList = root.getElementsByTagName("segment");
if (segmentsList != null) {
for (int i = 0; i < segmentsList.getLength(); i++) {
Element segmentNode = (Element) segmentsList.item(i);
String name = segmentNode.getAttribute("id");
add(new WorldmapSegment(this, name, segmentNode));
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Map<String, Map<String, Point>> segments = new LinkedHashMap<String, Map<String, Point>>();
@Override
public Enumeration<WorldmapSegment> children() {
return Collections.enumeration(this);
}
public Worldmap(GameSource gameSource) {
this.parent = gameSource;
if (getDataType() == Type.source) {
worldmapFile = new File(parent.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
} else {
worldmapFile = new File(parent.baseFolder, DEFAULT_REL_PATH_IN_PROJECT);
}
if (worldmapFile.exists()) {
loadFromFile(worldmapFile);
}
if (getDataType() == Type.source) {
for (WorldmapSegment segment : this) {
segment.writable = false;
}
} else {
for (WorldmapSegment segment : this) {
segment.writable = true;
}
}
}
@Override
public boolean getAllowsChildren() {
return true;
}
private void loadFromFile(File file) {
if (!file.exists()) return;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc;
try {
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource insrc = new InputSource(new FileInputStream(file));
insrc.setSystemId("http://worldmap/");
insrc.setEncoding("UTF-8");
doc = builder.parse(insrc);
@Override
public TreeNode getChildAt(int arg0) {
return get(arg0);
}
Element root = (Element) doc.getElementsByTagName("worldmap").item(0);
if (root != null) {
NodeList segmentsList = root.getElementsByTagName("segment");
if (segmentsList != null) {
for (int i = 0; i < segmentsList.getLength(); i++) {
Element segmentNode = (Element) segmentsList.item(i);
String name = segmentNode.getAttribute("id");
add(new WorldmapSegment(this, name, segmentNode));
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public int getChildCount() {
return size();
}
@Override
public Enumeration<WorldmapSegment> children() {
return Collections.enumeration(this);
}
@Override
public int getIndex(TreeNode arg0) {
return indexOf(arg0);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public TreeNode getChildAt(int arg0) {
return get(arg0);
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public int getChildCount() {
return size();
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenAdded(path);
}
@Override
public int getIndex(TreeNode arg0) {
return indexOf(arg0);
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenChanged(path);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+"Worldmap";
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenAdded(path);
}
@Override
public Image getIcon() {
return DefaultIcons.getMapClosedIcon();
}
@Override
public Image getLeafIcon() {
return null;
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getMapClosedIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getMapOpenIcon();
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenChanged(path);
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public Type getDataType() {
return parent.getDataType();
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "") + "Worldmap";
}
public void save() {
try {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
doc.setXmlVersion("1.0");
Element root = doc.createElement("worldmap");
doc.appendChild(root);
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
for (WorldmapSegment segment : this) {
root.appendChild(segment.toXmlElement(doc));
segment.state = GameDataElement.State.saved;
}
@Override
public Project getProject() {
return parent.getProject();
}
saveDocToFile(doc, worldmapFile);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public Image getIcon() {
return DefaultIcons.getMapClosedIcon();
}
public WorldmapSegment getWorldmapSegment(String id) {
for (WorldmapSegment s : this) {
if (s.id.equals(id)) {
return s;
}
}
return null;
}
@Override
public Image getLeafIcon() {
return null;
}
public void addSegment(WorldmapSegment node) {
ProjectTreeNode higherEmptyParent = this;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode)higherEmptyParent.getParent()).isEmpty()) higherEmptyParent = (ProjectTreeNode)higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
add(node);
node.parent = this;
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getMapClosedIcon();
}
public static void saveDocToFile(Document doc, File f) {
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(new FileOutputStream(f));
Source input = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2");
transformer.transform(input, output);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getMapOpenIcon();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Type getDataType() {
return parent.getDataType();
}
public void save() {
try {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
doc.setXmlVersion("1.0");
Element root = doc.createElement("worldmap");
doc.appendChild(root);
for (WorldmapSegment segment : this) {
root.appendChild(segment.toXmlElement(doc));
segment.state = GameDataElement.State.saved;
}
saveDocToFile(doc, worldmapFile);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public WorldmapSegment getWorldmapSegment(String id) {
for (WorldmapSegment s : this) {
if (s.id.equals(id)) {
return s;
}
}
return null;
}
public void addSegment(WorldmapSegment node) {
ProjectTreeNode higherEmptyParent = this;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode) higherEmptyParent.getParent()).isEmpty())
higherEmptyParent = (ProjectTreeNode) higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
add(node);
node.parent = this;
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
public static void saveDocToFile(Document doc, File f) {
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(new FileOutputStream(f));
Source input = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2");
transformer.transform(input, output);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : this) {
if (node.needsSaving()) return true;
}
return false;
}
@Override
public boolean needsSaving() {
for (ProjectTreeNode node : this) {
if (node.needsSaving()) return true;
}
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More