Skip to content

Commit

Permalink
Draft out snap builder
Browse files Browse the repository at this point in the history
  • Loading branch information
ChillerDragon committed Feb 21, 2024
1 parent 05867af commit c726756
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 11 deletions.
1 change: 1 addition & 0 deletions lib/packer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

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
Expand Down
61 changes: 61 additions & 0 deletions lib/snapshot/builder.rb
Original file line number Diff line number Diff line change
@@ -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 changes: 30 additions & 0 deletions lib/snapshot/snapshot.rb
Original file line number Diff line number Diff line change
@@ -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
12 changes: 3 additions & 9 deletions lib/snapshot/unpacker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@
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
Expand Down Expand Up @@ -76,6 +68,7 @@ def self.valid_type?(type)
class SnapshotUnpacker
def initialize(client)
@client = client
# @type verbose [Boolean]
@verbose = client.verbose_snap
end

Expand Down Expand Up @@ -181,6 +174,7 @@ def snap_single(chunk)
invalid = false
item_type = u.get_int
id_parsed = u.parsed.last
# @type snap_items [Array<SnapItemBase>]
snap_items = []
while item_type
obj = nil
Expand Down
28 changes: 26 additions & 2 deletions lib/teeworlds_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def seq

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
Expand Down Expand Up @@ -448,7 +448,7 @@ def tick_start_time(tick)
# 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 = []
Expand All @@ -470,6 +470,30 @@ def do_snapshot
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
Expand Down
39 changes: 39 additions & 0 deletions spec/09_snap_builder_spec.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c726756

Please sign in to comment.