From 2c8e6aeb8f4202aaf8211f771a166b49dbbd740a Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 4 Nov 2022 11:39:41 +0100 Subject: [PATCH] Unhardcode startinfo Thanks a lot to @Learath2 for explaining the int packer to me <3 --- lib/packer.rb | 62 +++++++++++++++++++++++++++++++++++++++++ lib/teeworlds-client.rb | 46 ++++++++++++++++++++++++++---- 2 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 lib/packer.rb diff --git a/lib/packer.rb b/lib/packer.rb new file mode 100644 index 0000000..4acb71d --- /dev/null +++ b/lib/packer.rb @@ -0,0 +1,62 @@ +class Packer + # poor mans int packer + # homebrew not covering + # the full tw fancyness + # + # Format: ESDDDDDD EDDDDDDD EDD... Extended, Data, Sign + def self.pack_int(num) + if num > 63 || num < -63 + # the first byte can fit 6 bits + # because the first two bits are extended and sign + # so if you have a number bigger than 63 + # it needs two bytes + # which are also least significant byte first etc + # so we do not support that YET + # + # the first too big number 64 is represented as those bits + # 10000000 00000001 + # ^^^ ^ ^ ^ + # ||\ / \ / + # || \ / \ / + # || \ \/ + # || \ / + # || \ / + # || \ / + # || \/ + # || /\ + # || / \ + # || / \ + # || 00000001 000000 + # || | + # || v + # || 64 + # || + # |positive + # extended + raise "Numbers greater than 63 are not supported yet" + end + sign = '0' + if num.negative? + sign = '1' + num += 1 + end + num = num.abs + ext = '0' + bits = ext + sign + num.to_s(2).rjust(6, '0') + [bits.to_i(2)] + end +end + +def todo_make_this_rspec_test + p Packer.pack_int(1) == [1] + p Packer.pack_int(16) == [16] + p Packer.pack_int(63) == [63] + + p Packer.pack_int(3) == [3] + p Packer.pack_int(-1) == [64] + p Packer.pack_int(-2) == [65] + + # todo + # p Packer.pack_int(64) == [64] +end + diff --git a/lib/teeworlds-client.rb b/lib/teeworlds-client.rb index fb61e8c..641ce04 100644 --- a/lib/teeworlds-client.rb +++ b/lib/teeworlds-client.rb @@ -10,6 +10,7 @@ require_relative 'packet' require_relative 'chunk' require_relative 'server_info' require_relative 'net_base' +require_relative 'packer' class TwClient attr_reader :state @@ -102,13 +103,48 @@ class TwClient end def send_msg_startinfo() - # todo: build startinfo chunk here + start_info = { + name: "ruby gamer", + clan: "", + country: 1, + body: "spiky", + marking: "duodonny", + decoration: "", + hands: "standard", + feet: "standard", + eyes: "standard", + custom_color_body: 0, + custom_color_marking: 0, + custom_color_decoration: 0, + custom_color_hands: 0, + custom_color_feet: 0, + custom_color_eyes: 0, + color_body: 0, + color_marking: 0, + color_decoration: 0, + color_hands: 0, + color_feet: 0, + color_eyes: 0 + } - # create unused chunk just to bump - # the sequence number ._. - NetChunk.create_vital_header({vital: true}, 1) + data = [] - @netbase.send_packet(MSG_STARTINFO) + start_info.each do |key, value| + if value.class == String + data += value.chars.map(&:ord) + [0x00] + elsif value.class == Integer + data += Packer.pack_int(value) + else + puts "Error: invalid startinfo #{key}: #{value}" + exit 1 + end + end + + @netbase.send_packet( + NetChunk.create_vital_header({vital: true}, data.size + 1) + + [pack_msg_id(NETMSGTYPE_CL_STARTINFO, system: false)] + + data + ) end def send_msg_ready()