rgss_db 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/COPYING.md +674 -0
  4. data/README.md +347 -0
  5. data/bin/rgss-db +4 -0
  6. data/bin/rgssdb +4 -0
  7. data/lib/rgss_db/app.rb +928 -0
  8. data/lib/rgss_db/controller/data_manager.rb +557 -0
  9. data/lib/rgss_db/model/data_file.rb +516 -0
  10. data/lib/rgss_db/model/data_file_factory.rb +94 -0
  11. data/lib/rgss_db/model/debug.rb +199 -0
  12. data/lib/rgss_db/model/errors.rb +17 -0
  13. data/lib/rgss_db/model/mixins/jsonable.rb +35 -0
  14. data/lib/rgss_db/model/mixins/jsonable_constructor.rb +40 -0
  15. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/color.rb +72 -0
  16. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/rect.rb +70 -0
  17. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/table.rb +99 -0
  18. data/lib/rgss_db/model/rpg_maker_data/vx/rgss/tone.rb +72 -0
  19. data/lib/rgss_db/model/rpg_maker_data/vx/rgss.rb +11 -0
  20. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/actor.rb +44 -0
  21. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/animation.rb +31 -0
  22. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/animation_frame.rb +20 -0
  23. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/animation_timing.rb +23 -0
  24. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/area.rb +26 -0
  25. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/armor.rb +31 -0
  26. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/audio_file.rb +23 -0
  27. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/base_item.rb +25 -0
  28. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/bgm.rb +36 -0
  29. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/bgs.rb +36 -0
  30. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/class.rb +31 -0
  31. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/class_learning.rb +20 -0
  32. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/common_event.rb +25 -0
  33. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/enemy.rb +44 -0
  34. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/enemy_action.rb +29 -0
  35. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/enemy_drop_item.rb +23 -0
  36. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event.rb +36 -0
  37. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_command.rb +19 -0
  38. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_page.rb +32 -0
  39. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_page_condition.rb +34 -0
  40. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/event_page_graphic.rb +25 -0
  41. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/item.rb +27 -0
  42. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/map.rb +47 -0
  43. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/map_info.rb +26 -0
  44. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/me.rb +27 -0
  45. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/move_command.rb +18 -0
  46. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/move_route.rb +20 -0
  47. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/se.rb +21 -0
  48. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/skill.rb +22 -0
  49. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/state.rb +47 -0
  50. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system.rb +43 -0
  51. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system_terms.rb +53 -0
  52. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system_test_battler.rb +25 -0
  53. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/system_vehicle.rb +24 -0
  54. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop.rb +24 -0
  55. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop_member.rb +23 -0
  56. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop_page.rb +21 -0
  57. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/troop_page_condition.rb +33 -0
  58. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/usable_item.rb +87 -0
  59. data/lib/rgss_db/model/rpg_maker_data/vx/rpg/weapon.rb +31 -0
  60. data/lib/rgss_db/model/rpg_maker_data/vx/rpg.rb +59 -0
  61. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/color.rb +72 -0
  62. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/rect.rb +70 -0
  63. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/table.rb +99 -0
  64. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss/tone.rb +72 -0
  65. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rgss.rb +11 -0
  66. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/actor.rb +27 -0
  67. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/animation.rb +31 -0
  68. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/animation_frame.rb +23 -0
  69. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/animation_timing.rb +26 -0
  70. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/armor.rb +20 -0
  71. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/audio_file.rb +23 -0
  72. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/base_item.rb +31 -0
  73. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/base_item_feature.rb +29 -0
  74. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/bgm.rb +43 -0
  75. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/bgs.rb +43 -0
  76. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/class.rb +37 -0
  77. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/class_learning.rb +24 -0
  78. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/common_event.rb +33 -0
  79. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/enemy.rb +27 -0
  80. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/enemy_action.rb +26 -0
  81. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/enemy_drop_item.rb +24 -0
  82. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/equip_item.rb +19 -0
  83. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event.rb +36 -0
  84. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_command.rb +19 -0
  85. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_page.rb +35 -0
  86. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_page_condition.rb +40 -0
  87. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/event_page_graphic.rb +31 -0
  88. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/item.rb +25 -0
  89. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/map.rb +58 -0
  90. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/map_encounter.rb +23 -0
  91. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/map_info.rb +26 -0
  92. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/me.rb +27 -0
  93. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/move_command.rb +17 -0
  94. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/move_route.rb +19 -0
  95. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/se.rb +21 -0
  96. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/skill.rb +25 -0
  97. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/state.rb +34 -0
  98. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system.rb +62 -0
  99. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system_terms.rb +25 -0
  100. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system_test_battler.rb +24 -0
  101. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/system_vehicle.rb +27 -0
  102. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/tileset.rb +26 -0
  103. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop.rb +24 -0
  104. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop_member.rb +25 -0
  105. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop_page.rb +24 -0
  106. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/troop_page_condition.rb +39 -0
  107. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/usable_item.rb +84 -0
  108. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/usable_item_damage.rb +56 -0
  109. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/usable_item_effect.rb +25 -0
  110. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg/weapon.rb +25 -0
  111. data/lib/rgss_db/model/rpg_maker_data/vx_ace/rpg.rb +66 -0
  112. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/color.rb +72 -0
  113. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/rect.rb +70 -0
  114. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/table.rb +99 -0
  115. data/lib/rgss_db/model/rpg_maker_data/xp/rgss/tone.rb +72 -0
  116. data/lib/rgss_db/model/rpg_maker_data/xp/rgss.rb +11 -0
  117. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/actor.rb +44 -0
  118. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/animation.rb +28 -0
  119. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/animation_frame.rb +20 -0
  120. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/animation_timing.rb +24 -0
  121. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/armor.rb +37 -0
  122. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/audio_file.rb +23 -0
  123. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/class.rb +28 -0
  124. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/class_learning.rb +20 -0
  125. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/common_event.rb +25 -0
  126. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/enemy.rb +47 -0
  127. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/enemy_action.rb +28 -0
  128. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event.rb +36 -0
  129. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_command.rb +19 -0
  130. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_page.rb +32 -0
  131. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_page_condition.rb +30 -0
  132. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/event_page_graphic.rb +27 -0
  133. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/item.rb +48 -0
  134. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/map.rb +39 -0
  135. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/map_info.rb +26 -0
  136. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/move_command.rb +18 -0
  137. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/move_route.rb +19 -0
  138. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/skill.rb +47 -0
  139. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/state.rb +51 -0
  140. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/system.rb +56 -0
  141. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/system_test_battler.rb +25 -0
  142. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/system_words.rb +39 -0
  143. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/tileset.rb +39 -0
  144. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop.rb +24 -0
  145. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop_member.rb +23 -0
  146. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop_page.rb +21 -0
  147. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/troop_page_condition.rb +32 -0
  148. data/lib/rgss_db/model/rpg_maker_data/xp/rpg/weapon.rb +38 -0
  149. data/lib/rgss_db/model/rpg_maker_data/xp/rpg.rb +52 -0
  150. data/lib/rgss_db/model/strings.rb +607 -0
  151. data/lib/rgss_db/model/utilities.rb +90 -0
  152. data/lib/rgss_db/version.rb +7 -0
  153. data/lib/rgss_db/view/app_cli.rb +449 -0
  154. data/lib/rgss_db.rb +41 -0
  155. data/sig/rgss_db.rbs +5221 -0
  156. metadata +496 -0
@@ -0,0 +1,516 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgssDb
4
+ # Label used for data files that allows objects selection
5
+ # @return [String]
6
+ DATA_FILE_CUSTOM_LABEL = "_custom"
7
+
8
+ # RPG Maker actors data file (glob pattern)
9
+ # @return [String]
10
+ DATA_FILE_ACTORS = "Actors"
11
+
12
+ # RPG Maker animations data file (glob pattern)
13
+ # @return [String]
14
+ DATA_FILE_ANIMATIONS = "Animations"
15
+
16
+ # RPG Maker areas data file (glob pattern)
17
+ # @return [String]
18
+ DATA_FILE_AREAS = "Areas"
19
+
20
+ # RPG Maker armors data file (glob pattern)
21
+ # @return [String]
22
+ DATA_FILE_ARMORS = "Armors"
23
+
24
+ # RPG Maker classes data file (glob pattern)
25
+ # @return [String]
26
+ DATA_FILE_CLASSES = "Classes"
27
+
28
+ # RPG Maker common events data file (glob pattern)
29
+ # @return [String]
30
+ DATA_FILE_COMMON_EVENTS = "CommonEvents"
31
+
32
+ # RPG Maker enemies data file (glob pattern)
33
+ # @return [String]
34
+ DATA_FILE_ENEMIES = "Enemies"
35
+
36
+ # RPG Maker items data file (glob pattern)
37
+ # @return [String]
38
+ DATA_FILE_ITEMS = "Items"
39
+
40
+ # RPG Maker maps data file (glob pattern)
41
+ # @return [String]
42
+ DATA_FILE_MAPS = "Map[0-9][0-9][1-9]"
43
+
44
+ # RPG Maker map infos data file (glob pattern)
45
+ # @return [String]
46
+ DATA_FILE_MAP_INFOS = "MapInfos"
47
+
48
+ # RPG Maker skills data file (glob pattern)
49
+ # @return [String]
50
+ DATA_FILE_SKILLS = "Skills"
51
+
52
+ # RPG Maker states data file (glob pattern)
53
+ # @return [String]
54
+ DATA_FILE_STATES = "States"
55
+
56
+ # RPG Maker system data file (glob pattern)
57
+ # @return [String]
58
+ DATA_FILE_SYSTEM = "System"
59
+
60
+ # RPG Maker tilesets data file (glob pattern)
61
+ # @return [String]
62
+ DATA_FILE_TILESETS = "Tilesets"
63
+
64
+ # RPG Maker troops data file (glob pattern)
65
+ # @return [String]
66
+ DATA_FILE_TROOPS = "Troops"
67
+
68
+ # RPG Maker weapons data file (glob pattern)
69
+ # @return [String]
70
+ DATA_FILE_WEAPONS = "Weapons"
71
+
72
+ #
73
+ # RPG Maker base data file
74
+ #
75
+ # This class saves the object as is, without any treatment
76
+ #
77
+ class DataFile
78
+ include Comparable
79
+
80
+ # Data file type
81
+ # @return [String]
82
+ attr_reader :type
83
+
84
+ # Data file path
85
+ # @return [String]
86
+ attr_reader :file_path
87
+
88
+ # Data file object IDs list
89
+ # @return [Array<Integer>]
90
+ attr_reader :object_ids
91
+
92
+ # Data file object (not processed)
93
+ # @return [Object]
94
+ attr_reader :object
95
+
96
+ #
97
+ # Constructor
98
+ #
99
+ # @param type [String] Data file type
100
+ # @param file_path [String] Data file path
101
+ # @param object [Object] Data file object
102
+ #
103
+ def initialize(type, file_path, object)
104
+ @type = type
105
+ @file_path = file_path
106
+ @object = object
107
+ @object_ids = []
108
+ end
109
+
110
+ #
111
+ # Checks if the given file matches this data file path
112
+ #
113
+ # The check is case insensitive
114
+ #
115
+ # @param [String] file File path
116
+ #
117
+ # @return [Boolean]
118
+ #
119
+ def file_path?(file)
120
+ @file_path.casecmp?(file)
121
+ end
122
+
123
+ #
124
+ # Checks if the given file base name matches this data file base name
125
+ #
126
+ # The check is case insensitive
127
+ #
128
+ # @param file [String] File path
129
+ #
130
+ # @return [Boolean]
131
+ #
132
+ def file?(file)
133
+ File.basename(@file_path).casecmp?(File.basename(file))
134
+ end
135
+
136
+ #
137
+ # Checks if the given data type matches this data file type
138
+ #
139
+ # The check is case insensitive
140
+ #
141
+ # @param [String] data_type
142
+ #
143
+ # @return [Boolean]
144
+ #
145
+ def type?(data_type)
146
+ File.fnmatch(@type, data_type, File::FNM_CASEFOLD)
147
+ end
148
+
149
+ #
150
+ # Checks whether this data file instance supports object selection or not
151
+ #
152
+ # @return [Boolean]
153
+ #
154
+ def customizable?
155
+ !to_list.nil?
156
+ end
157
+
158
+ #
159
+ # Checks whether this data file instance is mergeable or not
160
+ #
161
+ # @return [Boolean]
162
+ #
163
+ def mergeable?
164
+ !to_merge.nil?
165
+ end
166
+
167
+ #
168
+ # Checks whether all objects are included in the serialization process
169
+ #
170
+ # @return [Boolean]
171
+ #
172
+ def all_objects?
173
+ true
174
+ end
175
+
176
+ #
177
+ # Updates the list of object IDs for this data file
178
+ #
179
+ # Any duped ID is auto. removed from the list
180
+ #
181
+ # @param object_ids [Array<Integer>]
182
+ #
183
+ def object_ids_update(*object_ids)
184
+ @object_ids = object_ids.flatten.uniq
185
+ end
186
+
187
+ #
188
+ # Clears the current list of object IDs
189
+ #
190
+ def object_ids_clear
191
+ @object_ids.clear
192
+ end
193
+
194
+ #
195
+ # Gets the data file name
196
+ #
197
+ # @return [String]
198
+ #
199
+ def file
200
+ File.basename(@file_path)
201
+ end
202
+
203
+ #
204
+ # Process the data file's file name for serialization
205
+ #
206
+ # The extension is automatically removed
207
+ #
208
+ # @return [String]
209
+ #
210
+ def serialize_file_name
211
+ base_name = File.basename(@file_path, ".*")
212
+ if all_objects?
213
+ base_name
214
+ else
215
+ base_name.concat(DATA_FILE_CUSTOM_LABEL)
216
+ end
217
+ end
218
+
219
+ #
220
+ # Merges the given data file contents with this data file
221
+ #
222
+ # @param [DataFile] data_file
223
+ #
224
+ # @raise [StandardError] Data file cannot be merged
225
+ #
226
+ def merge(data_file)
227
+ raise "cannot merge data file: '#{data_file}' because it is not supported!"
228
+ end
229
+
230
+ #
231
+ # Serializes the data file's object
232
+ #
233
+ # This method performs the necessary logic to the object for serialization
234
+ #
235
+ # By default, it returns the object as is
236
+ #
237
+ # @return [Object]
238
+ #
239
+ def serialize
240
+ @object
241
+ end
242
+
243
+ #
244
+ # Converts the given object list to object IDs for this data file
245
+ #
246
+ # The given list must be instances of this data file's contents
247
+ #
248
+ # By default it returns an empty array
249
+ #
250
+ # @param list [Array] List of objects
251
+ #
252
+ # @return [Array<Integer>]
253
+ #
254
+ def convert_list_to_ids(list)
255
+ []
256
+ end
257
+
258
+ #
259
+ # Gets a list of objects prepared to be merged
260
+ #
261
+ # Returns ``nil`` by default
262
+ #
263
+ # @return [Array<Object>]
264
+ #
265
+ def to_merge
266
+ nil
267
+ end
268
+
269
+ #
270
+ # Gets a list of objects to perform a selection
271
+ #
272
+ # If the data file does not allow this behavior it returns ``nil``
273
+ #
274
+ # Returns ``nil`` by default
275
+ #
276
+ # @return [Array<Object>]
277
+ #
278
+ def to_list
279
+ nil
280
+ end
281
+
282
+ #
283
+ # Converts this instance to a string
284
+ #
285
+ # @return [String]
286
+ #
287
+ def to_s
288
+ File.basename(@file_path)
289
+ end
290
+
291
+ #
292
+ # Comparable operator (case insensitive)
293
+ #
294
+ # @param [Object] other Other
295
+ #
296
+ # @return [Integer]
297
+ #
298
+ def <=>(other)
299
+ return @file_path.downcase <=> other.file_path.downcase if other.is_a?(DataFile)
300
+
301
+ @file_path.downcase <=> other.downcase if other.is_a?(String)
302
+ end
303
+ end
304
+
305
+ #
306
+ # RPG Maker array data file
307
+ #
308
+ # This class expects the object to be an array
309
+ #
310
+ class DataFileArray < DataFile
311
+ # Data file object (not processed)
312
+ # @return [Array]
313
+ attr_reader :object
314
+
315
+ #
316
+ # Checks whether all objects are included in the serialization process
317
+ #
318
+ # @return [Boolean]
319
+ #
320
+ def all_objects?
321
+ object_ids.empty? || object_ids.size == object.compact.size
322
+ end
323
+
324
+ #
325
+ # Merges the given data file contents with this data file
326
+ #
327
+ # @param [DataFile] data_file
328
+ #
329
+ # @raise [StandardError] Data file cannot be merged
330
+ #
331
+ def merge(data_file)
332
+ raise "cannot merge data file: '#{data_file}' because it is not supported!" unless data_file.is_a?(DataFileArray)
333
+
334
+ object.push(*data_file.to_merge)
335
+ end
336
+
337
+ #
338
+ # Serializes the data file's object
339
+ #
340
+ # This method prepares the object as an array
341
+ #
342
+ # The first element is always ``nil`` (required for RPG Maker)
343
+ #
344
+ # Object IDs list is used to filter the selected items on the data file
345
+ #
346
+ # @return [Array<Object>]
347
+ #
348
+ def serialize
349
+ # Applies the selected object IDs (if any)
350
+ processed_object = all_objects? ? object.dup : object.dup.values_at(*object_ids)
351
+
352
+ # Returns the formatted object (with a safe-check)
353
+ processed_object.first.nil? ? processed_object : processed_object.unshift(nil)
354
+ end
355
+
356
+ #
357
+ # Converts the given object list to object IDs for this data file
358
+ #
359
+ # The given list must be instances of this data file's array
360
+ #
361
+ # @param list [Array] List of objects
362
+ #
363
+ # @return [Array<Integer>]
364
+ #
365
+ def convert_list_to_ids(list)
366
+ list.map { |i| object.index(i) }
367
+ end
368
+
369
+ #
370
+ # Gets a list of objects prepared to be merged
371
+ #
372
+ # @return [Array<Object>]
373
+ #
374
+ def to_merge
375
+ object.compact
376
+ end
377
+
378
+ #
379
+ # Gets a list of objects to perform a selection
380
+ #
381
+ # @return [Array<Object>]
382
+ #
383
+ def to_list
384
+ # Data files needs to be compacted because TTY does not allow to create zero index based lists
385
+ # for some data files, the first element is nil because they are created in RPG Maker database starting at 1
386
+ # If this array is not compacted, it will cause an index mismatch later when selecting objects
387
+ object.compact
388
+ end
389
+ end
390
+
391
+ #
392
+ # RPG Maker hash data file
393
+ #
394
+ # This class expects the object to be a hash
395
+ #
396
+ class DataFileHash < DataFile
397
+ # Data file object (not processed)
398
+ # @return [Hash]
399
+ attr_reader :object
400
+
401
+ #
402
+ # Checks whether all objects are included in the serialization process
403
+ #
404
+ # @return [Boolean]
405
+ #
406
+ def all_objects?
407
+ object_ids.empty? || object.all? { |key, value| object_ids.include?(key) }
408
+ end
409
+
410
+ #
411
+ # Merges the given data file contents with this data file
412
+ #
413
+ # @param [DataFile] data_file
414
+ #
415
+ # @raise [StandardError] Data file cannot be merged
416
+ #
417
+ def merge(data_file)
418
+ raise "cannot merge data file: '#{data_file}' because it is not supported!" unless data_file.is_a?(DataFileHash)
419
+
420
+ data_file.to_merge.each_pair do |key, value|
421
+ object.store(key, value)
422
+ end
423
+ end
424
+
425
+ #
426
+ # Serializes the data file's object
427
+ #
428
+ # This method prepares the object as a hash
429
+ #
430
+ # Object IDs list is used to filter the correct
431
+ #
432
+ # @return [Hash]
433
+ #
434
+ def serialize
435
+ # Dups the original object
436
+ processed_object = object.dup
437
+
438
+ # Applies the selected object IDs (if any)
439
+ processed_object = processed_object.filter { |key, value| object_ids.include?(key) } unless all_objects?
440
+
441
+ # Returns the formatted object
442
+ processed_object
443
+ end
444
+
445
+ #
446
+ # Converts the given list to object IDs for this data file
447
+ #
448
+ # The list must be an array of this data file hash values or keys
449
+ #
450
+ # @param list [Array] List of objects
451
+ #
452
+ # @return [Array<Object>]
453
+ #
454
+ def convert_list_to_ids(list)
455
+ list.map { |i| object.key?(i) ? i : object.key(i) }
456
+ end
457
+
458
+ #
459
+ # Gets a list of objects prepared to be merged
460
+ #
461
+ # @return [Hash]
462
+ #
463
+ def to_merge
464
+ object
465
+ end
466
+
467
+ #
468
+ # Gets a list of objects to perform a selection
469
+ #
470
+ # @return [Array<Object>]
471
+ #
472
+ def to_list
473
+ # Data files needs to be compacted because TTY does not allow to create zero index based lists
474
+ # for some data files, the first element is nil because they are created in RPG Maker database starting at 1
475
+ # If this array is not compacted, it will cause an index mismatch later when auto-selecting objects
476
+ object.values
477
+ end
478
+ end
479
+
480
+ #
481
+ # RPG Maker numbered hash data file
482
+ #
483
+ # This class expects the object to be a hash
484
+ #
485
+ # This class forces hash keys to be a number for the data files:
486
+ # - Areas
487
+ # - MapInfos
488
+ #
489
+ # **Reason: Creating a DataFileHash instance from a MapInfos/Areas JSON file provokes undesired behavior.**
490
+ #
491
+ # JSON only allows key names to be strings, so all keys of the hash will be converted to string.
492
+ #
493
+ # This is undesired behavior because RPG Maker editor requires the MapInfos and Areas hash keys to be numbers.
494
+ #
495
+ # So we need to convert all keys read from the JSON file to integers when importing the JSON file into the
496
+ # RPG Maker database, hence the inclusion of this class specification from DataFileHash.
497
+ #
498
+ # Otherwise the RPG Maker editor will fail to show the maps and areas even though data still exists.
499
+ #
500
+ class DataFileHashNumber < DataFileHash
501
+ #
502
+ # Serializes the data file's object
503
+ #
504
+ # This method prepares the object as a hash
505
+ #
506
+ # Object IDs list is used to filter the correct
507
+ #
508
+ # @return [Hash]
509
+ #
510
+ def serialize
511
+ super.transform_keys do |key|
512
+ key.to_s.to_i
513
+ end
514
+ end
515
+ end
516
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./data_file"
4
+
5
+ module RgssDb
6
+ #
7
+ # Data file factory module
8
+ #
9
+ module DataFileFactory
10
+ # List of all data files types
11
+ # @return [Array<String>]
12
+ FACTORY_ALL_TYPES = [
13
+ DATA_FILE_ACTORS,
14
+ DATA_FILE_ANIMATIONS,
15
+ DATA_FILE_AREAS,
16
+ DATA_FILE_ARMORS,
17
+ DATA_FILE_CLASSES,
18
+ DATA_FILE_COMMON_EVENTS,
19
+ DATA_FILE_ENEMIES,
20
+ DATA_FILE_ITEMS,
21
+ DATA_FILE_MAP_INFOS,
22
+ DATA_FILE_MAPS,
23
+ DATA_FILE_SKILLS,
24
+ DATA_FILE_STATES,
25
+ DATA_FILE_SYSTEM,
26
+ DATA_FILE_TILESETS,
27
+ DATA_FILE_TROOPS,
28
+ DATA_FILE_WEAPONS
29
+ ].freeze
30
+
31
+ # List of data files handled using an array
32
+ #
33
+ # Some RPG Maker database files are saved as arrays (Actors, Weapons, Items...)
34
+ # @return [Array<String>]
35
+ FACTORY_ARRAY = [
36
+ DATA_FILE_ACTORS, DATA_FILE_ANIMATIONS,
37
+ DATA_FILE_ARMORS, DATA_FILE_CLASSES, DATA_FILE_COMMON_EVENTS,
38
+ DATA_FILE_ENEMIES, DATA_FILE_ITEMS, DATA_FILE_SKILLS,
39
+ DATA_FILE_STATES, DATA_FILE_TILESETS, DATA_FILE_TROOPS,
40
+ DATA_FILE_WEAPONS
41
+ ].freeze
42
+
43
+ # List of data files handled using a hash
44
+ # @return [Array<String>]
45
+ FACTORY_HASH = [].freeze
46
+
47
+ # List of data files handled using a number hash
48
+ # @return [Array<String>]
49
+ FACTORY_HASH_NUMBER = [
50
+ DATA_FILE_AREAS,
51
+ DATA_FILE_MAP_INFOS
52
+ ].freeze
53
+
54
+ #
55
+ # Creates a data file instance based on the given file entry
56
+ #
57
+ # The database file type is auto. determined using the ``data_file`` path
58
+ #
59
+ # @param data_file [String] Data file entry
60
+ # @param object [Object] Deserialized data file object
61
+ #
62
+ # @return [DataFile]
63
+ #
64
+ # @raise [StandardError] No type found
65
+ #
66
+ def self.create_data_file(data_file, object)
67
+ type = determine_data_file_type(data_file)
68
+ raise "could not find a valid data file type for the file: '#{data_file}'" if type.nil?
69
+
70
+ # Checks for a specific data file usage (bulk-check)
71
+ return DataFileArray.new(type, data_file, object) if FACTORY_ARRAY.any? { |f| f.casecmp?(type) }
72
+ return DataFileHash.new(type, data_file, object) if FACTORY_HASH.any? { |f| f.casecmp?(type) }
73
+ return DataFileHashNumber.new(type, data_file, object) if FACTORY_HASH_NUMBER.any? { |f| f.casecmp?(type) }
74
+
75
+ # Assume a base data file (map data files will use this)
76
+ DataFile.new(type, data_file, object)
77
+ end
78
+
79
+ #
80
+ # Determines the type of the data file
81
+ #
82
+ # Returns ``nil`` if a valid type cannot be found
83
+ #
84
+ # @param [String] data_file Data file entry
85
+ #
86
+ # @return [String]
87
+ #
88
+ def self.determine_data_file_type(data_file)
89
+ # Gets the data file name without extensions (and custom label, if any)
90
+ data_file_name = File.basename(data_file, ".*").gsub(DATA_FILE_CUSTOM_LABEL, "")
91
+ FACTORY_ALL_TYPES.find { |type| File.fnmatch(type, data_file_name, File::FNM_CASEFOLD) }
92
+ end
93
+ end
94
+ end