Draft out snap builder
This commit is contained in:
parent
05867afa62
commit
c726756b5c
|
@ -8,6 +8,7 @@ SKIP_START_WHITESPACES = 4
|
|||
|
||||
class Packer
|
||||
# Format: ESDDDDDD EDDDDDDD EDD... Extended, Data, Sign
|
||||
# @return [Array<int>]
|
||||
def self.pack_int(num)
|
||||
# the first byte can fit 6 bits
|
||||
# because the first two bits are extended and sign
|
||||
|
|
61
lib/snapshot/builder.rb
Normal file
61
lib/snapshot/builder.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'snapshot'
|
||||
|
||||
# should be merged with SnapItemBase
|
||||
class SnapItem
|
||||
# @param type [Integer] type of the item for example 5 is obj_flag
|
||||
# @param id [Integer] id of said item for characters thats the ClientID
|
||||
# @param fields [Array] array of uncompressed integers
|
||||
# for example [0, 0, 1] for obj_flag
|
||||
# would set
|
||||
# m_X = 0
|
||||
# m_Y = 0
|
||||
# m_Team = 1
|
||||
def initialize(type, id, size, fields)
|
||||
@type = type
|
||||
@id = id
|
||||
@size = size
|
||||
@fields = fields
|
||||
end
|
||||
|
||||
# basically to_network
|
||||
# tee int array that will be sent over
|
||||
# the wire
|
||||
def to_a
|
||||
Packer.pack_int(@type) +
|
||||
Packer.pack_int(@id) +
|
||||
fields.map { |field| Packer.pack_int(field) }
|
||||
end
|
||||
end
|
||||
|
||||
class SnapshotBuilder
|
||||
def initialize
|
||||
@data_size = 0
|
||||
@num_items = 0
|
||||
@items = []
|
||||
end
|
||||
|
||||
##
|
||||
# insert new snap item into the snap
|
||||
#
|
||||
# https://chillerdragon.github.io/teeworlds-protocol/07/snap_items.html
|
||||
#
|
||||
# @param type [Integer] type of the item for example 5 is obj_flag
|
||||
# @param id [Integer] id of said item for characters thats the ClientID
|
||||
# @param fields [Array] array of uncompressed integers
|
||||
# for example [0, 0, 1] for obj_flag
|
||||
# would set
|
||||
# m_X = 0
|
||||
# m_Y = 0
|
||||
# m_Team = 1
|
||||
def new_item(type, id, size, fields)
|
||||
item = SnapItem.new(type, id, size, fields)
|
||||
@items.push(item)
|
||||
end
|
||||
|
||||
# @return [Snapshot]
|
||||
def finish
|
||||
Snapshot.new
|
||||
end
|
||||
end
|
30
lib/snapshot/snapshot.rb
Normal file
30
lib/snapshot/snapshot.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# shared by client and server
|
||||
class Snapshot
|
||||
attr_accessor :game_tick, :items
|
||||
|
||||
def initialize(items)
|
||||
# @type game_tick [Integer]
|
||||
@game_tick = 0
|
||||
# @type items [Array<SnapItemBase>]
|
||||
@items = items
|
||||
end
|
||||
|
||||
# @return [Integer] cyclic redundancy check a checksum of all snap items
|
||||
def crc
|
||||
sum = 0
|
||||
@items.each do |item|
|
||||
sum += item.to_a.sum
|
||||
end
|
||||
sum
|
||||
end
|
||||
|
||||
def to_a
|
||||
data = []
|
||||
@items.each do |item|
|
||||
data += item.to_a
|
||||
end
|
||||
data
|
||||
end
|
||||
end
|
|
@ -19,15 +19,7 @@ require_relative 'events/damage'
|
|||
require_relative 'events/death'
|
||||
require_relative 'events/hammer_hit'
|
||||
require_relative '../packer'
|
||||
|
||||
class Snapshot
|
||||
attr_accessor :game_tick, :items
|
||||
|
||||
def initialize(items)
|
||||
@game_tick = 0
|
||||
@items = items
|
||||
end
|
||||
end
|
||||
require_relative 'snapshot'
|
||||
|
||||
class DDNetSnapItem
|
||||
attr_accessor :notes, :name
|
||||
|
@ -76,6 +68,7 @@ end
|
|||
class SnapshotUnpacker
|
||||
def initialize(client)
|
||||
@client = client
|
||||
# @type verbose [Boolean]
|
||||
@verbose = client.verbose_snap
|
||||
end
|
||||
|
||||
|
@ -181,6 +174,7 @@ class SnapshotUnpacker
|
|||
invalid = false
|
||||
item_type = u.get_int
|
||||
id_parsed = u.parsed.last
|
||||
# @type snap_items [Array<SnapItemBase>]
|
||||
snap_items = []
|
||||
while item_type
|
||||
obj = nil
|
||||
|
|
|
@ -65,7 +65,7 @@ end
|
|||
|
||||
class TeeworldsServer
|
||||
attr_accessor :clients
|
||||
attr_reader :hooks, :shutdown_reason
|
||||
attr_reader :hooks, :shutdown_reason, :current_game_tick
|
||||
|
||||
def initialize(options = {})
|
||||
@verbose = options[:verbose] || false
|
||||
|
@ -448,7 +448,7 @@ class TeeworldsServer
|
|||
# m_GameStartTime + (time_freq()*Tick)/SERVER_TICK_SPEED;
|
||||
end
|
||||
|
||||
def do_snapshot
|
||||
def do_snap_empty
|
||||
delta_tick = -1
|
||||
# DeltaTick = m_aClients[i].m_LastAckedSnapshot;
|
||||
data = []
|
||||
|
@ -470,6 +470,30 @@ class TeeworldsServer
|
|||
end
|
||||
end
|
||||
|
||||
def do_snap_single
|
||||
builder = SnapshotBuilder.new
|
||||
snap = builder.finish
|
||||
items = snap.to_a
|
||||
|
||||
data = []
|
||||
# Game tick Int
|
||||
data += Packer.pack_int(@current_game_tick)
|
||||
# Delta tick Int
|
||||
data += Packer.pack_int(@current_game_tick - delta_tick)
|
||||
# Crc Int
|
||||
data += Packer.pack_int(snap.crc)
|
||||
# Part size Int The size of this part. Meaning the size in bytes of the next raw data field.
|
||||
data += Packer.pack_int(items.size)
|
||||
# Data
|
||||
data += items
|
||||
|
||||
p data
|
||||
end
|
||||
|
||||
def do_snapshot
|
||||
do_snap_empty
|
||||
end
|
||||
|
||||
def get_player_by_id(id)
|
||||
@clients[id]&.player
|
||||
end
|
||||
|
|
39
spec/09_snap_builder_spec.rb
Normal file
39
spec/09_snap_builder_spec.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# require_relative '../lib/snapshot/builder.rb'
|
||||
#
|
||||
# describe 'SnapshotBuilder', :snapshot do
|
||||
# context 'finish' do
|
||||
# it 'Should create correct snap' do
|
||||
# builder = SnapshotBuilder.new
|
||||
# snap = builder.finish
|
||||
# expected_payload = [
|
||||
# 0x00, 0x01, 0x00, 0x0a, # removed_items=0 num_item_deltas=1 _zero=0 type=10 NetObj::Character
|
||||
# 0x00, 0x29, 0x00, 0x0d, # id=0 tick=41 x=0 y=13
|
||||
# 0x00, 0xb3, 0x36, 0x00, # vel_x=0 vel_y=3507 angle=0
|
||||
# 0x00, 0x40, 0x00, 0x00, # direction=0 jumped=-1 hooked_player=0 hook_state=0
|
||||
# 0x00, 0x00, 0x00, 0x00, # hook_tick=0 hook_x=0 hook_y=0 hook_dx=0
|
||||
# 0x00, 0x00, 0x00, 0x00, # hook_dy=0 health=0 armor=0 ammo_count=0
|
||||
# 0x00, 0x00, 0x00, 0x00, # weapon=0 emote=0 attack_tick=0 triggered_events=0
|
||||
# ]
|
||||
# expect(snap.to_a).to eq(expected_payload)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
# >>> snap NETMSG_SNAPSINGLE (8)
|
||||
# id=8 game_tick=1908 delta_tick=38
|
||||
# num_parts=1 part=0 crc=16846 part_size=28
|
||||
#
|
||||
# header:
|
||||
# 11 b4 1d 26 ...& int 17 >> 1 = 8 int 1908 int 38
|
||||
# 8e 87 02 1c .... int 16846 int 28
|
||||
#
|
||||
# payload:
|
||||
# 00 01 00 0a .... removed_items=0 num_item_deltas=1 _zero=0 type=10 NetObj::Character
|
||||
# 00 29 00 0d .).. id=0 tick=41 x=0 y=13
|
||||
# 00 b3 36 00 ..6. vel_x=0 vel_y=3507 angle=0
|
||||
# 00 40 00 00 .@.. direction=0 jumped=-1 hooked_player=0 hook_state=0
|
||||
# 00 00 00 00 .... hook_tick=0 hook_x=0 hook_y=0 hook_dx=0
|
||||
# 00 00 00 00 .... hook_dy=0 health=0 armor=0 ammo_count=0
|
||||
# 00 00 00 00 .... weapon=0 emote=0 attack_tick=0 triggered_events=0
|
Loading…
Reference in a new issue