rvpacker-txt 1.3.1 → 1.5.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/Gemfile +2 -1
- data/README.md +20 -16
- data/bin/rvpacker-txt +141 -70
- data/lib/classes.rb +42 -9
- data/lib/read.rb +652 -0
- data/lib/write.rb +498 -0
- data/rvpacker-txt.gemspec +4 -5
- metadata +5 -35
- data/Rakefile +0 -1
- data/lib/serialize.rb +0 -874
- data/sig/global_variables.rbs +0 -5
- data/sig/rgss.rbs +0 -39
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2b69421e26d7a2a85ce60f482712d941e23946887a3e9b8640752dd4441b4cea
|
|
4
|
+
data.tar.gz: 66fdd2d16bbd06ae1210105684805c9ec4a2beefef7f859568ae1faa37f6051e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '068699415ee5fe5faa764a20f66f60b6d359610503aff909dda3b62b42f78c83abfe7e5049cc8aab03b7c4e5f3ff3e77a879ff43f6a059ad021bb97beed0d74d'
|
|
7
|
+
data.tar.gz: e78c574fcf21bef8a4216f856ceeea67481281fe20047e78fd7a007c2b274e2e525a5a84a98c7bfcc1db8e4113c11b71837f6cd3f756002fde0c1ad4321811e3
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -5,9 +5,9 @@ port of Ruby 1.9.x's rvpacker to Ruby 3.x to use .txt files instead of YAML, and
|
|
|
5
5
|
|
|
6
6
|
rvpacker consists of 3 parts:
|
|
7
7
|
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* classes.rb library - all necessary classes to properly load and dump RPG Maker files
|
|
9
|
+
* read.rb library - all necessary functions for reading and parsing RPG Maker files to text
|
|
10
|
+
* write.rb library - all necessary functions for writing parsed RPG Maker files back to their initial form.
|
|
11
11
|
|
|
12
12
|
# Installation
|
|
13
13
|
|
|
@@ -15,8 +15,9 @@ rvpacker consists of 3 parts:
|
|
|
15
15
|
$ gem install rvpacker-txt
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Usage
|
|
19
|
-
|
|
18
|
+
# Usage
|
|
19
|
+
|
|
20
|
+
You can get a help message on usage using `rvpacker-txt -h`.
|
|
20
21
|
|
|
21
22
|
```
|
|
22
23
|
$ rvpacker-txt -h
|
|
@@ -28,15 +29,17 @@ COMMANDS:
|
|
|
28
29
|
read - Parses RPG Maker game files to .txt
|
|
29
30
|
write - Writes parsed files back to their initial form
|
|
30
31
|
OPTIONS:
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
-
|
|
32
|
+
-i, --input-dir DIR Input directory of RPG Maker project
|
|
33
|
+
-o, --output-dir DIR Output directory of parsed/written files
|
|
34
|
+
--disable-processing FILES Don't process specified files (maps, other, system, plugins)
|
|
35
|
+
-s, --shuffle NUM Shuffle level (1: lines, 2: lines and words)
|
|
36
|
+
--disable_custom_processing Disables built-in custom parsing/writing for some games
|
|
37
|
+
-l, --log Log information while processing
|
|
38
|
+
-f, --force Force rewrite all files. Cannot be used with --append.
|
|
39
|
+
USE WITH CAUTION!
|
|
40
|
+
-a, --append When you update the rvpacker-txt, you probably should re-read your files with append, as some new text might be added to parser.
|
|
41
|
+
Cannot be used with --force
|
|
42
|
+
-h, --help Show help message
|
|
40
43
|
```
|
|
41
44
|
|
|
42
45
|
For example, to read a RPG Maker VX Ace project in E:/Documents/RPGMakerGame to .txt files:
|
|
@@ -49,7 +52,8 @@ Program determines game engine automatically.
|
|
|
49
52
|
|
|
50
53
|
This will parse all text from Data/* files into translation/maps and translation/other directories as files without
|
|
51
54
|
_trans postfix that contain original text and files with _trans postfix that contain empty lines for translation.
|
|
52
|
-
Lines from Scripts file will be parsed into translation/other/scripts.txt file as plain text
|
|
55
|
+
Lines from Scripts file will be parsed into translation/other/scripts.txt file as plain text, and
|
|
56
|
+
also into a scripts_plain.txt file that contains scripts contents as a whole - that's just for convenience.
|
|
53
57
|
|
|
54
58
|
To write previously parsed project back to its initial form:
|
|
55
59
|
|
|
@@ -80,4 +84,4 @@ https://github.com/ymaxkrapzv/rvpacker
|
|
|
80
84
|
|
|
81
85
|
Darkness9724 forked rvpacker to rvpacker-ng, ported it to Ruby 3.x and updated dependencies.
|
|
82
86
|
|
|
83
|
-
https://gitlab.com/Darkness9724/rvpacker-ng
|
|
87
|
+
https://gitlab.com/Darkness9724/rvpacker-ng
|
data/bin/rvpacker-txt
CHANGED
|
@@ -1,88 +1,159 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
3
4
|
require 'optparse'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
require 'classes'
|
|
8
|
+
require 'read'
|
|
9
|
+
require 'write'
|
|
10
|
+
|
|
11
|
+
def self.parse_options
|
|
12
|
+
options = { disable_processing: Array.new(4, false) }
|
|
13
|
+
|
|
14
|
+
OptionParser.new do |cmd|
|
|
15
|
+
cmd.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"
|
|
16
|
+
|
|
17
|
+
cmd.on('-i', '--input-dir DIR', String, 'Input directory of RPG Maker project') do |dir|
|
|
18
|
+
options[:input_dir] = File.exist?(dir) ? File.realpath(dir) : (raise "#{dir} not found")
|
|
19
|
+
options[:output_dir] = options[:input_dir]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
cmd.on('-o', '--output-dir DIR', String, 'Output directory of parsed/written files') do |dir|
|
|
23
|
+
options[:output_dir] = File.exist?(dir) ? File.realpath(dir) : (raise "#{dir} not found")
|
|
24
|
+
end
|
|
4
25
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
options = {}
|
|
11
|
-
OptionParser.new do |command|
|
|
12
|
-
command.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
|
-
command.on('-d',
|
|
15
|
-
'--input-dir DIRECTORY',
|
|
16
|
-
'Input directory of RPG Maker project.',
|
|
17
|
-
'Must contain "Data" or "original" folder to read,',
|
|
18
|
-
'and additionally "translation" with "maps" and "other" subdirectories to write.') { |dir| options[:input_dir] = dir }
|
|
19
|
-
|
|
20
|
-
command.on('--no',
|
|
21
|
-
"Don't process specified files.",
|
|
22
|
-
'Takes multiple values separated by a comma.',
|
|
23
|
-
'Allowed values: maps, other, system, plugins') do |files|
|
|
24
|
-
actual_files = files.split(',')
|
|
25
|
-
|
|
26
|
-
actual_files.each do |file|
|
|
27
|
-
case file
|
|
28
|
-
when "maps"
|
|
29
|
-
$no[0] = true
|
|
30
|
-
when "other"
|
|
31
|
-
$no[1] = true
|
|
32
|
-
when "system"
|
|
33
|
-
$no[2] = true
|
|
34
|
-
when "scripts"
|
|
35
|
-
$no[3] = true
|
|
36
|
-
else
|
|
37
|
-
puts "Wrong value for no argument: #{file}.\nAllowed values: maps, other, system, plugins"
|
|
38
|
-
exit
|
|
26
|
+
cmd.on('--disable-processing FILES', Array, 'Don\'t process specified files (maps, other, system, plugins)') do |files|
|
|
27
|
+
files.each do |file|
|
|
28
|
+
index = %w[maps other system scripts].index(file)
|
|
29
|
+
options[:disable_processing][index] = true if index
|
|
39
30
|
end
|
|
40
31
|
end
|
|
41
|
-
end
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
cmd.on('-s', '--shuffle NUM', Integer, 'Shuffle level (1: lines, 2: lines and words)') do |num|
|
|
34
|
+
options[:shuffle_level] = num
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
cmd.on('--disable_custom_processing', 'Disables built-in custom parsing/writing for some games') do
|
|
38
|
+
options[:disable_custom_processing] = true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
cmd.on('-l', '--log', 'Log information while processing') do
|
|
42
|
+
options[:logging] = true
|
|
43
|
+
end
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
cmd.on('-f', '--force', 'Force rewrite all files. Cannot be used with --append.', 'USE WITH CAUTION!') do
|
|
46
|
+
options[:force] = true
|
|
47
|
+
end
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
cmd.on('-a', '--append', 'When you update the rvpacker-txt, you probably should re-read your files with append, as some new text might be added to parser.', 'Cannot be used with --force') do
|
|
50
|
+
raise '--append cannot be used beside --force.' if options[:force]
|
|
51
|
+
options[:append] = true
|
|
52
|
+
end
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
end
|
|
54
|
+
cmd.on('-h', '--help', 'Show help message') do
|
|
55
|
+
puts cmd
|
|
56
|
+
exit
|
|
57
|
+
end
|
|
58
|
+
end.parse!
|
|
59
|
+
|
|
60
|
+
options[:action] = ARGV.shift
|
|
61
|
+
raise 'COMMAND argument is required. Use rvpacker-txt -h for help.' if options[:action].nil?
|
|
62
|
+
raise 'Invalid command. Allowed commands are: read, write.' unless %w[read write].include?(options[:action])
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
puts 'COMMAND argument is required. Use rvpacker-txt -h for help.'
|
|
61
|
-
exit
|
|
64
|
+
options
|
|
62
65
|
end
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
def self.get_game_type(system_file_path)
|
|
68
|
+
object = Marshal.load(File.binread(system_file_path))
|
|
69
|
+
game_title = object.instance_variable_get(:@game_title).to_s.downcase
|
|
70
|
+
game_title.include?('lisa') ? 'lisa' : nil
|
|
71
|
+
end
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
start_time = Time.now
|
|
74
|
+
|
|
75
|
+
options = parse_options
|
|
76
|
+
input_dir = options[:input_dir]
|
|
77
|
+
output_dir = options[:output_dir]
|
|
78
|
+
disable_custom_processing = options[:disable_custom_processing]
|
|
79
|
+
shuffle_level = options[:shuffle_level]
|
|
80
|
+
logging = options[:logging]
|
|
81
|
+
disable_processing = options[:disable_processing]
|
|
82
|
+
force = options[:force]
|
|
83
|
+
append = options[:append]
|
|
84
|
+
|
|
85
|
+
extensions = { xp: '.rxdata', vx: 'rvdata', ace: 'rvdata2' }
|
|
86
|
+
|
|
87
|
+
original_directory = Dir.glob(File.join(input_dir, '{data,original}'), File::FNM_CASEFOLD).first
|
|
88
|
+
raise '"Data" or "original" directory not found within input directory.' unless original_directory
|
|
89
|
+
|
|
90
|
+
paths = {
|
|
91
|
+
original_path: original_directory,
|
|
92
|
+
translation_path: File.join(input_dir, 'translation'),
|
|
93
|
+
maps_path: File.join(input_dir, 'translation', 'maps'),
|
|
94
|
+
other_path: File.join(input_dir, 'translation', 'other'),
|
|
95
|
+
output_path: File.join(output_dir, 'output')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
paths.each_value { |path| FileUtils.mkdir_p(path) }
|
|
99
|
+
|
|
100
|
+
engine = extensions.find do |symbol, extension|
|
|
101
|
+
symbol if File.exist?(File.join(paths[:original_path], "System.#{extension}"))
|
|
102
|
+
end || (raise "Couldn't determine project engine.")
|
|
103
|
+
|
|
104
|
+
files = Dir.glob("#{paths[:original_path]}/*#{extensions[engine]}")
|
|
105
|
+
|
|
106
|
+
maps_files_paths = []
|
|
107
|
+
other_files_paths = []
|
|
108
|
+
system_file_path = nil
|
|
109
|
+
scripts_file_path = nil
|
|
110
|
+
|
|
111
|
+
files.each do |file|
|
|
112
|
+
basename = File.basename(file)
|
|
113
|
+
|
|
114
|
+
if basename.start_with?(/Map[0-9]/)
|
|
115
|
+
maps_files_paths.push(file)
|
|
116
|
+
elsif !basename.start_with?(/Map|Tilesets|Animations|System|Scripts|Areas/)
|
|
117
|
+
other_files_paths.push(file)
|
|
118
|
+
elsif basename.start_with?('System')
|
|
119
|
+
system_file_path = file
|
|
120
|
+
elsif basename.start_with?('Scripts')
|
|
121
|
+
scripts_file_path = file
|
|
122
|
+
end
|
|
69
123
|
end
|
|
70
124
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
125
|
+
ini_file_path = File.join(input_dir, "Game.ini")
|
|
126
|
+
|
|
127
|
+
game_type = disable_custom_processing ? nil : get_game_type(system_file_path)
|
|
128
|
+
|
|
129
|
+
wait_time = 0
|
|
130
|
+
processing_type = if force
|
|
131
|
+
wait_time_start = Time.now
|
|
132
|
+
|
|
133
|
+
puts "WARNING! You\'re about to forcefully rewrite all your translation files, including _trans files.\nIf you really want to do it, make sure you've made a backup of your _trans files, if you made some changes in them already.\nInput 'Y' to continue."
|
|
134
|
+
exit unless gets.chomp == 'Y'
|
|
74
135
|
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
wait_time = Time.now - wait_time_start
|
|
137
|
+
'force'
|
|
138
|
+
else
|
|
139
|
+
append ? 'append' : 'default'
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
puts 'Custom processing for this game is enabled. Use --disable-custom-processing to disable it.' unless game_type.nil?
|
|
143
|
+
|
|
144
|
+
if options[:action] == 'read'
|
|
145
|
+
read_map(maps_files_paths, paths[:maps_path], logging, game_type, processing_type) unless disable_processing[0]
|
|
146
|
+
read_other(other_files_paths, paths[:other_path], logging, game_type, processing_type) unless disable_processing[1]
|
|
147
|
+
read_system(system_file_path, ini_file_path, paths[:other_path], logging, processing_type) unless disable_processing[2]
|
|
148
|
+
read_scripts(scripts_file_path, paths[:other_path], logging, processing_type) unless disable_processing[3]
|
|
149
|
+
else
|
|
150
|
+
write_map(maps_files_paths, paths[:maps_path], paths[:output_path], shuffle_level, logging, game_type, processing_type) unless disable_processing[0]
|
|
151
|
+
write_other(other_files_paths, paths[:other_path], paths[:output_path], shuffle_level, logging, game_type, processing_type) unless disable_processing[1]
|
|
152
|
+
write_system(system_file_path, ini_file_path, paths[:other_path], paths[:output_path], shuffle_level, logging, processing_type) unless disable_processing[2]
|
|
153
|
+
write_scripts(scripts_file_path, paths[:other_path], paths[:output_path], logging, processing_type) unless disable_processing[3]
|
|
154
|
+
end
|
|
77
155
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
elsif File.exist?(File.join(directory, original_directory, 'System.rvdata'))
|
|
81
|
-
:vx
|
|
82
|
-
elsif File.exist?(File.join(directory, original_directory, 'System.rvdata2'))
|
|
83
|
-
:ace
|
|
84
|
-
else
|
|
85
|
-
raise "Couldn't determine project engine."
|
|
86
|
-
end
|
|
156
|
+
$wait_time = 0 if $wait_time.nil?
|
|
157
|
+
end_time = Time.now - start_time - wait_time - $wait_time
|
|
87
158
|
|
|
88
|
-
|
|
159
|
+
puts "Done in #{end_time}"
|
data/lib/classes.rb
CHANGED
|
@@ -22,9 +22,7 @@ class Table
|
|
|
22
22
|
def initialize(bytes)
|
|
23
23
|
@dim, @x, @y, @z, items, *@data = bytes.unpack('L5 S*')
|
|
24
24
|
|
|
25
|
-
unless items == @data.length && @x * @y * @z == items
|
|
26
|
-
raise 'Size mismatch loading Table from data'
|
|
27
|
-
end
|
|
25
|
+
raise 'Size mismatch loading Table from data' unless items == @data.length && @x * @y * @z == items
|
|
28
26
|
end
|
|
29
27
|
|
|
30
28
|
def _dump(*_ignored)
|
|
@@ -32,7 +30,7 @@ class Table
|
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
def self._load(bytes)
|
|
35
|
-
|
|
33
|
+
new(bytes)
|
|
36
34
|
end
|
|
37
35
|
end
|
|
38
36
|
|
|
@@ -46,7 +44,7 @@ class Color
|
|
|
46
44
|
end
|
|
47
45
|
|
|
48
46
|
def self._load(bytes)
|
|
49
|
-
|
|
47
|
+
new(bytes)
|
|
50
48
|
end
|
|
51
49
|
end
|
|
52
50
|
|
|
@@ -60,7 +58,7 @@ class Tone
|
|
|
60
58
|
end
|
|
61
59
|
|
|
62
60
|
def self._load(bytes)
|
|
63
|
-
|
|
61
|
+
new(bytes)
|
|
64
62
|
end
|
|
65
63
|
end
|
|
66
64
|
|
|
@@ -74,7 +72,44 @@ class Rect
|
|
|
74
72
|
end
|
|
75
73
|
|
|
76
74
|
def self._load(bytes)
|
|
77
|
-
|
|
75
|
+
new(bytes)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Fuck using an array with set, that's just straight dumb and not efficient
|
|
80
|
+
class IndexSet
|
|
81
|
+
def initialize
|
|
82
|
+
@hash = Hash.new
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def add(item)
|
|
86
|
+
return if @hash.include?(item)
|
|
87
|
+
@hash[item] = hash.size
|
|
88
|
+
@hash
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def include?(item)
|
|
92
|
+
@hash.include?(item)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def each(&block)
|
|
96
|
+
@hash.each_key(&block)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def to_a
|
|
100
|
+
@hash.dup
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def join(delimiter = '')
|
|
104
|
+
@hash.keys.join(delimiter)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def length
|
|
108
|
+
@hash.size
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def empty?
|
|
112
|
+
@hash.empty?
|
|
78
113
|
end
|
|
79
114
|
end
|
|
80
115
|
|
|
@@ -146,5 +181,3 @@ module RGSS
|
|
|
146
181
|
process(Object, *symbol_array)
|
|
147
182
|
end
|
|
148
183
|
end
|
|
149
|
-
|
|
150
|
-
require 'serialize'
|