rvpacker-txt 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.
data/lib/RGSS.rb ADDED
@@ -0,0 +1,409 @@
1
+ =begin
2
+ Copyright (c) 2013 Howard Jeng
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
5
+ software and associated documentation files (the "Software"), to deal in the Software
6
+ without restriction, including without limitation the rights to use, copy, modify, merge,
7
+ publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
8
+ to whom the Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all copies or
11
+ substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
15
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
16
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
+ DEALINGS IN THE SOFTWARE.
19
+ =end
20
+
21
+ require 'scanf'
22
+
23
+ class Table
24
+ def initialize(bytes)
25
+ @dim, @x, @y, @z, items, *@data = bytes.unpack('L5 S*')
26
+ unless items == @data.length
27
+ raise 'Size mismatch loading Table from data'
28
+ end
29
+ unless @x * @y * @z == items
30
+ raise 'Size mismatch loading Table from data'
31
+ end
32
+ end
33
+
34
+ MAX_ROW_LENGTH = 20
35
+
36
+ def encode_with(coder)
37
+ coder.style = Psych::Nodes::Mapping::BLOCK
38
+
39
+ coder['dim'] = @dim
40
+ coder['x'] = @x
41
+ coder['y'] = @y
42
+ coder['z'] = @z
43
+
44
+ if @x * @y * @z > 0
45
+ stride = @x < 2 ? (@y < 2 ? @z : @y) : @x
46
+ rows = @data.each_slice(stride).to_a
47
+ if MAX_ROW_LENGTH != -1 && stride > MAX_ROW_LENGTH
48
+ block_length = (stride + MAX_ROW_LENGTH - 1) / MAX_ROW_LENGTH
49
+ row_length = (stride + block_length - 1) / block_length
50
+ rows =
51
+ rows
52
+ .collect { |x| x.each_slice(row_length).to_a }
53
+ .flatten(1)
54
+ end
55
+ rows = rows.collect { |x| x.collect { |y| '%04x' % y }.join(' ') }
56
+ coder['data'] = rows
57
+ else
58
+ coder['data'] = []
59
+ end
60
+ end
61
+
62
+ def init_with(coder)
63
+ @dim = coder['dim']
64
+ @x = coder['x']
65
+ @y = coder['y']
66
+ @z = coder['z']
67
+ @data =
68
+ coder['data'].collect { |x| x.split(' ').collect(&:hex) }.flatten
69
+ items = @x * @y * @z
70
+ unless items == @data.length
71
+ raise 'Size mismatch loading Table from YAML'
72
+ end
73
+ end
74
+
75
+ def _dump(*ignored)
76
+ return [@dim, @x, @y, @z, @x * @y * @z, *@data].pack('L5 S*')
77
+ end
78
+
79
+ def self._load(bytes)
80
+ Table.new(bytes)
81
+ end
82
+ end
83
+
84
+ class Color
85
+ def initialize(bytes)
86
+ @r, @g, @b, @a = *bytes.unpack('D4')
87
+ end
88
+
89
+ def _dump(*ignored)
90
+ return [@r, @g, @b, @a].pack('D4')
91
+ end
92
+
93
+ def self._load(bytes)
94
+ Color.new(bytes)
95
+ end
96
+ end
97
+
98
+ class Tone
99
+ def initialize(bytes)
100
+ @r, @g, @b, @a = *bytes.unpack('D4')
101
+ end
102
+
103
+ def _dump(*ignored)
104
+ return [@r, @g, @b, @a].pack('D4')
105
+ end
106
+
107
+ def self._load(bytes)
108
+ Tone.new(bytes)
109
+ end
110
+ end
111
+
112
+ class Rect
113
+ def initialize(bytes)
114
+ @x, @y, @width, @height = *bytes.unpack('i4')
115
+ end
116
+
117
+ def _dump(*ignored)
118
+ return [@x, @y, @width, @height].pack('i4')
119
+ end
120
+
121
+ def self._load(bytes)
122
+ Rect.new(bytes)
123
+ end
124
+ end
125
+
126
+ module RGSS
127
+ def self.remove_defined_method(scope, name)
128
+ if scope.instance_methods(false).include?(name)
129
+ scope.send(:remove_method, name)
130
+ end
131
+ end
132
+
133
+ def self.reset_method(scope, name, method)
134
+ remove_defined_method(scope, name)
135
+ scope.send(:define_method, name, method)
136
+ end
137
+
138
+ def self.reset_const(scope, sym, value)
139
+ scope.send(:remove_const, sym) if scope.const_defined?(sym)
140
+ scope.send(:const_set, sym, value)
141
+ end
142
+
143
+ def self.array_to_hash(arr, &block)
144
+ h = {}
145
+ arr.each_with_index do |val, index|
146
+ r = block_given? ? block.call(val) : val
147
+ h[index] = r unless r.nil?
148
+ end
149
+ if arr.length > 0
150
+ last = arr.length - 1
151
+ h[last] = nil unless h.has_key?(last)
152
+ end
153
+ return h
154
+ end
155
+
156
+ def self.hash_to_array(hash)
157
+ arr = []
158
+ hash.each { |k, v| arr[k] = v }
159
+ return arr
160
+ end
161
+
162
+ require 'RGSS/BasicCoder'
163
+ require 'RPG'
164
+
165
+ # creates an empty class in a potentially nested scope
166
+ def self.process(root, name, *args)
167
+ if args.length > 0
168
+ process(root.const_get(name), *args)
169
+ else
170
+ unless root.const_defined?(name, false)
171
+ root.const_set(name, Class.new)
172
+ end
173
+ end
174
+ end
175
+
176
+ # other classes that don't need definitions
177
+ [
178
+ # RGSS data structures
179
+ %i[RPG Actor],
180
+ %i[RPG Animation],
181
+ %i[RPG Animation Frame],
182
+ %i[RPG Animation Timing],
183
+ %i[RPG Area],
184
+ %i[RPG Armor],
185
+ %i[RPG AudioFile],
186
+ %i[RPG BaseItem],
187
+ %i[RPG BaseItem Feature],
188
+ %i[RPG BGM],
189
+ %i[RPG BGS],
190
+ %i[RPG Class],
191
+ %i[RPG Class Learning],
192
+ %i[RPG CommonEvent],
193
+ %i[RPG Enemy],
194
+ %i[RPG Enemy Action],
195
+ %i[RPG Enemy DropItem],
196
+ %i[RPG EquipItem],
197
+ %i[RPG Event],
198
+ %i[RPG Event Page],
199
+ %i[RPG Event Page Condition],
200
+ %i[RPG Event Page Graphic],
201
+ %i[RPG Item],
202
+ %i[RPG Map],
203
+ %i[RPG Map Encounter],
204
+ %i[RPG MapInfo],
205
+ %i[RPG ME],
206
+ %i[RPG MoveCommand],
207
+ %i[RPG MoveRoute],
208
+ %i[RPG SE],
209
+ %i[RPG Skill],
210
+ %i[RPG State],
211
+ %i[RPG System Terms],
212
+ %i[RPG System TestBattler],
213
+ %i[RPG System Vehicle],
214
+ %i[RPG System Words],
215
+ %i[RPG Tileset],
216
+ %i[RPG Troop],
217
+ %i[RPG Troop Member],
218
+ %i[RPG Troop Page],
219
+ %i[RPG Troop Page Condition],
220
+ %i[RPG UsableItem],
221
+ %i[RPG UsableItem Damage],
222
+ %i[RPG UsableItem Effect],
223
+ %i[RPG Weapon],
224
+ # Script classes serialized in save game files
225
+ [:Game_ActionResult],
226
+ [:Game_Actor],
227
+ [:Game_Actors],
228
+ [:Game_BaseItem],
229
+ [:Game_BattleAction],
230
+ [:Game_CommonEvent],
231
+ [:Game_Enemy],
232
+ [:Game_Event],
233
+ [:Game_Follower],
234
+ [:Game_Followers],
235
+ [:Game_Interpreter],
236
+ [:Game_Map],
237
+ [:Game_Message],
238
+ [:Game_Party],
239
+ [:Game_Picture],
240
+ [:Game_Pictures],
241
+ [:Game_Player],
242
+ [:Game_System],
243
+ [:Game_Timer],
244
+ [:Game_Troop],
245
+ [:Game_Screen],
246
+ [:Game_Vehicle],
247
+ [:Interpreter]
248
+ ].each { |x| process(Object, *x) }
249
+
250
+ def self.setup_system(version, options)
251
+ # convert variable and switch name arrays to a hash when serialized
252
+ # if round_trip isn't set change version_id to fixed number
253
+ if options[:round_trip]
254
+ iso = ->(val) { return val }
255
+ reset_method(RPG::System, :reduce_string, iso)
256
+ reset_method(RPG::System, :map_version, iso)
257
+ reset_method(Game_System, :map_version, iso)
258
+ else
259
+ reset_method(
260
+ RPG::System,
261
+ :reduce_string,
262
+ ->(str) do
263
+ return nil if str.nil?
264
+ stripped = str.strip
265
+ return stripped.empty? ? nil : stripped
266
+ end
267
+ )
268
+
269
+ # These magic numbers should be different. If they are the same, the saved version
270
+ # of the map in save files will be used instead of any updated version of the map
271
+ reset_method(
272
+ RPG::System,
273
+ :map_version,
274
+ ->(ignored) { return 12_345_678 }
275
+ )
276
+ reset_method(
277
+ Game_System,
278
+ :map_version,
279
+ ->(ignored) { return 87_654_321 }
280
+ )
281
+ end
282
+ end
283
+
284
+ def self.setup_interpreter(version)
285
+ # Game_Interpreter is marshalled differently in VX Ace
286
+ if version == :ace
287
+ reset_method(Game_Interpreter, :marshal_dump, -> { return @data })
288
+ reset_method(
289
+ Game_Interpreter,
290
+ :marshal_load,
291
+ ->(obj) { @data = obj }
292
+ )
293
+ else
294
+ remove_defined_method(Game_Interpreter, :marshal_dump)
295
+ remove_defined_method(Game_Interpreter, :marshal_load)
296
+ end
297
+ end
298
+
299
+ def self.setup_event_command(version, options)
300
+ # format event commands to flow style for the event codes that aren't move commands
301
+ if options[:round_trip]
302
+ reset_method(RPG::EventCommand, :clean, -> {})
303
+ else
304
+ reset_method(
305
+ RPG::EventCommand,
306
+ :clean,
307
+ -> { @parameters[0].rstrip! if @code == 401 }
308
+ )
309
+ end
310
+ reset_const(
311
+ RPG::EventCommand,
312
+ :MOVE_LIST_CODE,
313
+ version == :xp ? 209 : 205
314
+ )
315
+ end
316
+
317
+ def self.setup_classes(version, options)
318
+ setup_system(version, options)
319
+ setup_interpreter(version)
320
+ setup_event_command(version, options)
321
+ BasicCoder.set_ivars_methods(version)
322
+ end
323
+
324
+ FLOW_CLASSES = [Color, Tone, RPG::BGM, RPG::BGS, RPG::MoveCommand, RPG::SE]
325
+
326
+ SCRIPTS_BASE = 'Scripts'
327
+
328
+ ACE_DATA_EXT = '.rvdata2'
329
+ VX_DATA_EXT = '.rvdata'
330
+ XP_DATA_EXT = '.rxdata'
331
+ YAML_EXT = '.yaml'
332
+ RUBY_EXT = '.rb'
333
+
334
+ def self.get_data_directory(base)
335
+ return File.join(base, 'Data')
336
+ end
337
+
338
+ def self.get_yaml_directory(base)
339
+ return File.join(base, 'YAML')
340
+ end
341
+
342
+ def self.get_script_directory(base)
343
+ return File.join(base, 'Scripts')
344
+ end
345
+
346
+ class Game_Switches
347
+ include RGSS::BasicCoder
348
+
349
+ def encode(name, value)
350
+ return array_to_hash(value)
351
+ end
352
+
353
+ def decode(name, value)
354
+ return hash_to_array(value)
355
+ end
356
+ end
357
+
358
+ class Game_Variables
359
+ include RGSS::BasicCoder
360
+
361
+ def encode(name, value)
362
+ return array_to_hash(value)
363
+ end
364
+
365
+ def decode(name, value)
366
+ return hash_to_array(value)
367
+ end
368
+ end
369
+
370
+ class Game_SelfSwitches
371
+ include RGSS::BasicCoder
372
+
373
+ def encode(name, value)
374
+ return(
375
+ Hash[
376
+ value.collect do |pair|
377
+ key, value = pair
378
+ next ['%03d %03d %s' % key, value]
379
+ end
380
+ ]
381
+ )
382
+ end
383
+
384
+ def decode(name, value)
385
+ return(
386
+ Hash[
387
+ value.collect do |pair|
388
+ key, value = pair
389
+ next [key.scanf('%d %d %s'), value]
390
+ end
391
+ ]
392
+ )
393
+ end
394
+ end
395
+
396
+ class Game_System
397
+ include RGSS::BasicCoder
398
+
399
+ def encode(name, value)
400
+ if name == 'version_id'
401
+ return map_version(value)
402
+ else
403
+ return value
404
+ end
405
+ end
406
+ end
407
+
408
+ require 'RGSS/serialize'
409
+ end
data/lib/RPG.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'RGSS'
2
+ module RPG
3
+ class System
4
+ include RGSS::BasicCoder
5
+ HASHED_VARS = %w[variables switches]
6
+ end
7
+
8
+ def self.array_to_hash(arr, &block)
9
+ h = {}
10
+ arr.each_with_index do |val, index|
11
+ r = block_given? ? block.call(val) : val
12
+ h[index] = r unless r.nil?
13
+ end
14
+ if arr.length > 0
15
+ last = arr.length - 1
16
+ h[last] = nil unless h.has_key?(last)
17
+ end
18
+ return h
19
+ end
20
+
21
+ def encode(name, value)
22
+ if HASHED_VARS.include?(name)
23
+ return array_to_hash(value) { |val| reduce_string(val) }
24
+ elsif name == 'version_id'
25
+ return map_version(value)
26
+ else
27
+ return value
28
+ end
29
+ end
30
+
31
+ def decode(name, value)
32
+ if HASHED_VARS.include?(name)
33
+ return hash_to_array(value)
34
+ else
35
+ return value
36
+ end
37
+ end
38
+
39
+ class EventCommand
40
+ def encode_with(coder)
41
+ case @code
42
+ when MOVE_LIST_CODE
43
+ # move list
44
+ coder.style = Psych::Nodes::Mapping::BLOCK
45
+ else
46
+ coder.style = Psych::Nodes::Mapping::FLOW
47
+ end
48
+ coder['i'], coder['c'], coder['p'] = @indent, @code, @parameters
49
+ end
50
+
51
+ def init_with(coder)
52
+ @indent, @code, @parameters = coder['i'], coder['c'], coder['p']
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module RVPACKER
2
+ VERSION = '1.3.2'.freeze
3
+ end
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'rvpacker-txt'
3
+ spec.version = '1.0.0'
4
+ spec.authors = ['Howard Jeng', 'Andrew Kesterson', 'Solistra', 'Darkness9724', 'savannstm']
5
+ spec.email = ['savannstm@gmail.com']
6
+ spec.summary = 'Reads or writes RPG Maker XP/VX/VXAce game text to .txt files'
7
+ spec.homepage = 'https://github.com/savannstm/rvpacker-txt'
8
+ spec.license = 'MIT'
9
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
10
+
11
+ spec.files = `git ls-files -z`.split("\x0")
12
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
13
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
+ spec.require_paths = ['lib']
15
+
16
+ spec.add_development_dependency 'bundler', '>= 2.5.14'
17
+ spec.add_development_dependency 'rake', '>= 13.0.6'
18
+ spec.add_dependency 'scanf', '>= 1.0.0'
19
+ end
data/sig/rgss.rbs ADDED
@@ -0,0 +1,33 @@
1
+ module RGSS
2
+ def self.get_game_type: (String) -> (String | nil)
3
+
4
+ def self.get_translated: (Integer, String, Hash[String, String]) -> (String | nil)
5
+
6
+ def self.get_variable_translated: (String) -> (String | nil)
7
+
8
+ def self.merge_map: (Object) -> Object
9
+
10
+ def self.merge_other: (Array[Object]) -> Array[Object]
11
+
12
+ def self.parse_parameter: (Integer, String) -> (String | nil)
13
+
14
+ def self.parse_variable: (String) -> (String | nil)
15
+
16
+ def self.read_map: (Array[String], String) -> void
17
+
18
+ def self.read_other: (Array[String], String) -> void
19
+
20
+ def self.read_system: (String, String) -> void
21
+
22
+ def self.read_scripts: (String, String) -> void
23
+
24
+ def self.serialize: (Symbol, string, string, Hash[untyped, untyped]) -> void
25
+
26
+ def self.write_map: (String, Array[String], String) -> void
27
+
28
+ def self.write_other: (String, Array[String], String) -> void
29
+
30
+ def self.write_system: (String, String, String) -> void
31
+
32
+ def self.write_scripts: (String, String, String) -> void
33
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rvpacker-txt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Howard Jeng
8
+ - Andrew Kesterson
9
+ - Solistra
10
+ - Darkness9724
11
+ - savannstm
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2024-07-01 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: bundler
19
+ requirement: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.5.14
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 2.5.14
31
+ - !ruby/object:Gem::Dependency
32
+ name: rake
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: 13.0.6
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 13.0.6
45
+ - !ruby/object:Gem::Dependency
46
+ name: scanf
47
+ requirement: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 1.0.0
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 1.0.0
59
+ description:
60
+ email:
61
+ - savannstm@gmail.com
62
+ executables:
63
+ - rvpacker-txt
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - Gemfile
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - bin/rvpacker-txt
72
+ - lib/RGSS.rb
73
+ - lib/RGSS/BasicCoder.rb
74
+ - lib/RGSS/serialize.rb
75
+ - lib/RPG.rb
76
+ - lib/rvpacker/version.rb
77
+ - rvpacker-txt.gemspec
78
+ - sig/rgss.rbs
79
+ homepage: https://github.com/savannstm/rvpacker-txt
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 3.0.0
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.5.14
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Reads or writes RPG Maker XP/VX/VXAce game text to .txt files
102
+ test_files: []