teeworlds_network/lib/snapshot/snap_item_base.rb

99 lines
2.1 KiB
Ruby

# frozen_string_literal: true
require_relative '../packer'
require_relative '../network'
class SnapItemBase
attr_reader :notes, :name, :type
attr_accessor :id
def initialize(hash_or_raw)
@fields = @field_names.map do |_|
0
end
@size = @fields.count
@name = self.class.name
@notes = [] # hexdump annotation notes
if hash_or_raw.instance_of?(Hash)
init_hash(hash_or_raw)
elsif hash_or_raw.instance_of?(Unpacker)
init_unpacker(hash_or_raw)
else
init_raw(hash_or_raw)
end
end
def validate
@fields.none?(&:nil?)
end
def size
@fields.size
end
def init_unpacker(u)
@id = u.get_int
p = u.parsed.last
@notes.push([:cyan, p[:pos], p[:len], "id=#{@id}"])
i = 0
@fields.map! do |_|
# TODO: as of right now it can get nil values here
# the fix would be "u.get_int || 0"
# but fixing it would probably make it harder
# to debug invalid data
#
# but do rethink this in a later point please :)
# for now call .validate() everywhere
val = u.get_int
p = u.parsed.last
color = (i % 2).zero? ? :yellow : :pink
desc = @field_names[i]
@notes.push([color, p[:pos], p[:len], "#{desc}=#{val}"])
i += 1
val
end
end
def init_raw(data)
u = Unpacker.new(data)
init_unpacker(u)
end
def init_hash(attr)
@field_names.each_with_index do |name, i|
# direct instance variables work
# but using the @fields array is easier to then pack
# idk how to iterate just the instance variables that i need on packing
# instance_variable_set("@#{name}", attr[name] || 0)
@fields[i] = attr[name] || 0
end
end
def to_h
hash = {}
hash[:id] = @id
@field_names.each_with_index do |name, index|
hash[name] = @fields[index]
end
hash
end
# basically to_network
# int array the server sends to the client
def to_a
arr = []
arr += Packer.pack_int(@type)
arr += Packer.pack_int(@id)
@fields.each do |value|
arr += Packer.pack_int(value)
end
arr
end
def to_s
to_h
end
end