sso-elements-fmk 0.1.1 → 0.1.3

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