First draft of sending inputs

Thanks a lot to @Swarfey for his tw-chatonly typescript package
https://www.npmjs.com/package/teeworlds

His simple calculation of the pred time was saving me a lot of time!
This commit is contained in:
ChillerDragon 2022-11-06 20:08:32 +01:00
parent ffbc433b67
commit fff2e9efb0
3 changed files with 103 additions and 17 deletions

View file

@ -34,6 +34,21 @@ class NetChunk
" data: #{str_hex(data)}"
end
def self.create_non_vital_header(data = { size: 0 })
flag_bits = '00'
unused_bits = '00'
size_bits = data[:size].to_s(2).rjust(12, '0')
header_bits =
flag_bits +
size_bits[0..5] +
unused_bits +
size_bits[6..]
header_bits.chars.groups_of(8).map do |eigth_bits|
eigth_bits.join.to_i(2)
end
end
##
# Create int array ready to be send over the network
#

View file

@ -33,11 +33,13 @@ class Context
end
class GameClient
attr_accessor :players
attr_accessor :players, :pred_game_tick, :ack_game_tick
def initialize(client)
@client = client
@players = {}
@ack_game_tick = -1
@pred_game_tick = 0
end
def on_client_info(chunk)
@ -115,6 +117,43 @@ class GameClient
@client.hooks[:rcon_line]&.call(context)
end
def on_snapshot(chunk)
u = Unpacker.new(chunk.data)
u.get_int
# msg = u.get_int
# msg >>= 1
# num_parts = 1
# part = 0
game_tick = u.get_int
# delta_tick = u.get_int
# part_size = 0
# crc = 0
# complete_size = 0
# data = nil
# TODO: state check
# if msg == NETMSG_SNAP
# num_parts = u.get_int
# part = u.get_int
# end
# unless msg == NETMSG_SNAPEMPTY
# crc = u.get_int
# part_size = u.get_int
# end
# TODO: add get_raw(size)
# data = u.get_raw
# ack every snapshot no matter how broken
@ack_game_tick = game_tick
return unless (@pred_game_tick - @ack_game_tick).abs > 10
@pred_game_tick = @ack_game_tick + 1
end
def on_emoticon(chunk); end
def on_map_change(chunk)

View file

@ -77,6 +77,10 @@ class TeeworldsClient
@hooks[:rcon_line] = block
end
def on_on_snapshot(&block)
@hooks[:snapshot] = block
end
def send_chat(str)
@netbase.send_packet(
NetChunk.create_vital_header({ vital: true }, 4 + str.length) +
@ -256,18 +260,37 @@ class TeeworldsClient
end
def send_input
header = [0x10, 0x0A, 0o1] + str_bytes(@token)
random_compressed_input = [
0x4D, 0xE9, 0x48, 0x13, 0xD0, 0x0B, 0x6B, 0xFC, 0xB7, 0x2B, 0x6E, 0x00, 0xBA
]
# this wont work we need to ack the ticks
# and then compress it
# CMsgPacker Msg(NETMSG_INPUT, true);
# Msg.AddInt(m_AckGameTick);
# Msg.AddInt(m_PredTick);
# Msg.AddInt(Size);
msg = header + random_compressed_input
@s.send(msg.pack('C*'), 0, @ip, @port)
inp = {
direction: -1,
target_x: 10,
target_y: 10,
jump: rand(0..1),
fire: 0,
hook: 0,
player_flags: 0,
wanted_weapon: 0,
next_weapon: 0,
prev_weapon: 0
}
data = []
data += Packer.pack_int(@game_client.ack_game_tick)
data += Packer.pack_int(@game_client.pred_game_tick)
data += Packer.pack_int(40) # magic size 40
data += Packer.pack_int(inp[:direction])
data += Packer.pack_int(inp[:target_x])
data += Packer.pack_int(inp[:target_y])
data += Packer.pack_int(inp[:jump])
data += Packer.pack_int(inp[:fire])
data += Packer.pack_int(inp[:hook])
data += Packer.pack_int(inp[:player_flags])
data += Packer.pack_int(inp[:wanted_weapon])
data += Packer.pack_int(inp[:next_weapon])
data += Packer.pack_int(inp[:prev_weapon])
msg = NetChunk.create_non_vital_header(size: data.size + 1) +
[pack_msg_id(NETMSG_INPUT, system: true)] +
data
@netbase.send_packet(msg, 1)
end
def on_msg_token(data)
@ -331,6 +354,8 @@ class TeeworldsClient
# should we be in alert here?
when NETMSG_RCON_LINE
@game_client.on_rcon_line(chunk)
when NETMSG_SNAP, NETMSG_SNAPSINGLE, NETMSG_SNAPEMPTY
@game_client.on_snapshot(chunk)
else
puts "Unsupported system msg: #{chunk.msg}"
exit(1)
@ -385,11 +410,18 @@ class TeeworldsClient
process_server_packet(packet)
end
@ticks += 1
send_ctrl_keepalive if (@ticks % 8).zero?
# if @ticks % 20 == 0
# send_chat("hello world")
# end
if @game_client.ack_game_tick.positive?
now = Time.now
@@last_pred ||= now
diff = now - @@last_pred
# @Swarfey does js setInterval(20) in his lib
# not sure if it makes sense to do a diff > 0.2 here then xd
@game_client.pred_game_tick += 1 if diff > 0.2
end
@ticks += 1
send_input if (@ticks % 20).zero?
end
def connection_loop