rvpacker-txt 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af3cb24de9b95cae720c5577b90b49e3f3f817256841e8c877fa589db3e2255a
4
- data.tar.gz: 857ae8378748e69e870fabd9ca7f0b148131250ed32fa932f2f002373eed43c2
3
+ metadata.gz: 0504a1427ffcd718aedc6a6db70bce63331ef54046b9e5abe0037d60ffbb0445
4
+ data.tar.gz: fa94b889274185fa2c6adfb1bd539ded6a8ecf7b1e05702bdf49a557376e9d7d
5
5
  SHA512:
6
- metadata.gz: dd9df69240e9b738836ed8059324ff1617c09f54b1b9f057e0c1a7ed6d6016331d29310fb1b96a79b4c95e45ee09207ecd6bb001689bd715ebbbb2742819d0a6
7
- data.tar.gz: fc7d6ab0e470b9eca55a90835367d721d8b694f1e5e581c8c95e5025bc2f3ef1f189a2e493ab26a9555ffe1f4c34d30e2376bf759052b630a46b23a3dc9919f5
6
+ metadata.gz: 9d16fa9c8cecf327cbc947250fe8b9f84b4cf0656a80d12caded68d74c2037f7971a8630469389542b8548b5737ff110aa2cdd0936eb34b822d646e3bc661a21
7
+ data.tar.gz: c0fb36404458b2fc15546c10782ca43841e9179d139e65ced2f12478345911e7d67ad2751e4f43ea7756490b032c43b34777493161f75187de51686fa7ee223d
data/README.md CHANGED
@@ -20,6 +20,8 @@ Usage
20
20
 
21
21
  ```
22
22
  $ rvpacker-txt -h
23
+ This tool allows to parse RPG Maker project to .txt files and back.
24
+
23
25
  Usage: rvpacker-txt COMMAND [options]
24
26
 
25
27
  COMMANDS:
@@ -29,15 +31,18 @@ OPTIONS:
29
31
  -d, --input-dir DIRECTORY Input directory of RPG Maker project.
30
32
  Must contain "Data" or "original" folder to read,
31
33
  and additionally "translation" with "maps" and "other" subdirectories to write.
32
- -l, --log Log information while processing.
34
+ --no Don't process specified files.
35
+ Takes multiple values separated by a comma.
36
+ Allowed values: maps, other, system, plugins
33
37
  -s, --shuffle NUMBER At value 1: Shuffles all lines in strings, at value 2: shuffles all lines and words in strings.
38
+ -l, --log Log information while processing.
34
39
  -h, --help Show help message.
35
40
  ```
36
41
 
37
42
  For example, to read a RPG Maker VX Ace project in E:/Documents/RPGMakerGame to .txt files:
38
43
 
39
44
  ```
40
- $ rvpacker read --input-dir E:/Documents/RPGMakerGame
45
+ $ rvpacker-txt read --input-dir E:/Documents/RPGMakerGame
41
46
  ```
42
47
 
43
48
  Program determines game engine automatically.
@@ -49,7 +54,7 @@ Lines from Scripts file will be parsed into translation/other/scripts.txt file a
49
54
  To write previously parsed project back to its initial form:
50
55
 
51
56
  ```
52
- $ rvpacker write --input-dir E:/Documents/RPGMakerGame
57
+ $ rvpacker-txt write --input-dir E:/Documents/RPGMakerGame
53
58
  ```
54
59
 
55
60
  This will take all of translation lines from _trans files from the translation subdirectories and repack all of them
data/bin/rvpacker-txt CHANGED
@@ -3,6 +3,8 @@ require 'RGSS'
3
3
  require 'optparse'
4
4
 
5
5
  $logging = false
6
+ $no = [true, true, true, true] # 0 is whether to process maps, 1 is other, 2 is system, 3 is scripts
7
+
6
8
  opts = {}
7
9
  OptionParser.new do |options|
8
10
  options.banner = "This tool allows to parse RPG Maker project to .txt files and back.\n\nUsage: rvpacker-txt COMMAND [options]\n\nCOMMANDS:\n read - Parses RPG Maker game files to .txt\n write - Writes parsed files back to their initial form\nOPTIONS:\n"
@@ -13,14 +15,33 @@ OptionParser.new do |options|
13
15
  opts[:input_dir] = dir
14
16
  end
15
17
 
16
- options.on('-l', '--log', 'Log information while processing.') do
17
- $logging = true
18
+ options.on('--no', "Don't process specified files.", 'Takes multiple values separated by a comma.', 'Allowed values: maps, other, system, plugins') do |files|
19
+ actual_files = files.split(',')
20
+
21
+ actual_files.each do |file|
22
+ case file
23
+ when "maps"
24
+ $no[0] = false
25
+ when "other"
26
+ $no[1] = false
27
+ when "system"
28
+ $no[2] = false
29
+ when "scripts"
30
+ $no[3] = false
31
+ else
32
+ nil
33
+ end
34
+ end
18
35
  end
19
36
 
20
37
  options.on('-s', '--shuffle NUMBER', 'At value 1: Shuffles all lines in strings, at value 2: shuffles all lines and words in strings.') do |number|
21
38
  opts[:shuffle] = number
22
39
  end
23
40
 
41
+ options.on('-l', '--log', 'Log information while processing.') do
42
+ $logging = true
43
+ end
44
+
24
45
  options.on_tail('-h', '--help', 'Show help message.') do
25
46
  puts options
26
47
  exit
@@ -44,20 +65,20 @@ project_types = { 'vx' => :vx, 'ace' => :ace, 'xp' => :xp }
44
65
  directory = opts[:input_dir]
45
66
  raise "#{directory} not found" unless File.exist?(directory)
46
67
 
47
- data_folder = Dir.foreach(directory).find { |filename| filename.downcase == 'original' }
48
- data_folder = Dir.foreach(directory).find { |filename| filename.downcase == 'data' } if data_folder.nil?
49
- raise '"Data" or "original" directory not found within input directory.' if data_folder.nil?
68
+ original_directory = Dir.foreach(directory).find { |filename| filename.downcase == 'original' } ||
69
+ Dir.foreach(directory).find { |filename| filename.downcase == 'data' }
70
+ raise '"Data" or "original" directory not found within input directory.' if original_directory.nil?
50
71
 
51
72
  types = %w[vx ace xp]
52
73
 
53
- type = types.find do |_type|
54
- case _type
74
+ type = types.find do |type_|
75
+ case type_
55
76
  when 'xp'
56
- break project_types[_type] if File.exist?(File.join(directory, data_folder, 'System.rxdata'))
77
+ break project_types[type_] if File.exist?(File.join(directory, original_directory, 'System.rxdata'))
57
78
  when 'vx'
58
- break project_types[_type] if File.exist?(File.join(directory, data_folder, 'System.rvdata'))
79
+ break project_types[type_] if File.exist?(File.join(directory, original_directory, 'System.rvdata'))
59
80
  when 'ace'
60
- break project_types[_type] if File.exist?(File.join(directory, data_folder, 'System.rvdata2'))
81
+ break project_types[type_] if File.exist?(File.join(directory, original_directory, 'System.rvdata2'))
61
82
  else
62
83
  break nil
63
84
  end
@@ -65,4 +86,4 @@ end
65
86
 
66
87
  raise 'Couldn\'t determine project engine.' if type.nil?
67
88
 
68
- RGSS.serialize(type, opts[:action], directory)
89
+ RGSS.serialize(type, opts[:action], directory, original_directory)
@@ -50,6 +50,10 @@ class IndexedSet
50
50
  def length
51
51
  @index.length
52
52
  end
53
+
54
+ def empty?
55
+ @index.empty?
56
+ end
53
57
  end
54
58
 
55
59
  module RGSS
@@ -156,11 +160,9 @@ module RGSS
156
160
  lines[0].add(parsed) unless parsed.nil?
157
161
  end
158
162
  end
159
- elsif code == 356
160
- if parameter.is_a?(String) && !parameter.empty?
161
- parsed = parse_parameter(code, parameter)
162
- lines[0].add(parsed.gsub(/\r?\n/, '\#')) unless parsed.nil?
163
- end
163
+ elsif code == 356 && parameter.is_a?(String) && !parameter.empty?
164
+ parsed = parse_parameter(code, parameter)
165
+ lines[0].add(parsed.gsub(/\r?\n/, '\#')) unless parsed.nil?
164
166
  end
165
167
  end
166
168
  end
@@ -172,9 +174,9 @@ module RGSS
172
174
  end
173
175
 
174
176
  File.write("#{output_path}/maps.txt", lines[0].join("\n"))
175
- File.write("#{output_path}/maps_trans.txt", "\n" * (lines[0].length.positive? ? lines[0].length - 1 : 0))
177
+ File.write("#{output_path}/maps_trans.txt", "\n" * (!lines[0].empty? ? lines[0].length - 1 : 0))
176
178
  File.write("#{output_path}/names.txt", lines[1].join("\n"))
177
- File.write("#{output_path}/names_trans.txt", "\n" * (lines[1].length.positive? ? lines[1].length - 1 : 0))
179
+ File.write("#{output_path}/names_trans.txt", "\n" * (!lines[1].empty? ? lines[1].length - 1 : 0))
178
180
  end
179
181
 
180
182
  def self.read_other(original_other_files, output_path)
@@ -250,7 +252,7 @@ module RGSS
250
252
  puts "Parsed #{filename}" if $logging
251
253
 
252
254
  File.write("#{output_path}/#{processed_filename}.txt", lines.join("\n"))
253
- File.write("#{output_path}/#{processed_filename}_trans.txt", "\n" * (lines.length.positive? ? lines.length - 1 : 0))
255
+ File.write("#{output_path}/#{processed_filename}_trans.txt", "\n" * (!lines.empty? ? lines.length - 1 : 0))
254
256
  end
255
257
  end
256
258
 
@@ -292,21 +294,74 @@ module RGSS
292
294
  puts "Parsed #{filename}" if $logging
293
295
 
294
296
  File.write("#{output_path}/#{basename}.txt", lines.join("\n"), mode: 'wb')
295
- File.write("#{output_path}/#{basename}_trans.txt", "\n" * (lines.length.positive? ? lines.length - 1 : 0),
297
+ File.write("#{output_path}/#{basename}_trans.txt", "\n" * (!lines.empty? ? lines.length - 1 : 0),
296
298
  mode: 'wb')
297
299
  end
298
300
 
301
+ def self.extract_quoted_strings(input)
302
+ result = []
303
+ in_quotes = false
304
+ quote_type = nil
305
+ buffer = []
306
+
307
+ input.each_char.with_index do |char, index|
308
+ if char == '#' && (index == 0 || input[index - 1] == "\n")
309
+ index = input.index("\n", index) || input.length
310
+ next
311
+ end
312
+
313
+ if char == '"' || char == "'"
314
+ if in_quotes
315
+ if char == quote_type
316
+ result.push(buffer.join)
317
+ buffer.clear
318
+ in_quotes = false
319
+ quote_type = nil
320
+ else
321
+ buffer.push(char)
322
+ end
323
+ else
324
+ in_quotes = true
325
+ quote_type = char
326
+ end
327
+
328
+ next
329
+ end
330
+
331
+ if in_quotes
332
+ if char != "\r"
333
+ if char == "\n"
334
+ buffer.push('\#')
335
+ next
336
+ end
337
+
338
+ buffer.push(char)
339
+ end
340
+ end
341
+ end
342
+
343
+ result
344
+ end
345
+
299
346
  def self.read_scripts(scripts_file_path, output_path)
300
347
  script_entries = Marshal.load(File.read(scripts_file_path, mode: 'rb'))
301
- strings = []
348
+ strings = IndexedSet.new
302
349
 
303
350
  script_entries.each do |script|
304
351
  code = Zlib::Inflate.inflate(script[2]).force_encoding('UTF-8')
305
- code.scan(/".*"/) { |string| strings.push(string) }
352
+
353
+ extract_quoted_strings(code).each do |string|
354
+ next if string.strip! || (string.empty? || string.delete('  ').empty?)
355
+
356
+ next if string.start_with?(/(#|\!?\$|@|(Graphics|Data|Audio|CG|Movies)\/)/) ||
357
+ string.match?(/^\d+$|^(.)\1{2,}$|^false|true$|^(wb|rb)$|^[A-Za-z0-9\-]+$|^[\.\(\)\+\-:;\|\[\]\^~%&!\*\/→×?\?x%▼]$|#\{|\\(?!#)|\+?=?=|\{|\}|_|r[vx]data|[<>]|\.split/) ||
358
+
359
+ strings.add(string)
360
+ end
306
361
  end
307
362
 
308
363
  File.write("#{output_path}/scripts.txt", strings.join("\n"), mode: 'wb')
309
- File.write("#{output_path}/scripts_trans.txt", "\n" * (strings.length.positive? ? strings.length - 1 : 0), mode: 'wb')
364
+ File.write("#{output_path}/scripts_trans.txt", "\n" * (!strings.empty? ? strings.length - 1 : 0), mode: 'wb')
310
365
  end
311
366
 
312
367
  def self.merge_seq(object_array)
@@ -363,7 +418,7 @@ module RGSS
363
418
  end
364
419
  end
365
420
 
366
- return object
421
+ object
367
422
  end
368
423
 
369
424
  def self.merge_other(object_array)
@@ -386,6 +441,8 @@ module RGSS
386
441
  object.instance_variable_set(:@list, merge_seq(list))
387
442
  end
388
443
  end
444
+
445
+ object_array
389
446
  end
390
447
 
391
448
  def self.get_translated(code, parameter, hashmap)
@@ -646,7 +703,7 @@ module RGSS
646
703
  File.write("#{output_path}/#{File.basename(scripts_file)}", Marshal.dump(script_entries), mode: 'wb')
647
704
  end
648
705
 
649
- def self.serialize(engine, action, directory)
706
+ def self.serialize(engine, action, directory, original_directory)
650
707
  start_time = Time.now
651
708
 
652
709
  setup_classes(engine)
@@ -654,7 +711,7 @@ module RGSS
654
711
  absolute_path = File.realpath(directory)
655
712
 
656
713
  paths = {
657
- original_path: File.join(absolute_path, 'Data'),
714
+ original_path: File.join(absolute_path, original_directory),
658
715
  translation_path: File.join(absolute_path, 'translation'),
659
716
  maps_path: File.join(absolute_path, 'translation/maps'),
660
717
  other_path: File.join(absolute_path, 'translation/other'),
@@ -690,15 +747,15 @@ module RGSS
690
747
  end
691
748
 
692
749
  if action == 'read'
693
- read_map(maps_files, paths[:maps_path])
694
- read_other(other_files, paths[:other_path])
695
- read_system(system_file, paths[:other_path])
696
- read_scripts(scripts_file, paths[:other_path])
750
+ read_map(maps_files, paths[:maps_path]) unless $no[0]
751
+ read_other(other_files, paths[:other_path]) unless $no[1]
752
+ read_system(system_file, paths[:other_path]) unless $no[2]
753
+ read_scripts(scripts_file, paths[:other_path]) unless $no[3]
697
754
  else
698
- write_map(maps_files, paths[:maps_path], paths[:output_path])
699
- write_other(other_files, paths[:other_path], paths[:output_path])
700
- write_system(system_file, paths[:other_path], paths[:output_path])
701
- write_scripts(scripts_file, paths[:other_path], paths[:output_path])
755
+ write_map(maps_files, paths[:maps_path], paths[:output_path]) unless $no[0]
756
+ write_other(other_files, paths[:other_path], paths[:output_path]) unless $no[1]
757
+ write_system(system_file, paths[:other_path], paths[:output_path]) unless $no[2]
758
+ write_scripts(scripts_file, paths[:other_path], paths[:output_path]) unless $no[3]
702
759
  end
703
760
 
704
761
  puts "Done in #{(Time.now - start_time)}"
data/lib/RGSS.rb CHANGED
@@ -17,6 +17,7 @@ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TOR
17
17
  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
18
  DEALINGS IN THE SOFTWARE.
19
19
  =end
20
+
20
21
  class Table
21
22
  def initialize(bytes)
22
23
  @dim, @x, @y, @z, items, *@data = bytes.unpack('L5 S*')
data/rvpacker-txt.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'rvpacker-txt'
3
- spec.version = '1.1.0'
3
+ spec.version = '1.2.0'
4
4
  spec.authors = ['Howard Jeng', 'Andrew Kesterson', 'Solistra', 'Darkness9724', 'savannstm']
5
5
  spec.email = ['savannstm@gmail.com']
6
6
  spec.summary = 'Reads or writes RPG Maker XP/VX/VXAce game text to .txt files'
data/sig/rgss.rbs CHANGED
@@ -21,7 +21,7 @@ module RGSS
21
21
 
22
22
  def self.read_scripts: (String, String) -> void
23
23
 
24
- def self.serialize: (Symbol, String, String) -> void
24
+ def self.serialize: (Symbol, String, String, String) -> void
25
25
 
26
26
  def self.write_map: (Array[String], String, String) -> void
27
27
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rvpacker-txt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Howard Jeng
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2024-07-02 00:00:00.000000000 Z
15
+ date: 2024-07-03 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bundler