rvpacker-txt 1.9.4 → 1.11.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: c57413528c8aa902963d9df851562c6dab33d8edbcdd8e19ef2c5dd0a3f5fbf0
4
- data.tar.gz: 0aec862409028ee0f116a2ea98d08104c97bd3027969dd3ac830dbdbcf576c88
3
+ metadata.gz: 0be6dfc912a9d15dd4be7c37ecee0c316d650ca10f89eb99af19d5baf38addf2
4
+ data.tar.gz: a0ed09eac3d11c36db6d9014e4c0bc6ffa2408ac8c4a78f55fdfbb08285b759a
5
5
  SHA512:
6
- metadata.gz: 7a31f9ba7db0bd30345637c7701282191d842d053ccf38355331e1375f270fb6558fbfae4b2378174655c8968f5edba97354c2cee05ff580760c260db149c8e9
7
- data.tar.gz: 2af993afb94e8d29705014bba95f655c26eec161da56f5715f9e7a069231e57456cd37b01678bd8de1148ac5f2d5858ff6c5b759902916eeb151569c2de9cc41
6
+ metadata.gz: bfc00222eff1dc676c73e62bc9048a89a4ea01fdce63eda1e7373a8d4f5a4d9975418111844704127cae24f2d01848d8486ba544f8f2de409346801f9563325c
7
+ data.tar.gz: 473d0707b8359f54dd49ed665addf7cbfedf4a80ccadfaf6f7d997db9e4f691ae05a4882187a5dad3c8a6dc37231c11efb6e997a573bd89a70bc3f366f6e8695
data/README.md CHANGED
@@ -36,10 +36,11 @@ OPTIONS:
36
36
  --disable-processing FILES Skips processing specified files.
37
37
  Example: --disable-processing=maps,other,system.
38
38
  [Allowed values: maps, other, system, scripts]
39
- --disable-custom-processing Disables built-in custom parsing/writing for some games.
40
- -r, --romanize When reading: If you parsing text from a Japanese game, that contains symbols like 「」,
41
- which are just the Japanese quotation marks, it automatically replaces these symbols by their roman equivalents.
42
- When writing: Use to correctly write files back if you have parsed them with --romanize flag.
39
+ --disable-custom-processing Disables built-in custom text processing for some games.
40
+ This flag will automatically be used when writing if you parsed game text with it.
41
+ -r, --romanize If you parsing text from a Japanese game, that contains symbols like 「」, which are just the Japanese quotation marks,
42
+ it automatically replaces these symbols by their roman equivalents (in this case, "").
43
+ This flag will automatically be used when writing if you parsed game text with it.
43
44
  -l, --log Enables logging.
44
45
  -h, --help Prints the program's help message or for the entered subcommand.
45
46
  ```
data/bin/rvpacker-txt CHANGED
@@ -43,29 +43,22 @@ def self.parse_options
43
43
 
44
44
  banner,
45
45
  input_dir_description,
46
- output_dir_description,
47
- romanize_description =
46
+ output_dir_description, =
48
47
  case options[:action]
49
48
  when 'read'
50
49
  ["#{read_command_description}\n\nOPTIONS:\n",
51
50
  ['Input directory, containing folders "original" or "data" with original game files.'],
52
- ['Output directory, where a "translation" folder will be created, containing parsed .txt files with the text from the game.'],
53
- ['If you parsing text from a Japanese game, that contains symbols like 「」, which are just the Japanese quotation marks,',
54
- 'it automatically replaces these symbols by their roman equivalents.']]
51
+ ['Output directory, where a "translation" folder will be created, containing parsed .txt files with the text from the game.']]
55
52
  when 'write'
56
53
  ["#{write_command_description}\n\nOPTIONS:\n",
57
54
  ['Input directory, containing folders "original" or "data" and "translation" with original game files and .txt files with translation respectively.'],
58
- ['Output directory, where an "output" folder will be created, containing compiled RPG Maker files with your translation.'],
59
- ['Use to correctly write files back if you have parsed them with --romanize flag.']]
55
+ ['Output directory, where an "output" folder will be created, containing compiled RPG Maker files with your translation.']]
60
56
  else
61
57
  [banner_text,
62
58
  ['When reading: Input directory, containing folders "original" or "data" with original game files.',
63
59
  'When writing: Input directory, containing folders "original" or "data" and "translation" with original game files and .txt files with translation respectively.'],
64
60
  ['When reading: Output directory, where a "translation" folder will be created, containing parsed .txt files with the text from the game.',
65
- 'When writing: Output directory, where an "output" folder will be created, containing compiled RPG Maker files with your translation.'],
66
- ['When reading: If you parsing text from a Japanese game, that contains symbols like 「」,',
67
- 'which are just the Japanese quotation marks, it automatically replaces these symbols by their roman equivalents.',
68
- 'When writing: Use to correctly write files back if you have parsed them with --romanize flag.']]
61
+ 'When writing: Output directory, where an "output" folder will be created, containing compiled RPG Maker files with your translation.']]
69
62
  end
70
63
 
71
64
  OptionParser.new(banner) do |cmd|
@@ -92,12 +85,15 @@ def self.parse_options
92
85
  end
93
86
 
94
87
  cmd.on('--disable-custom-processing',
95
- 'Disables built-in custom parsing/writing for some games.') do
88
+ 'Disables built-in custom text processing for some games.',
89
+ 'This flag will automatically be used when writing if you parsed game text with it.') do
96
90
  options[:disable_custom_processing] = true
97
91
  end
98
92
 
99
93
  cmd.on('-r', '--romanize',
100
- *romanize_description) do
94
+ 'If you parsing text from a Japanese game, that contains symbols like 「」, which are just the Japanese quotation marks,',
95
+ 'it automatically replaces these symbols by their roman equivalents (in this case, "").',
96
+ 'This flag will automatically be used when writing if you parsed game text with it.') do
101
97
  options[:romanize] = true
102
98
  end
103
99
 
@@ -110,7 +106,7 @@ def self.parse_options
110
106
 
111
107
  cmd.on('-a', '--append',
112
108
  "When the rvpacker-txt or the game which files you've parsed receives an update, you probably should re-read game files with --append,",
113
- ' which will append any new text to your files without overwriting the progress.',
109
+ 'which will append any new text to your files without overwriting the progress.',
114
110
  'Cannot be used with --force.') do
115
111
  raise '--append cannot be used with --force.' if options[:force]
116
112
  options[:append] = true
@@ -170,6 +166,7 @@ force = options[:force]
170
166
  append = options[:append]
171
167
  # @type [Boolean]
172
168
  romanize = options[:romanize]
169
+ # @type [Boolean]
173
170
  silent = options[:silent]
174
171
 
175
172
  extensions = { xp: 'rxdata', vx: 'rvdata', ace: 'rvdata2' }
@@ -179,6 +176,7 @@ raise '"Data" or "original" directory not found within input directory.' unless
179
176
 
180
177
  maps_path = File.join(input_path, 'translation', 'maps')
181
178
  other_path = File.join(input_path, 'translation', 'other')
179
+ metadata_file_path = File.join(input_path, 'translation', '.rvpacker-txt-metadata.marshal')
182
180
 
183
181
  FileUtils.mkdir_p(maps_path)
184
182
  FileUtils.mkdir_p(other_path)
@@ -220,7 +218,7 @@ if options[:action] == 'read'
220
218
  require 'read'
221
219
 
222
220
  processing_mode = if force
223
- unless options[:silent]
221
+ unless silent
224
222
  wait_time_start = Time.now
225
223
 
226
224
  puts "WARNING! You're about to forcefully rewrite all your translation files, including _trans files.",
@@ -237,6 +235,8 @@ if options[:action] == 'read'
237
235
  :default
238
236
  end
239
237
 
238
+ File.binwrite(metadata_file_path, Marshal.dump({ romanize: romanize, disable_custom_processing: disable_custom_processing }))
239
+
240
240
  read_map(maps_files_paths, maps_path, romanize, logging, game_type, processing_mode) unless disable_processing[:maps]
241
241
  read_other(other_files_paths, other_path, romanize, logging, game_type, processing_mode) unless disable_processing[:other]
242
242
  read_system(system_file_path, ini_file_path, other_path, romanize, logging, processing_mode) unless disable_processing[:system]
@@ -247,6 +247,20 @@ else
247
247
  output_path = File.join(output_path, 'output')
248
248
  FileUtils.mkdir_p(output_path)
249
249
 
250
+ if File.exist?(metadata_file_path)
251
+ metadata = Marshal.load(File.binread(metadata_file_path))
252
+
253
+ if metadata[:romanize]
254
+ puts 'Enabling romanize according to the metadata from previous read.'
255
+ romanize = metadata[:romanize]
256
+ end
257
+
258
+ if metadata[:disable_custom_processing] && !game_type.nil?
259
+ puts 'Disabling custom processing according to the metadata from previous read.'
260
+ game_type = nil
261
+ end
262
+ end
263
+
250
264
  write_map(maps_files_paths, maps_path, output_path, shuffle_level, romanize, logging, game_type) unless disable_processing[:maps]
251
265
  write_other(other_files_paths, other_path, output_path, shuffle_level, romanize, logging, game_type) unless disable_processing[:other]
252
266
  write_system(system_file_path, ini_file_path, other_path, output_path, shuffle_level, romanize, logging) unless disable_processing[:system]
data/lib/classes.rb CHANGED
@@ -112,6 +112,16 @@ class IndexSet
112
112
  end
113
113
  end
114
114
 
115
+ class Hash
116
+ def insert_at_index(index, key, value)
117
+ return self[key] = value if index >= size
118
+
119
+ temp_array = to_a
120
+ temp_array.insert(index, [key, value])
121
+ replace(temp_array.to_h)
122
+ end
123
+ end
124
+
115
125
  module RPG
116
126
  class Map
117
127
  attr_accessor :display_name, :events
data/lib/extensions.rb CHANGED
@@ -7,13 +7,13 @@ def self.romanize_string(string)
7
7
  case char
8
8
  when '。'
9
9
  string[i] = '.'
10
- when '、'
10
+ when '、', ','
11
11
  string[i] = ','
12
12
  when '・'
13
13
  string[i] = '·'
14
14
  when '゠'
15
15
  string[i] = '–'
16
- when '='
16
+ when '=', 'ー'
17
17
  string[i] = '—'
18
18
  when '…', '‥'
19
19
  string[i, 3] = '...'
@@ -41,6 +41,74 @@ def self.romanize_string(string)
41
41
  string[i] = ':'
42
42
  when '!'
43
43
  string[i] = '!'
44
+ when '※'
45
+ string[i] = '*'
46
+ when ' '
47
+ string[i] = ' '
48
+ when 'Ⅰ'
49
+ string[i] = 'I'
50
+ when 'ⅰ'
51
+ string[i] = 'i'
52
+ when 'Ⅱ'
53
+ string[i, 2] = 'II'
54
+ when 'ⅱ'
55
+ string[i, 2] = 'ii'
56
+ when 'Ⅲ'
57
+ string[i, 3] = 'III'
58
+ when 'ⅲ'
59
+ string[i, 3] = 'iii'
60
+ when 'Ⅳ'
61
+ string[i, 2] = 'IV'
62
+ when 'ⅳ'
63
+ string[i, 2] = 'iv'
64
+ when 'Ⅴ'
65
+ string[i] = 'V'
66
+ when 'ⅴ'
67
+ string[i] = 'v'
68
+ when 'Ⅵ'
69
+ string[i, 2] = 'VI'
70
+ when 'ⅵ'
71
+ string[i, 2] = 'vi'
72
+ when 'Ⅶ'
73
+ string[i, 3] = 'VII'
74
+ when 'ⅶ'
75
+ string[i, 3] = 'vii'
76
+ when 'Ⅷ'
77
+ string[i, 4] = 'VIII'
78
+ when 'ⅷ'
79
+ string[i, 4] = 'viii'
80
+ when 'Ⅸ'
81
+ string[i, 2] = 'IX'
82
+ when 'ⅸ'
83
+ string[i, 2] = 'ix'
84
+ when 'Ⅹ'
85
+ string[i] = 'X'
86
+ when 'ⅹ'
87
+ string[i] = 'x'
88
+ when 'Ⅺ'
89
+ string[i, 2] = 'XI'
90
+ when 'ⅺ'
91
+ string[i, 2] = 'xi'
92
+ when 'Ⅻ'
93
+ string[i, 3] = 'XII'
94
+ when 'ⅻ'
95
+ string[i, 3] = 'xii'
96
+ when 'Ⅼ'
97
+ string[i] = 'L'
98
+ when 'ⅼ'
99
+ string[i] = 'l'
100
+ when 'Ⅽ'
101
+ string[i] = 'C'
102
+ when 'ⅽ'
103
+ string[i] = 'c'
104
+ when 'Ⅾ'
105
+ string[i] = 'D'
106
+ when 'ⅾ'
107
+ string[i] = 'd'
108
+ when 'Ⅿ'
109
+ string[i] = 'M'
110
+ when 'ⅿ'
111
+ string[i] = 'm'
44
112
  else
45
113
  nil
46
114
  end
@@ -48,3 +116,121 @@ def self.romanize_string(string)
48
116
 
49
117
  string
50
118
  end
119
+
120
+ # @param [Array<String>] array Array of strings
121
+ # @return [Array<String>] Array of shuffled strings
122
+ def self.shuffle_words(array)
123
+ array.each do |string|
124
+ select_words_re = /\S+/
125
+ words = string.scan(select_words_re).shuffle
126
+ string.gsub(select_words_re) { words.pop || '' }
127
+ end
128
+ end
129
+
130
+ # @param [String] string A parsed scripts code string, containing raw Ruby code
131
+ # @param [Symbol] mode Mode to extract quoted strings
132
+ # @return [IndexSet<String>] Set of extracted strings
133
+ def extract_quoted_strings(string, mode)
134
+ if mode == :read
135
+ result = IndexSet.new
136
+
137
+ skip_block = false
138
+ in_quotes = false
139
+ quote_type = nil
140
+ buffer = []
141
+
142
+ string.each_line do |line|
143
+ stripped = line.strip
144
+
145
+ next if stripped[0] == '#' ||
146
+ (!in_quotes && !stripped.match?(/["']/)) ||
147
+ stripped.start_with?(/(Win|Lose)|_Fanfare/) ||
148
+ stripped.match?(/eval\(/)
149
+
150
+ skip_block = true if stripped.start_with?('=begin')
151
+ skip_block = false if stripped.start_with?('=end')
152
+
153
+ next if skip_block
154
+
155
+ line.each_char do |char|
156
+ if %w[' "].include?(char)
157
+ unless quote_type.nil? || char == quote_type
158
+ buffer.push(char)
159
+ next
160
+ end
161
+
162
+ quote_type = char
163
+ in_quotes = !in_quotes
164
+ result.add(buffer.join)
165
+ buffer.clear
166
+ next
167
+ end
168
+
169
+ next unless in_quotes
170
+
171
+ if char == "\r"
172
+ next
173
+ elsif char == "\n"
174
+ buffer.push('\#')
175
+ next
176
+ end
177
+
178
+ buffer.push(char)
179
+ end
180
+ end
181
+
182
+ result
183
+ else
184
+ strings_array = []
185
+ indices_array = []
186
+
187
+ skip_block = false
188
+ in_quotes = false
189
+ quote_type = nil
190
+ buffer = []
191
+
192
+ current_string_index = 0
193
+ string.each_line do |line|
194
+ stripped = line.strip
195
+
196
+ if stripped[0] == '#' || stripped.start_with?(/(Win|Lose)|_Fanfare/)
197
+ current_string_index += line.length
198
+ next
199
+ end
200
+
201
+ skip_block = true if stripped.start_with?('=begin')
202
+ skip_block = false if stripped.start_with?('=end')
203
+
204
+ if skip_block
205
+ current_string_index += line.length
206
+ next
207
+ end
208
+
209
+ buffer.push('\#') if in_quotes
210
+
211
+ line.each_char.each_with_index do |char, index|
212
+ if %w[' "].include?(char)
213
+ unless quote_type.nil? || char == quote_type
214
+ buffer.push(char)
215
+ next
216
+ end
217
+
218
+ quote_type = char
219
+ in_quotes = !in_quotes
220
+
221
+ strings_array.push(buffer.join)
222
+ indices_array.push(current_string_index + index)
223
+
224
+ buffer.clear
225
+ next
226
+ end
227
+
228
+ buffer.push(char) if in_quotes
229
+ end
230
+
231
+ current_string_index += line.length
232
+ end
233
+
234
+ [strings_array, indices_array]
235
+ end
236
+ end
data/lib/read.rb CHANGED
@@ -3,72 +3,9 @@
3
3
  require 'zlib'
4
4
  require_relative 'extensions'
5
5
 
6
- STRING_IS_ONLY_SYMBOLS_RE = /^[.()+-:;\[\]^~%&!*\/→×??x%▼| ]+$/
6
+ STRING_IS_ONLY_SYMBOLS_RE = /^[.()+\-:;\[\]^~%&!№$@`*\/→×??x%▼|♥♪!:〜『』「」〽。…‥=゠、,【】[]{}()〔〕⦅⦆〘〙〈〉《》・\\#'"<>=_ー※▶ⅠⅰⅡⅱⅢⅲⅣⅳⅤⅴⅥⅵⅦⅶⅧⅷⅨⅸⅩⅹⅪⅺⅫⅻⅬⅼⅭⅽⅮⅾⅯⅿ\s0-9]+$/
7
7
  APPEND_FLAG_OMIT_MSG = "Files aren't already parsed. Continuing as if --append flag was omitted."
8
8
 
9
- class Hash
10
- def insert_at_index(index, key, value)
11
- return self[key] = value if index >= size
12
-
13
- temp_array = to_a
14
- temp_array.insert(index, [key, value])
15
- replace(temp_array.to_h)
16
- end
17
- end
18
-
19
- # @param [String] string A parsed scripts code string, containing raw Ruby code
20
- # @return [IndexSet<String>] Set of extracted strings
21
- def self.extract_quoted_strings(string)
22
- result = IndexSet.new
23
-
24
- skip_block = false
25
- in_quotes = false
26
- quote_type = nil
27
- buffer = []
28
-
29
- string.each_line do |line|
30
- stripped = line.strip
31
-
32
- next if stripped[0] == '#' ||
33
- (!in_quotes && !stripped.match?(/["']/)) ||
34
- stripped.start_with?(/(Win|Lose)|_Fanfare/) ||
35
- stripped.match?(/eval\(/)
36
-
37
- skip_block = true if stripped.start_with?('=begin')
38
- skip_block = false if stripped.start_with?('=end')
39
-
40
- next if skip_block
41
-
42
- line.each_char do |char|
43
- if %w[' "].include?(char)
44
- unless quote_type.nil? || char == quote_type
45
- buffer.push(char)
46
- next
47
- end
48
-
49
- quote_type = char
50
- in_quotes = !in_quotes
51
- result.add(buffer.join)
52
- buffer.clear
53
- next
54
- end
55
-
56
- next unless in_quotes
57
-
58
- if char == "\r"
59
- next
60
- elsif char == "\n"
61
- buffer.push('\#')
62
- next
63
- end
64
-
65
- buffer.push(char)
66
- end
67
- end
68
-
69
- result
70
- end
71
-
72
9
  # @param [Integer] code
73
10
  # @param [String] parameter
74
11
  # @param [String] game_type
@@ -76,41 +13,63 @@ end
76
13
  def self.parse_parameter(code, parameter, game_type)
77
14
  return nil if parameter.match?(STRING_IS_ONLY_SYMBOLS_RE)
78
15
 
16
+ ends_with_if = parameter[/ if\(.*\)$/]
17
+ parameter = parameter.chomp(ends_with_if) if ends_with_if
18
+
79
19
  unless game_type.nil?
80
- case code
81
- when 401, 405
82
- case game_type
83
- when 'lisa'
84
- match = parameter.scan(/^\\et\[[0-9]+\]/)
85
- match = parameter.scan(/^\\nbt/) if match.empty?
86
- parameter = parameter[match[0].length..] unless match.empty?
20
+ case game_type
21
+ when 'lisa'
22
+ case code
23
+ when 401, 405
24
+ prefix = parameter[/^(\\et\[[0-9]+\]|\\nbt)/]
25
+ parameter = parameter.sub(prefix, '') if prefix
26
+ when 102
27
+ # Implement some custom parsing
28
+ when 356
29
+ # Implement some custom parsing
87
30
  else
88
- nil
31
+ return nil
89
32
  end
90
- when 102
91
- # Implement some custom parsing
92
- when 356
93
- # Implement some custom parsing
33
+ # Implement cases for other games
94
34
  else
95
- return nil
35
+ nil
96
36
  end
37
+
97
38
  end
98
39
 
99
40
  parameter
100
41
  end
101
42
 
102
43
  # @param [String] variable
44
+ # @param [Integer] type
103
45
  # @param [String] _game_type
104
46
  # @return [String]
105
- def self.parse_variable(variable, _game_type)
47
+ def self.parse_variable(variable, type, _game_type)
48
+ variable = variable.gsub(/\r?\n/, "\n")
49
+ # for some reason it returns true if multi-line string contains carriage returns (wtf?)
106
50
  return nil if variable.match?(STRING_IS_ONLY_SYMBOLS_RE)
107
- variable = variable.gsub(/\r?\n/, '\#') if variable.count("\n").positive?
108
51
 
109
- return nil if variable.split('\#').all? { |line| line.strip.match?(/(^#? ?<.*>\.?$)|^$/) }
110
- return nil if variable.match?(/^[+-]?[0-9]*$/) ||
52
+ if variable.split("\n").all? do |line|
53
+ line.empty? ||
54
+ line.match?(/^#? ?<.*>.?$/) ||
55
+ line.match?(/^[a-z][0-9]$/)
56
+ end
57
+ return nil
58
+ end
59
+
60
+ return nil if variable.match?(/^[+-]?[0-9]+$/) ||
111
61
  variable.match?(/---/) ||
112
62
  variable.match?(/restrict eval/)
113
63
 
64
+ case type
65
+ when 0 # name
66
+ when 1 # nickname
67
+ when 2 # description
68
+ when 3 # note
69
+ else
70
+ nil
71
+ end
72
+
114
73
  variable
115
74
  end
116
75
 
@@ -189,9 +148,9 @@ def self.read_map(maps_files_paths, output_path, romanize, logging, game_type, p
189
148
  list.each do |item|
190
149
  code = item.code
191
150
 
192
- unless allowed_codes.include?(code)
193
- if in_sequence
194
- joined = line.join('\#').strip
151
+ if in_sequence && code != 401
152
+ unless line.empty?
153
+ joined = line.join("\n").strip.gsub("\n", '\#')
195
154
  parsed = parse_parameter(401, joined, game_type)
196
155
 
197
156
  unless parsed.nil?
@@ -201,21 +160,22 @@ def self.read_map(maps_files_paths, output_path, romanize, logging, game_type, p
201
160
  !maps_translation_map.include?(parsed)
202
161
 
203
162
  maps_lines.add(parsed)
204
-
205
- line.clear
206
- in_sequence = false
207
163
  end
208
164
  end
209
- next
165
+
166
+ line.clear
167
+ in_sequence = false
210
168
  end
211
169
 
170
+ next unless allowed_codes.include?(code)
171
+
212
172
  parameters = item.parameters
213
173
 
214
174
  if code == 401
215
175
  next unless parameters[0].is_a?(String) && !parameters[0].empty?
216
176
 
217
177
  in_sequence = true
218
- line.push(parameters[0])
178
+ line.push(parameters[0].gsub(' ', ' ').strip)
219
179
  elsif parameters[0].is_a?(Array)
220
180
  parameters[0].each do |subparameter|
221
181
  next unless subparameter.is_a?(String)
@@ -240,7 +200,6 @@ def self.read_map(maps_files_paths, output_path, romanize, logging, game_type, p
240
200
  parsed = parse_parameter(code, parameter, game_type)
241
201
  next if parsed.nil?
242
202
 
243
- parsed = parsed.gsub(/\r?\n/, '\#')
244
203
  parsed = romanize_string(parsed) if romanize
245
204
 
246
205
  maps_translation_map.insert_at_index(maps_lines.length, parsed, '') if processing_mode == :append &&
@@ -326,22 +285,28 @@ def self.read_other(other_files_paths, output_path, romanize, logging, game_type
326
285
  description = object.description
327
286
  note = object.note
328
287
 
329
- [name, nickname, description, note].each do |variable|
330
- next unless variable.is_a?(String)
288
+ catch :next_object do
289
+ [name, nickname, description, note].each_with_index do |variable, type|
290
+ next unless variable.is_a?(String)
331
291
 
332
- variable = variable.strip
333
- next if variable.empty?
292
+ variable = variable.strip
293
+ next if variable.empty?
334
294
 
335
- parsed = parse_variable(variable, game_type)
336
- next if parsed.nil?
295
+ parsed = parse_variable(variable, type, game_type)
337
296
 
338
- parsed = parsed.gsub(/\r?\n/, '\#')
339
- parsed = romanize_string(parsed) if romanize
297
+ if !parsed.nil?
298
+ parsed = romanize_string(parsed) if romanize
299
+
300
+ parsed = parsed.split("\n").map(&:strip).join('\#')
340
301
 
341
- other_translation_map.insert_at_index(other_lines.length, parsed, '') if inner_processing_type == :append &&
342
- !other_translation_map.include?(parsed)
302
+ other_translation_map.insert_at_index(other_lines.length, parsed, '') if inner_processing_type == :append &&
303
+ !other_translation_map.include?(parsed)
343
304
 
344
- other_lines.add(parsed)
305
+ other_lines.add(parsed)
306
+ elsif type.zero?
307
+ throw :next_object
308
+ end
309
+ end
345
310
  end
346
311
  end
347
312
  else
@@ -361,9 +326,9 @@ def self.read_other(other_files_paths, output_path, romanize, logging, game_type
361
326
  list.each do |item|
362
327
  code = item.code
363
328
 
364
- unless allowed_codes.include?(code)
365
- if in_sequence
366
- joined = line.join('\#').strip
329
+ if in_sequence && ![401, 405].include?(code)
330
+ unless line.empty?
331
+ joined = line.join("\n").strip.gsub("\n", '\#')
367
332
  parsed = parse_parameter(401, joined, game_type)
368
333
 
369
334
  unless parsed.nil?
@@ -373,21 +338,22 @@ def self.read_other(other_files_paths, output_path, romanize, logging, game_type
373
338
  !other_translation_map.include?(parsed)
374
339
 
375
340
  other_lines.add(parsed)
376
-
377
- line.clear
378
- in_sequence = false
379
341
  end
380
342
  end
381
- next
343
+
344
+ line.clear
345
+ in_sequence = false
382
346
  end
383
347
 
348
+ next unless allowed_codes.include?(code)
349
+
384
350
  parameters = item.parameters
385
351
 
386
352
  if [401, 405].include?(code)
387
353
  next unless parameters[0].is_a?(String) && !parameters[0].empty?
388
354
 
389
355
  in_sequence = true
390
- line.push(parameters[0].gsub(/\r?\n/, '\#'))
356
+ line.push(parameters[0].gsub(' ', ' ').strip)
391
357
  elsif parameters[0].is_a?(Array)
392
358
  parameters[0].each do |subparameter|
393
359
  next unless subparameter.is_a?(String)
@@ -395,35 +361,42 @@ def self.read_other(other_files_paths, output_path, romanize, logging, game_type
395
361
  subparameter = subparameter.strip
396
362
  next if subparameter.empty?
397
363
 
398
- subparameter = romanize_string(subparameter) if romanize
364
+ parsed = parse_parameter(code, subparameter, game_type)
365
+ next if parsed.nil?
366
+
367
+ parsed = romanize_string(parsed) if romanize
399
368
 
400
- other_translation_map.insert_at_index(other_lines.length, subparameter, '') if inner_processing_type == :append &&
401
- !other_translation_map.include?(subparameter)
369
+ other_translation_map.insert_at_index(other_lines.length, parsed, '') if inner_processing_type == :append &&
370
+ !other_translation_map.include?(parsed)
402
371
 
403
- other_lines.add(subparameter)
372
+ other_lines.add(parsed)
404
373
  end
405
374
  elsif parameters[0].is_a?(String)
406
375
  parameter = parameters[0].strip
407
376
  next if parameter.empty?
408
377
 
409
- parameter = parameter.gsub(/\r?\n/, '\#')
410
- parameter = romanize_string(parameter) if romanize
378
+ parsed = parse_parameter(code, parameter, game_type)
379
+ next if parsed.nil?
380
+
381
+ parsed = romanize_string(parsed) if romanize
411
382
 
412
- other_translation_map.insert_at_index(other_lines.length, parameter, '') if inner_processing_type == :append &&
413
- !other_translation_map.include?(parameter)
383
+ other_translation_map.insert_at_index(other_lines.length, parsed, '') if inner_processing_type == :append &&
384
+ !other_translation_map.include?(parsed)
414
385
 
415
- other_lines.add(parameter)
386
+ other_lines.add(parsed)
416
387
  elsif parameters[1].is_a?(String)
417
388
  parameter = parameters[1].strip
418
389
  next if parameter.empty?
419
390
 
420
- parameter = parameter.gsub(/\r?\n/, '\#')
421
- parameter = romanize_string(parameter) if romanize
391
+ parsed = parse_parameter(code, parameter, game_type)
392
+ next if parsed.nil?
393
+
394
+ parsed = romanize_string(parsed) if romanize
422
395
 
423
- other_translation_map.insert_at_index(other_lines.length, parameter, '') if inner_processing_type == :append &&
424
- !other_translation_map.include?(parameter)
396
+ other_translation_map.insert_at_index(other_lines.length, parsed, '') if inner_processing_type == :append &&
397
+ !other_translation_map.include?(parsed)
425
398
 
426
- other_lines.add(parameter)
399
+ other_lines.add(parsed)
427
400
  end
428
401
  end
429
402
  end
@@ -637,7 +610,7 @@ def self.read_scripts(scripts_file_path, output_path, romanize, logging, process
637
610
  end
638
611
  end
639
612
 
640
- extract_quoted_strings(code).each do |string|
613
+ extract_quoted_strings(code, :read).each do |string|
641
614
  # Removes the U+3000 Japanese typographical space to check if string, when stripped, is truly empty
642
615
  string = string.strip.delete(' ')
643
616
 
@@ -653,7 +626,7 @@ def self.read_scripts(scripts_file_path, output_path, romanize, logging, process
653
626
  string.match?(/^(.)\1{2,}$/) ||
654
627
  string.match?(/^(false|true)$/) ||
655
628
  string.match?(/^[wr]b$/) ||
656
- string.match?(/^(?=.*\d)[A-Za-z0-9\-]+$/) ||
629
+ string.match?(/^(?=.*\d)[A-Za-z0-9-]+$/) ||
657
630
  string.match?(/^[a-z\-()\/ +'&]*$/) ||
658
631
  string.match?(/^[A-Za-z]+[+-]$/) ||
659
632
  string.match?(STRING_IS_ONLY_SYMBOLS_RE) ||
data/lib/write.rb CHANGED
@@ -3,123 +3,78 @@
3
3
  require 'zlib'
4
4
  require_relative 'extensions'
5
5
 
6
- # @param [String] string A parsed scripts code string, containing raw Ruby code
7
- # @return [Array<Array<String, Integer>>] Hash of parsed from code strings and their start indices
8
- def self.extract_quoted_strings(string)
9
- strings_array = []
10
- indices_array = []
11
-
12
- skip_block = false
13
- in_quotes = false
14
- quote_type = nil
15
- buffer = []
16
-
17
- current_string_index = 0
18
- string.each_line do |line|
19
- stripped = line.strip
20
-
21
- if stripped[0] == '#' || stripped.start_with?(/(Win|Lose)|_Fanfare/)
22
- current_string_index += line.length
23
- next
24
- end
25
-
26
- skip_block = true if stripped.start_with?('=begin')
27
- skip_block = false if stripped.start_with?('=end')
28
-
29
- if skip_block
30
- current_string_index += line.length
31
- next
32
- end
33
-
34
- buffer.push('\#') if in_quotes
35
-
36
- line.each_char.each_with_index do |char, index|
37
- if %w[' "].include?(char)
38
- unless quote_type.nil? || char == quote_type
39
- buffer.push(char)
40
- next
41
- end
42
-
43
- quote_type = char
44
- in_quotes = !in_quotes
45
-
46
- strings_array.push(buffer.join)
47
- indices_array.push(current_string_index + index)
48
-
49
- buffer.clear
50
- next
51
- end
52
-
53
- buffer.push(char) if in_quotes
54
- end
55
-
56
- current_string_index += line.length
57
- end
58
-
59
- [strings_array, indices_array]
60
- end
61
-
62
- # @param [Array<String>] array Array of strings
63
- # @return [Array<String>] Array of shuffled strings
64
- def self.shuffle_words(array)
65
- array.each do |string|
66
- select_words_re = /\S+/
67
- words = string.scan(select_words_re).shuffle
68
- string.gsub(select_words_re) { words.pop || '' }
69
- end
70
- end
71
-
72
6
  # @param [Integer] code
73
7
  # @param [String] parameter
74
8
  # @param [Hash{String => String}] hashmap Translation hashmap (as everything in Ruby passed by reference, this pass is free!)
75
9
  # @param [String] game_type
76
10
  def self.get_parameter_translated(code, parameter, hashmap, game_type)
11
+ remaining_strings = []
12
+ insert_positions = []
13
+
14
+ ends_with_if = parameter[/ if\(.*\)$/]
15
+
16
+ if ends_with_if
17
+ parameter = parameter.chomp(ends_with_if)
18
+ remaining_strings.push(ends_with_if)
19
+ insert_positions.push(1)
20
+ end
21
+
77
22
  unless game_type.nil?
78
- lisa_start = nil
79
-
80
- case code
81
- when 401, 405
82
- case game_type
83
- when 'lisa'
84
- match = parameter.scan(/^\\et\[[0-9]+\]/)
85
- match = parameter.scan(/^\\nbt/) if match.empty?
86
-
87
- unless match.empty?
88
- lisa_start = match[0]
89
- parameter = parameter.slice((match[0].length)..)
90
- end
23
+ case game_type
24
+ when 'lisa'
25
+ case code
26
+ when 401, 405
27
+ prefix = parameter[/^(\\et\[[0-9]+\]|\\nbt)/]
28
+ parameter = parameter.sub(prefix, '') if prefix
29
+
30
+ remaining_strings.push(prefix)
31
+ insert_positions.push(0)
32
+ when 102, 402
33
+ # Implement some custom parsing
34
+ when 356
35
+ # Implement some custom parsing
91
36
  else
92
37
  nil
93
38
  end
94
- when 102, 402
95
- # Implement some custom parsing
96
- when 356
97
- # Implement some custom parsing
39
+ # Implement cases for other games
98
40
  else
99
41
  nil
100
42
  end
43
+ end
101
44
 
102
- gotten = hashmap[parameter]
103
- return nil if gotten.nil?
45
+ translated = hashmap[parameter]
46
+ return nil if translated.nil? || translated.empty?
104
47
 
105
- case game_type
106
- when 'lisa'
107
- gotten = lisa_start + gotten unless lisa_start.nil?
108
- else
109
- nil
48
+ remaining_strings.zip(insert_positions).each do |string, position|
49
+ case position
50
+ when 0
51
+ translated = string + translated
52
+ when 1
53
+ translated += string
110
54
  end
111
-
112
- return gotten
113
55
  end
114
56
 
115
- hashmap[parameter]
57
+ translated
116
58
  end
117
59
 
118
60
  # @param [String] variable
61
+ # @param [Integer] type
62
+ # @param [String] filename
119
63
  # @param [Hash{String => String}] hashmap Translation hashmap (as everything in Ruby passed by reference, this pass is free!)
120
64
  # @param [String] _game_type
121
65
  # @return [String]
122
- def self.get_variable_translated(variable, hashmap, _game_type)
66
+ def self.get_variable_translated(variable, type, _filename, hashmap, _game_type)
67
+ variable = variable.gsub(/\r?\n/, "\n")
68
+
69
+ case type
70
+ when 0 # name
71
+ when 1 # nickname
72
+ when 2 # description
73
+ when 3 # note
74
+ else
75
+ nil
76
+ end
77
+
123
78
  hashmap[variable]
124
79
  end
125
80
 
@@ -191,14 +146,14 @@ def self.write_map(original_files_paths, maps_path, output_path, shuffle_level,
191
146
  list.each_with_index do |item, it|
192
147
  code = item.code
193
148
 
194
- unless allowed_codes.include?(code)
195
- if in_sequence
196
- joined = line.join('\#').strip
149
+ if in_sequence && code != 401
150
+ unless line.empty?
151
+ joined = line.join("\n").strip
197
152
  joined = romanize_string(joined) if romanize
198
153
 
199
154
  translated = get_parameter_translated(401, joined, maps_translation_map, game_type)
200
155
 
201
- unless translated.nil? || translated.empty?
156
+ if !translated.nil? && !translated.empty?
202
157
  split = translated.split('\#')
203
158
 
204
159
  split_length = split.length
@@ -208,19 +163,25 @@ def self.write_map(original_files_paths, maps_path, output_path, shuffle_level,
208
163
  list[index].parameters[0] = i < split_length ? split[i] : ''
209
164
  end
210
165
 
211
- list[item_indices.last].parameters[0] = split[line_length..].join("\n") if split_length > line_length
166
+ if split_length > line_length
167
+ list[item_indices.last].parameters[0] = split[line_length..].join("\n")
168
+ end
212
169
  end
213
170
  end
214
- next
171
+
172
+ line.clear
173
+ in_sequence = false
215
174
  end
216
175
 
176
+ next unless allowed_codes.include?(code)
177
+
217
178
  parameters = item.parameters
218
179
 
219
180
  if code == 401
220
181
  next unless parameters[0].is_a?(String) && !parameters[0].empty?
221
182
 
222
183
  in_sequence = true
223
- line.push(parameters[0])
184
+ line.push(parameters[0].gsub(' ', ' ').strip)
224
185
  item_indices.push(it)
225
186
  elsif parameters[0].is_a?(Array)
226
187
  parameters[0].each_with_index do |subparameter, sp|
@@ -232,7 +193,7 @@ def self.write_map(original_files_paths, maps_path, output_path, shuffle_level,
232
193
  subparameter = romanize_string(subparameter) if romanize
233
194
 
234
195
  translated = get_parameter_translated(code, subparameter, maps_translation_map, game_type)
235
- parameters[0][sp] = translated unless translated.nil? || translated.empty?
196
+ parameters[0][sp] = translated if !translated.nil? && !translated.empty?
236
197
  end
237
198
  elsif parameters[0].is_a?(String)
238
199
  parameter = parameters[0].strip
@@ -241,7 +202,7 @@ def self.write_map(original_files_paths, maps_path, output_path, shuffle_level,
241
202
  parameter = romanize_string(parameter) if romanize
242
203
 
243
204
  translated = get_parameter_translated(code, parameter, maps_translation_map, game_type)
244
- parameters[0] = translated unless translated.nil? || translated.empty?
205
+ parameters[0] = translated if !translated.nil? && !translated.empty?
245
206
  elsif parameters[1].is_a?(String)
246
207
  parameter = parameters[1].strip
247
208
  next if parameter.empty?
@@ -249,7 +210,7 @@ def self.write_map(original_files_paths, maps_path, output_path, shuffle_level,
249
210
  parameter = romanize_string(parameter) if romanize
250
211
 
251
212
  translated = get_parameter_translated(code, parameter, maps_translation_map, game_type)
252
- parameters[1] = translated unless translated.nil? || translated.empty?
213
+ parameters[1] = translated if !translated.nil? && !translated.empty?
253
214
  end
254
215
 
255
216
  item.parameters = parameters
@@ -313,23 +274,24 @@ def self.write_other(original_files_paths, other_path, output_path, shuffle_leve
313
274
  description = object.description
314
275
  note = object.note
315
276
 
316
- [name, nickname, description, note].each_with_index do |variable, i|
277
+ [name, nickname, description, note].each_with_index do |variable, type|
317
278
  next unless variable.is_a?(String)
318
279
 
319
280
  variable = variable.strip
320
281
  next if variable.empty?
321
282
 
322
- variable = variable.gsub(/\r\n/, "\n")
323
283
  variable = romanize_string(variable) if romanize
324
284
 
325
- translated = get_variable_translated(variable, other_translation_map, game_type)
285
+ variable = variable.split("\n").map(&:strip).join("\n")
286
+
287
+ translated = get_variable_translated(variable, type, filename, other_translation_map, game_type)
326
288
 
327
- unless translated.nil? || translated.empty?
328
- if i.zero?
289
+ if !translated.nil? && !translated.empty?
290
+ if type.zero?
329
291
  object.name = translated
330
- elsif i == 1
292
+ elsif type == 1
331
293
  object.nickname = translated if object.is_a?(RPG::Actor)
332
- elsif i == 2
294
+ elsif type == 2
333
295
  object.description = translated
334
296
  else
335
297
  object.note = translated
@@ -355,14 +317,14 @@ def self.write_other(original_files_paths, other_path, output_path, shuffle_leve
355
317
  list.each_with_index do |item, it|
356
318
  code = item.code
357
319
 
358
- unless allowed_codes.include?(code)
359
- if in_sequence
360
- joined = line.join('\#').strip
320
+ if in_sequence && ![401, 405].include?(code)
321
+ unless line.empty?
322
+ joined = line.join("\n").strip
361
323
  joined = romanize_string(joined) if romanize
362
324
 
363
325
  translated = get_parameter_translated(401, joined, other_translation_map, game_type)
364
326
 
365
- unless translated.nil? || translated.empty?
327
+ if !translated.nil? && !translated.empty?
366
328
  split = translated.split('\#')
367
329
 
368
330
  split_length = split.length
@@ -372,19 +334,25 @@ def self.write_other(original_files_paths, other_path, output_path, shuffle_leve
372
334
  list[index].parameters[0] = i < split_length ? split[i] : ''
373
335
  end
374
336
 
375
- list[item_indices.last].parameters[0] = split[line_length..].join("\n") if split_length > line_length
337
+ if split_length > line_length
338
+ list[item_indices.last].parameters[0] = split[line_length..].join("\n")
339
+ end
376
340
  end
377
341
  end
378
- next
342
+
343
+ line.clear
344
+ in_sequence = false
379
345
  end
380
346
 
347
+ next unless allowed_codes.include?(code)
348
+
381
349
  parameters = item.parameters
382
350
 
383
351
  if [401, 405].include?(code)
384
352
  next unless parameters[0].is_a?(String) && !parameters[0].empty?
385
353
 
386
354
  in_sequence = true
387
- line.push(parameters[0])
355
+ line.push(parameters[0].gsub(' ', ' ').strip)
388
356
  item_indices.push(it)
389
357
  elsif parameters[0].is_a?(Array)
390
358
  parameters[0].each_with_index do |subparameter, sp|
@@ -396,7 +364,7 @@ def self.write_other(original_files_paths, other_path, output_path, shuffle_leve
396
364
  subparameter = romanize_string(subparameter) if romanize
397
365
 
398
366
  translated = get_parameter_translated(code, subparameter, other_translation_map, game_type)
399
- parameters[0][sp] = translated unless translated.nil? || translated.empty?
367
+ parameters[0][sp] = translated if !translated.nil? && !translated.empty?
400
368
  end
401
369
  elsif parameters[0].is_a?(String)
402
370
  parameter = parameters[0].strip
@@ -405,7 +373,7 @@ def self.write_other(original_files_paths, other_path, output_path, shuffle_leve
405
373
  parameter = romanize_string(parameter) if romanize
406
374
 
407
375
  translated = get_parameter_translated(code, parameter, other_translation_map, game_type)
408
- parameters[0] = translated unless translated.nil? || translated.empty?
376
+ parameters[0] = translated if !translated.nil? && !translated.empty?
409
377
  elsif parameters[1].is_a?(String)
410
378
  parameter = parameters[1].strip
411
379
  next if parameter.empty?
@@ -413,7 +381,7 @@ def self.write_other(original_files_paths, other_path, output_path, shuffle_leve
413
381
  parameter = romanize_string(parameter) if romanize
414
382
 
415
383
  translated = get_parameter_translated(code, parameter, other_translation_map, game_type)
416
- parameters[1] = translated unless translated.nil? || translated.empty?
384
+ parameters[1] = translated if !translated.nil? && !translated.empty?
417
385
  end
418
386
 
419
387
  item.parameters = parameters
@@ -490,7 +458,7 @@ def self.write_system(system_file_path, ini_file_path, other_path, output_path,
490
458
  string = romanize_string(string) if romanize
491
459
 
492
460
  translated = system_translation_map[string]
493
- array[i] = translated unless translated.nil? || translated.empty?
461
+ array[i] = translated if !translated.nil? && !translated.empty?
494
462
  end
495
463
 
496
464
  if i.zero?
@@ -519,7 +487,7 @@ def self.write_system(system_file_path, ini_file_path, other_path, output_path,
519
487
  value = romanize_string(value) if romanize
520
488
 
521
489
  translated = system_translation_map[value]
522
- value = translated unless translated.nil? || translated.empty?
490
+ value = translated if !translated.nil? && !translated.empty?
523
491
  elsif value.is_a?(Array)
524
492
  value.each_with_index do |string, i|
525
493
  string = string.strip
@@ -528,7 +496,7 @@ def self.write_system(system_file_path, ini_file_path, other_path, output_path,
528
496
  string = romanize_string(string) if romanize
529
497
 
530
498
  translated = system_translation_map[string]
531
- value[i] = translated unless translated.nil? || translated.empty?
499
+ value[i] = translated if !translated.nil? && !translated.empty?
532
500
  end
533
501
  end
534
502
 
@@ -591,7 +559,7 @@ def self.write_scripts(scripts_file_path, other_path, output_path, romanize, log
591
559
  end
592
560
 
593
561
  # this shit finally works and requires NO further changes
594
- string_array, index_array = extract_quoted_strings(code)
562
+ string_array, index_array = extract_quoted_strings(code, :write)
595
563
 
596
564
  string_array.zip(index_array).reverse_each do |string, index|
597
565
  string = string.strip.delete(' ')
data/rvpacker-txt.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'rvpacker-txt'
5
- spec.version = '1.9.4'
5
+ spec.version = '1.11.0'
6
6
  spec.authors = ['Howard Jeng', 'Andrew Kesterson', 'Solistra', 'Darkness9724', 'savannstm']
7
7
  spec.email = ['savannstm@gmail.com']
8
8
  spec.summary = 'Reads RPG Maker XP/VX/VXAce game text to .txt files and writes them to their initial form.'
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.9.4
4
+ version: 1.11.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-26 00:00:00.000000000 Z
15
+ date: 2024-07-28 00:00:00.000000000 Z
16
16
  dependencies: []
17
17
  description:
18
18
  email: