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 +4 -4
- data/README.md +8 -3
- data/bin/rvpacker-txt +32 -11
- data/lib/RGSS/serialize.rb +80 -23
- data/lib/RGSS.rb +1 -0
- data/rvpacker-txt.gemspec +1 -1
- data/sig/rgss.rbs +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0504a1427ffcd718aedc6a6db70bce63331ef54046b9e5abe0037d60ffbb0445
|
|
4
|
+
data.tar.gz: fa94b889274185fa2c6adfb1bd539ded6a8ecf7b1e05702bdf49a557376e9d7d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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('
|
|
17
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
raise '"Data" or "original" directory not found within input directory.' if
|
|
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 |
|
|
54
|
-
case
|
|
74
|
+
type = types.find do |type_|
|
|
75
|
+
case type_
|
|
55
76
|
when 'xp'
|
|
56
|
-
break project_types[
|
|
77
|
+
break project_types[type_] if File.exist?(File.join(directory, original_directory, 'System.rxdata'))
|
|
57
78
|
when 'vx'
|
|
58
|
-
break project_types[
|
|
79
|
+
break project_types[type_] if File.exist?(File.join(directory, original_directory, 'System.rvdata'))
|
|
59
80
|
when 'ace'
|
|
60
|
-
break project_types[
|
|
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)
|
data/lib/RGSS/serialize.rb
CHANGED
|
@@ -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
|
-
|
|
161
|
-
|
|
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].
|
|
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].
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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.
|
|
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
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.
|
|
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-
|
|
15
|
+
date: 2024-07-03 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
18
18
|
name: bundler
|