sso-elements-fmk 0.1.2 → 0.1.4

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.
@@ -1,248 +1,265 @@
1
- require_relative 'config'
2
-
3
- module SSO
4
- module Elements
5
- class Collection
6
- attr_accessor :version,
7
- :signature,
8
- :index,
9
- :configs
10
-
11
- def initialize
12
- @addon_index = {}
13
- @lists = []
14
- end
15
-
16
- def table(name)
17
- index[name]
18
- end
19
-
20
- def build_index!
21
- @index = {}
22
- @configs.each do |config|
23
- config_name = config.name.split(' - ').last.downcase.split('_').map(&:capitalize).join('')
24
- @index[config_name] = config
25
- end
26
- end
27
-
28
- def load_elements!(path)
29
- sstat = [ 0, 0, 0, 0, 0 ]
30
-
31
- file = File.open(path, 'rb')
32
-
33
- @version = file.read(2).unpack('s<').first
34
-
35
- if @configs.nil?
36
- puts '[INFO] No config provided. Searching in default CFG files'
37
- if SSO::Elements::Config::CFG_AVAIL.keys.include?(@version)
38
- puts "[INFO] Using #{SSO::Elements::Config::CFG_AVAIL[@version]}!"
39
- load_config!(@version)
40
- else
41
- raise "[ERROR] No config provided and no default cfg file to match with elements version #{@version}!"
42
- end
43
- end
44
-
45
- @signature = file.read(2).unpack('s<').first
46
-
47
- @configs.each_with_index do |config, i|
48
- puts "[INFO] (#{i+1}/#{@configs.size}) Reading #{config.name} ... "
49
- sstat[0] = i
50
-
51
- if config.offset.size > 0
52
- config.offset = file.read(config.offset.size).bytes
53
- else
54
- puts 'CRITICAL: NO OFFSET FOUND!'
55
- return false
56
- end
57
-
58
- config.values = Array.new(read_value(file, 'int32'))
59
- sstat[1] = config.values.size
60
-
61
- (0...config.values.size).each do |e|
62
- config.values[e] = Array.new(config.types.size)
63
-
64
- (0...config.values[e].size).each do |f|
65
- config.values[e][f] = read_value(file, config.types[f])
66
- end
67
- end
68
- end
69
-
70
- file.close
71
-
72
- build_index!
73
-
74
- true
75
- end
76
-
77
- def load_config!(path)
78
- if path.is_a?(Integer)
79
- cfg = Config::CFG_AVAIL[path]
80
- raise "Incompatible version #{path}!" unless cfg
81
- dir = File.dirname(__FILE__)
82
- path = File.expand_path("./configs/#{cfg}", dir)
83
- end
84
-
85
- buffer = File.readlines(path, chomp: true)
86
-
87
- lists_size = buffer.shift.to_i
88
-
89
- lists = []
90
- @conversation_list_index = buffer.shift.to_i
91
- @conversation_list_index = 58 if @conversation_list_index == 0
92
-
93
- lists_size.times do
94
- line = ''
95
-
96
- loop do
97
- line = buffer.shift
98
- break unless line == ''
99
- end
100
-
101
- offset = buffer.shift
102
-
103
- list = Config.new
104
- list.name = line
105
- list.offset = Array.new(offset.to_i) if offset != 'AUTO'
106
- list.fields = buffer.shift.split(';')
107
- list.types = buffer.shift.split(';')
108
- lists << list
109
- end
110
-
111
- @configs = lists
112
- true
113
- end
114
-
115
- def load_rules(path)
116
- buffer = File.readlines(path, chomp: true)
117
-
118
- result = {}
119
-
120
- buffer.each do |line|
121
- next if line.empty? || line[0] == '#'
122
-
123
- if line.include?('|')
124
- key, value = line.split('|')
125
- else
126
- key = line
127
- value = ''
128
- end
129
-
130
- result[key] = value
131
- end
132
-
133
- result['SETCONVERSATIONLISTINDEX'] ||= 58
134
-
135
- result
136
- end
137
-
138
- def save!(path)
139
- File.delete(path) if File.exist?(path)
140
- file = File.open(path, 'wb')
141
-
142
- file.write([@version].pack('s<'))
143
- file.write([@signature].pack('s<'))
144
-
145
- @configs.each_with_index do |config, index|
146
- puts "[INFO] (#{index+1}/#{@configs.size}) Saving #{config.name} ... "
147
- file.write(config.offset.pack("C*")) if config.offset.size > 0
148
-
149
- if @conversation_list_index != index
150
- file.write([config.values.size].pack('l<'))
151
- end
152
-
153
- if config.elements_loaded?
154
- (0...config.values.size).each do |config_values_index|
155
- config.values[config_values_index] = config.elements[config_values_index].to_value
156
- end
157
- end
158
-
159
- config.values.each do |values|
160
- values.each_with_index do |value, value_index|
161
- begin
162
- write_value(file, value, config.types[value_index])
163
- rescue => e
164
- pp values
165
- raise e
166
- end
167
- end
168
- end
169
- end
170
-
171
- file.close
172
- true
173
- rescue => e
174
- p e
175
- false
176
- end
177
-
178
- def read_value(file, type)
179
- if type == 'int16'
180
- file.read(2).unpack('s<')[0]
181
- elsif type == 'int32'
182
- file.read(4).unpack("l<")[0]
183
- elsif type == 'int64'
184
- file.read(8).unpack('q<')[0]
185
- elsif type == 'float'
186
- file.read(4).unpack('f')[0]
187
- elsif type == 'double'
188
- file.read(8).unpack('d')[0]
189
- elsif type.start_with?('byte:')
190
- byte_count = type[5..-1].to_i
191
- file.read(byte_count)
192
- elsif type.start_with?('wstring:')
193
- byte_count = type[8..-1].to_i
194
- Collection.compact_string(file.read(byte_count).force_encoding('UTF-16LE').encode('UTF-8'))
195
- elsif type.start_with?('string:')
196
- byte_count = type[7..-1].to_i
197
- Collection.compact_string(file.read(byte_count).force_encoding('UTF-8'))
198
- else
199
- nil
200
- end
201
- end
202
-
203
- def write_value(file, value, type)
204
- if type == 'int16'
205
- file.write([value.to_i].pack('s<'))
206
- elsif type == 'int32'
207
- file.write([value.to_i].pack('l<'))
208
- elsif type == 'int64'
209
- file.write([value.to_f].pack('q<'))
210
- elsif type == 'float'
211
- file.write([value.to_f].pack('f'))
212
- elsif type == 'double'
213
- file.write([value.to_f].pack('d'))
214
- elsif type.start_with?('byte:')
215
- file.write(value)
216
- elsif type.start_with?('wstring:')
217
- file.write(Collection.expand_string_utf16((value || 'BUG').encode('UTF-16LE'), type))
218
- elsif type.start_with?('string:')
219
- file.write(Collection.expand_string_utf8((value || 'BUG'), type))
220
- else
221
- nil
222
- end
223
- rescue => e
224
- pp value
225
- pp type
226
- raise e
227
- end
228
-
229
- def self.compact_string(s)
230
- s.gsub("\u0000", '')
231
- end
232
-
233
- def self.expand_string_utf16(base, type)
234
- sz = type.split(':').last.to_i
235
- s = base
236
- s += "\u0000".encode('UTF-16LE') while s.bytes.size < sz
237
- s
238
- end
239
-
240
- def self.expand_string_utf8(base, type)
241
- sz = type.split(':').last.to_i
242
- s = base
243
- s += "\u0000" while s.bytes.size < sz
244
- s
245
- end
246
- end
247
- end
1
+ require_relative 'config'
2
+
3
+ module SSO
4
+ module Elements
5
+ class Collection
6
+ attr_accessor :version,
7
+ :signature,
8
+ :index,
9
+ :configs,
10
+ :id_set
11
+
12
+ def initialize
13
+ @addon_index = {}
14
+ @lists = []
15
+ @id_set = Set.new
16
+ end
17
+
18
+ def gen_id
19
+ id = 1
20
+
21
+ while id_set.include?(id)
22
+ id += 1
23
+ end
24
+
25
+ id
26
+ end
27
+
28
+ def table(name)
29
+ index[name]
30
+ end
31
+
32
+ def build_index!
33
+ puts '[INFO] Building collections'
34
+ @index = {}
35
+ @configs.each do |config|
36
+ config_name = config.name.split(' - ').last.downcase.split('_').map(&:capitalize).join('')
37
+ @index[config_name] = config
38
+ puts "[INFO] Building collection #{config_name}"
39
+ config.elements.each do |element|
40
+ id_set << element.id
41
+ end
42
+ end
43
+ end
44
+
45
+ def load_elements!(path)
46
+ sstat = [ 0, 0, 0, 0, 0 ]
47
+
48
+ file = File.open(path, 'rb')
49
+
50
+ @version = file.read(2).unpack('s<').first
51
+
52
+ if @configs.nil?
53
+ puts '[INFO] No config provided. Searching in default CFG files'
54
+ if SSO::Elements::Config::CFG_AVAIL.keys.include?(@version)
55
+ puts "[INFO] Using #{SSO::Elements::Config::CFG_AVAIL[@version]}!"
56
+ load_config!(@version)
57
+ else
58
+ raise "[ERROR] No config provided and no default cfg file to match with elements version #{@version}!"
59
+ end
60
+ end
61
+
62
+ @signature = file.read(2).unpack('s<').first
63
+
64
+ @configs.each_with_index do |config, i|
65
+ puts "[INFO] (#{i+1}/#{@configs.size}) Reading #{config.name} ... "
66
+ sstat[0] = i
67
+
68
+ if config.offset.size > 0
69
+ config.offset = file.read(config.offset.size).bytes
70
+ else
71
+ puts 'CRITICAL: NO OFFSET FOUND!'
72
+ return false
73
+ end
74
+
75
+ config.values = Array.new(read_value(file, 'int32'))
76
+ sstat[1] = config.values.size
77
+
78
+ (0...config.values.size).each do |e|
79
+ config.values[e] = Array.new(config.types.size)
80
+
81
+ (0...config.values[e].size).each do |f|
82
+ config.values[e][f] = read_value(file, config.types[f])
83
+ end
84
+ end
85
+ end
86
+
87
+ file.close
88
+
89
+ build_index!
90
+
91
+ true
92
+ end
93
+
94
+ def load_config!(path)
95
+ if path.is_a?(Integer)
96
+ cfg = Config::CFG_AVAIL[path]
97
+ raise "Incompatible version #{path}!" unless cfg
98
+ dir = File.dirname(__FILE__)
99
+ path = File.expand_path("./configs/#{cfg}", dir)
100
+ end
101
+
102
+ buffer = File.readlines(path, chomp: true)
103
+
104
+ lists_size = buffer.shift.to_i
105
+
106
+ lists = []
107
+ @conversation_list_index = buffer.shift.to_i
108
+ @conversation_list_index = 58 if @conversation_list_index == 0
109
+
110
+ lists_size.times do
111
+ line = ''
112
+
113
+ loop do
114
+ line = buffer.shift
115
+ break unless line == ''
116
+ end
117
+
118
+ offset = buffer.shift
119
+
120
+ list = Config.new(self)
121
+ list.name = line
122
+ list.offset = Array.new(offset.to_i) if offset != 'AUTO'
123
+ list.fields = buffer.shift.split(';')
124
+ list.types = buffer.shift.split(';')
125
+ lists << list
126
+ end
127
+
128
+ @configs = lists
129
+ true
130
+ end
131
+
132
+ def load_rules(path)
133
+ buffer = File.readlines(path, chomp: true)
134
+
135
+ result = {}
136
+
137
+ buffer.each do |line|
138
+ next if line.empty? || line[0] == '#'
139
+
140
+ if line.include?('|')
141
+ key, value = line.split('|')
142
+ else
143
+ key = line
144
+ value = ''
145
+ end
146
+
147
+ result[key] = value
148
+ end
149
+
150
+ result['SETCONVERSATIONLISTINDEX'] ||= 58
151
+
152
+ result
153
+ end
154
+
155
+ def save!(path)
156
+ File.delete(path) if File.exist?(path)
157
+ file = File.open(path, 'wb')
158
+
159
+ file.write([@version].pack('s<'))
160
+ file.write([@signature].pack('s<'))
161
+
162
+ @configs.each_with_index do |config, index|
163
+ puts "[INFO] (#{index+1}/#{@configs.size}) Saving #{config.name} ... "
164
+ file.write(config.offset.pack("C*")) if config.offset.size > 0
165
+
166
+ if @conversation_list_index != index
167
+ file.write([config.values.size].pack('l<'))
168
+ end
169
+
170
+ if config.elements_loaded?
171
+ (0...config.values.size).each do |config_values_index|
172
+ config.values[config_values_index] = config.elements[config_values_index].to_value
173
+ end
174
+ end
175
+
176
+ config.values.each do |values|
177
+ values.each_with_index do |value, value_index|
178
+ begin
179
+ write_value(file, value, config.types[value_index])
180
+ rescue => e
181
+ pp values
182
+ raise e
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ file.close
189
+ true
190
+ rescue => e
191
+ p e
192
+ false
193
+ end
194
+
195
+ def read_value(file, type)
196
+ if type == 'int16'
197
+ file.read(2).unpack('s<')[0]
198
+ elsif type == 'int32'
199
+ file.read(4).unpack("l<")[0]
200
+ elsif type == 'int64'
201
+ file.read(8).unpack('q<')[0]
202
+ elsif type == 'float'
203
+ file.read(4).unpack('f')[0]
204
+ elsif type == 'double'
205
+ file.read(8).unpack('d')[0]
206
+ elsif type.start_with?('byte:')
207
+ byte_count = type[5..-1].to_i
208
+ file.read(byte_count)
209
+ elsif type.start_with?('wstring:')
210
+ byte_count = type[8..-1].to_i
211
+ Collection.compact_string(file.read(byte_count).force_encoding('UTF-16LE').encode('UTF-8'))
212
+ elsif type.start_with?('string:')
213
+ byte_count = type[7..-1].to_i
214
+ Collection.compact_string(file.read(byte_count).force_encoding('UTF-8'))
215
+ else
216
+ nil
217
+ end
218
+ end
219
+
220
+ def write_value(file, value, type)
221
+ if type == 'int16'
222
+ file.write([value.to_i].pack('s<'))
223
+ elsif type == 'int32'
224
+ file.write([value.to_i].pack('l<'))
225
+ elsif type == 'int64'
226
+ file.write([value.to_f].pack('q<'))
227
+ elsif type == 'float'
228
+ file.write([value.to_f].pack('f'))
229
+ elsif type == 'double'
230
+ file.write([value.to_f].pack('d'))
231
+ elsif type.start_with?('byte:')
232
+ file.write(value)
233
+ elsif type.start_with?('wstring:')
234
+ file.write(Collection.expand_string_utf16((value || 'BUG').encode('UTF-16LE'), type))
235
+ elsif type.start_with?('string:')
236
+ file.write(Collection.expand_string_utf8((value || 'BUG'), type))
237
+ else
238
+ nil
239
+ end
240
+ rescue => e
241
+ pp value
242
+ pp type
243
+ raise e
244
+ end
245
+
246
+ def self.compact_string(s)
247
+ s.gsub("\u0000", '')
248
+ end
249
+
250
+ def self.expand_string_utf16(base, type)
251
+ sz = type.split(':').last.to_i
252
+ s = base
253
+ s += "\u0000".encode('UTF-16LE') while s.bytes.size < sz
254
+ s
255
+ end
256
+
257
+ def self.expand_string_utf8(base, type)
258
+ sz = type.split(':').last.to_i
259
+ s = base
260
+ s += "\u0000" while s.bytes.size < sz
261
+ s
262
+ end
263
+ end
264
+ end
248
265
  end