From 948aafb749a021c54a5cd3f87b4f98292aadc3ee Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Thu, 17 Nov 2022 15:43:27 +0100 Subject: [PATCH] First workin snap item parser Thanks a lot to @Learath2 for explaining in irc And for the awesome libtw2 docs by @heinrich5991 https://github.com/heinrich5991/libtw2/blob/48a2573af66105fc38f032fe22cfcc60f95f7485/doc/snapshot.md --- lib/game_client.rb | 54 +++++++++++++++++++++------------------- lib/packer.rb | 1 + spec/05_unpacker_spec.rb | 7 ++++++ 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/lib/game_client.rb b/lib/game_client.rb index a616176..250727c 100644 --- a/lib/game_client.rb +++ b/lib/game_client.rb @@ -300,34 +300,36 @@ class GameClient end item_delta = u.get_int - item_bits = item_delta.to_s(2).rjust(32, '0') - item_id_bits = item_bits[0...16] - item_type_bits = item_bits[16..] - item_id = item_id_bits.to_i(2) - item_type = item_type_bits.to_i(2) - item_meta = @snap_items[item_type] - item_name = item_meta[:name] - # { name: 'obj_game_data', size: 3, fields: [ - # { type: 'int', name: 'start_tick' }, + while item_delta + # item_bits = item_delta.to_s(2).rjust(32, '0') + item_type = item_delta + # item_id_bits = item_bits[0...16] + # item_type_bits = item_bits[16..] + # item_id = item_id_bits.to_i(2) + # item_type = item_type_bits.to_i(2) + item_meta = @snap_items[item_type] + item_name = item_meta[:name] + # { name: 'obj_game_data', size: 3, fields: [ + # { type: 'int', name: 'start_tick' }, - p = u.parsed.last - notes.push([:green, p[:pos], p[:len], - "\n id = #{item_id_bits} -> #{item_id}" \ - "\n type = #{item_type_bits} -> #{item_type} #{item_name}"]) - - who = u.get_int - p = u.parsed.last - notes.push([:cyan, p[:pos], p[:len], "who are you mr #{who} ?"]) - - size = item_meta[:size] - (0...size).each do |i| - val = u.get_int p = u.parsed.last - color = (i % 2).zero? ? :yellow : :pink - fields = item_meta[:fields] - desc = '' - desc = fields[i][:name] unless fields.nil? || fields[i].nil? - notes.push([color, p[:pos], p[:len], "data[#{i}]=#{val} #{desc}"]) + notes.push([:green, p[:pos], p[:len], "type = #{item_type} #{item_name}"]) + + item_id = u.get_int + p = u.parsed.last + notes.push([:cyan, p[:pos], p[:len], "id=#{item_id}"]) + + size = item_meta[:size] + (0...size).each do |i| + val = u.get_int + p = u.parsed.last + color = (i % 2).zero? ? :yellow : :pink + fields = item_meta[:fields] + desc = '' + desc = fields[i][:name] unless fields.nil? || fields[i].nil? + notes.push([color, p[:pos], p[:len], "data[#{i}]=#{val} #{desc}"]) + end + item_delta = u.get_int end # skip = 0 diff --git a/lib/packer.rb b/lib/packer.rb index 03e6417..7abca09 100644 --- a/lib/packer.rb +++ b/lib/packer.rb @@ -135,6 +135,7 @@ class Unpacker def get_int return nil if @data.nil? + return nil if @data.empty? # TODO: make this more performant # it should not read in ALL bytes diff --git a/spec/05_unpacker_spec.rb b/spec/05_unpacker_spec.rb index 70fe1c7..12359a4 100644 --- a/spec/05_unpacker_spec.rb +++ b/spec/05_unpacker_spec.rb @@ -49,6 +49,13 @@ describe 'Unpacker', :unpacker do expect(u.get_int).to eq(2) end + it 'Should return nil if no more int is found' do + u = Unpacker.new([0x01, 0x02]) + expect(u.get_int).to eq(1) + expect(u.get_int).to eq(2) + expect(u.get_int).to eq(nil) + end + it 'Should unpack negative integers' do u = Unpacker.new([0x40, 0x41, 0x42]) # 0x40 => 1000 0000