Add more hooks to the server (#9)
This commit is contained in:
parent
6de22bae6d
commit
a7895747b6
|
@ -9,6 +9,7 @@ require_relative 'messages/server_settings'
|
||||||
require_relative 'messages/start_info'
|
require_relative 'messages/start_info'
|
||||||
require_relative 'messages/cl_say'
|
require_relative 'messages/cl_say'
|
||||||
require_relative 'messages/cl_emoticon'
|
require_relative 'messages/cl_emoticon'
|
||||||
|
require_relative 'messages/cl_info'
|
||||||
|
|
||||||
class GameServer
|
class GameServer
|
||||||
attr_accessor :pred_game_tick, :ack_game_tick, :map
|
attr_accessor :pred_game_tick, :ack_game_tick, :map
|
||||||
|
@ -41,19 +42,17 @@ class GameServer
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_emoticon(chunk, _packet)
|
def on_emoticon(chunk, _packet)
|
||||||
message = ClEmoticon.new(chunk.data[1..])
|
msg = ClEmoticon.new(chunk.data[1..])
|
||||||
p message
|
return if call_hook(:emote, Context.new(msg, chunk:, packet:)).nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_info(chunk, packet)
|
def on_info(chunk, packet)
|
||||||
u = Unpacker.new(chunk.data[1..])
|
msg = ClInfo.new(chunk.data[1..])
|
||||||
net_version = u.get_string
|
|
||||||
password = u.get_string
|
return if call_hook(:info, Context.new(msg, chunk:, packet:)).nil?
|
||||||
client_version = u.get_int
|
|
||||||
puts "vers=#{net_version} vers=#{client_version} pass=#{password}"
|
|
||||||
|
|
||||||
# TODO: check version and password
|
# TODO: check version and password
|
||||||
|
puts "vers=#{msg.net_version} vers=#{msg.client_version} pass=#{msg.password}"
|
||||||
@server.send_map(packet.client)
|
@server.send_map(packet.client)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -63,6 +62,8 @@ class GameServer
|
||||||
# - server settings
|
# - server settings
|
||||||
# - ready
|
# - ready
|
||||||
#
|
#
|
||||||
|
return if call_hook(:ready, Context.new(nil, chunk: nil, packet:)).nil?
|
||||||
|
|
||||||
@server.send_server_settings(packet.client, ServerSettings.new.to_a)
|
@server.send_server_settings(packet.client, ServerSettings.new.to_a)
|
||||||
@server.send_ready(packet.client)
|
@server.send_ready(packet.client)
|
||||||
end
|
end
|
||||||
|
@ -75,6 +76,8 @@ class GameServer
|
||||||
#
|
#
|
||||||
# We only send ready to enter for now
|
# We only send ready to enter for now
|
||||||
info = StartInfo.new(chunk.data[1..])
|
info = StartInfo.new(chunk.data[1..])
|
||||||
|
return if call_hook(:start_info, Context.new(info, chunk: nil, packet:)).nil?
|
||||||
|
|
||||||
packet.client.player.set_start_info(info)
|
packet.client.player.set_start_info(info)
|
||||||
info_str = info.to_s
|
info_str = info.to_s
|
||||||
puts "got start info: #{info_str}" if @verbose
|
puts "got start info: #{info_str}" if @verbose
|
||||||
|
@ -99,6 +102,8 @@ class GameServer
|
||||||
# - game info
|
# - game info
|
||||||
# - client info
|
# - client info
|
||||||
# - snap single
|
# - snap single
|
||||||
|
return if call_hook(:enter_game, Context.new(nil, chunk: nil, packet:)).nil?
|
||||||
|
|
||||||
packet.client.in_game = true
|
packet.client.in_game = true
|
||||||
@server.send_server_info(packet.client, ServerInfo.new.to_a)
|
@server.send_server_info(packet.client, ServerInfo.new.to_a)
|
||||||
@server.send_game_info(packet.client, GameInfo.new.to_a)
|
@server.send_game_info(packet.client, GameInfo.new.to_a)
|
||||||
|
@ -136,12 +141,17 @@ class GameServer
|
||||||
# - input_timing
|
# - input_timing
|
||||||
# - snap (empty)
|
# - snap (empty)
|
||||||
|
|
||||||
# we do nothing for now
|
msg = ClInput.new(chunk.data[1..])
|
||||||
# TODO: do something
|
return if call_hook(:input, Context.new(msg, chunk:, packet:)).nil?
|
||||||
|
|
||||||
|
dir = msg.direction
|
||||||
|
puts "#{packet.client.player.id} tried to move #{dir}" unless dir.zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_client_drop(client, reason = nil)
|
def on_client_drop(client, reason = nil)
|
||||||
reason = reason.nil? ? '' : " (#{reason})"
|
reason = reason.nil? ? '' : " (#{reason})"
|
||||||
|
return if call_hook(:client_drop, Context.new(nil, chunk:, packet:, reason:)).nil?
|
||||||
|
|
||||||
puts "'#{client.player.name}' left the game#{reason}"
|
puts "'#{client.player.name}' left the game#{reason}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -156,6 +166,8 @@ class GameServer
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_tick
|
def on_tick
|
||||||
|
return if call_hook(:tick, Context.new(nil, chunk:, packet:)).nil?
|
||||||
|
|
||||||
now = Time.now
|
now = Time.now
|
||||||
timeout_ids = []
|
timeout_ids = []
|
||||||
@server.clients.each do |id, client|
|
@server.clients.each do |id, client|
|
||||||
|
|
52
lib/messages/cl_info.rb
Normal file
52
lib/messages/cl_info.rb
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../packer'
|
||||||
|
|
||||||
|
##
|
||||||
|
# ClInfo
|
||||||
|
#
|
||||||
|
# Client -> Server
|
||||||
|
class ClInfo
|
||||||
|
attr_accessor :net_version, :password, :client_version
|
||||||
|
|
||||||
|
def initialize(hash_or_raw)
|
||||||
|
if hash_or_raw.instance_of?(Hash)
|
||||||
|
init_hash(hash_or_raw)
|
||||||
|
else
|
||||||
|
init_raw(hash_or_raw)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_raw(data)
|
||||||
|
u = Unpacker.new(data)
|
||||||
|
@net_version = u.get_string
|
||||||
|
@password = u.get_string
|
||||||
|
@client_version = u.get_int
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_hash(attr)
|
||||||
|
@net_version = attr[:net_version] || 'TODO: fill default'
|
||||||
|
@password = attr[:password] || 'TODO: fill default'
|
||||||
|
@client_version = attr[:client_version] || 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_h
|
||||||
|
{
|
||||||
|
net_version: @net_version,
|
||||||
|
password: @password,
|
||||||
|
client_version: @client_version
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# basically to_network
|
||||||
|
# int array the Client sends to the Server
|
||||||
|
def to_a
|
||||||
|
Packer.pack_str(@net_version) +
|
||||||
|
Packer.pack_str(@password) +
|
||||||
|
Packer.pack_int(@client_version)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
to_h
|
||||||
|
end
|
||||||
|
end
|
96
lib/messages/cl_input.rb
Normal file
96
lib/messages/cl_input.rb
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../packer'
|
||||||
|
|
||||||
|
##
|
||||||
|
# ClInput
|
||||||
|
#
|
||||||
|
# Client -> Server
|
||||||
|
class ClInput
|
||||||
|
attr_accessor :ack_game_tick, :prediction_tick, :size, :direction, :target_x, :target_y, :jump, :fire, :hook, :player_flags, :wanted_weapon, :next_weapon, :prev_weapon, :ping
|
||||||
|
|
||||||
|
def initialize(hash_or_raw)
|
||||||
|
if hash_or_raw.instance_of?(Hash)
|
||||||
|
init_hash(hash_or_raw)
|
||||||
|
else
|
||||||
|
init_raw(hash_or_raw)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_raw(data)
|
||||||
|
u = Unpacker.new(data)
|
||||||
|
@ack_game_tick = u.get_int
|
||||||
|
@prediction_tick = u.get_int
|
||||||
|
@size = u.get_int
|
||||||
|
@direction = u.get_int
|
||||||
|
@target_x = u.get_int
|
||||||
|
@target_y = u.get_int
|
||||||
|
@jump = u.get_int
|
||||||
|
@fire = u.get_int
|
||||||
|
@hook = u.get_int
|
||||||
|
@player_flags = u.get_int
|
||||||
|
@wanted_weapon = u.get_int
|
||||||
|
@next_weapon = u.get_int
|
||||||
|
@prev_weapon = u.get_int
|
||||||
|
@ping = u.get_int
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_hash(attr)
|
||||||
|
@ack_game_tick = attr[:ack_game_tick] || 0
|
||||||
|
@prediction_tick = attr[:prediction_tick] || 0
|
||||||
|
@size = attr[:size] || 0
|
||||||
|
@direction = attr[:direction] || 0
|
||||||
|
@target_x = attr[:target_x] || 0
|
||||||
|
@target_y = attr[:target_y] || 0
|
||||||
|
@jump = attr[:jump] || 0
|
||||||
|
@fire = attr[:fire] || 0
|
||||||
|
@hook = attr[:hook] || 0
|
||||||
|
@player_flags = attr[:player_flags] || 0
|
||||||
|
@wanted_weapon = attr[:wanted_weapon] || 0
|
||||||
|
@next_weapon = attr[:next_weapon] || 0
|
||||||
|
@prev_weapon = attr[:prev_weapon] || 0
|
||||||
|
@ping = attr[:ping] || 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_h
|
||||||
|
{
|
||||||
|
ack_game_tick: @ack_game_tick,
|
||||||
|
prediction_tick: @prediction_tick,
|
||||||
|
size: @size,
|
||||||
|
direction: @direction,
|
||||||
|
target_x: @target_x,
|
||||||
|
target_y: @target_y,
|
||||||
|
jump: @jump,
|
||||||
|
fire: @fire,
|
||||||
|
hook: @hook,
|
||||||
|
player_flags: @player_flags,
|
||||||
|
wanted_weapon: @wanted_weapon,
|
||||||
|
next_weapon: @next_weapon,
|
||||||
|
prev_weapon: @prev_weapon,
|
||||||
|
ping: @ping
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# basically to_network
|
||||||
|
# int array the Client sends to the Server
|
||||||
|
def to_a
|
||||||
|
Packer.pack_int(@ack_game_tick) +
|
||||||
|
Packer.pack_int(@prediction_tick) +
|
||||||
|
Packer.pack_int(@size) +
|
||||||
|
Packer.pack_int(@direction) +
|
||||||
|
Packer.pack_int(@target_x) +
|
||||||
|
Packer.pack_int(@target_y) +
|
||||||
|
Packer.pack_int(@jump) +
|
||||||
|
Packer.pack_int(@fire) +
|
||||||
|
Packer.pack_int(@hook) +
|
||||||
|
Packer.pack_int(@player_flags) +
|
||||||
|
Packer.pack_int(@wanted_weapon) +
|
||||||
|
Packer.pack_int(@next_weapon) +
|
||||||
|
Packer.pack_int(@prev_weapon) +
|
||||||
|
Packer.pack_int(@ping)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
to_h
|
||||||
|
end
|
||||||
|
end
|
|
@ -78,7 +78,15 @@ class TeeworldsServer
|
||||||
chat: [],
|
chat: [],
|
||||||
rcon_auth: [],
|
rcon_auth: [],
|
||||||
rcon_cmd: [],
|
rcon_cmd: [],
|
||||||
shutdown: []
|
shutdown: [],
|
||||||
|
emote: [],
|
||||||
|
info: [],
|
||||||
|
ready: [],
|
||||||
|
start_info: [],
|
||||||
|
enter_game: [],
|
||||||
|
input: [],
|
||||||
|
client_drop: [],
|
||||||
|
tick: []
|
||||||
}
|
}
|
||||||
@thread_running = false
|
@thread_running = false
|
||||||
@is_shutting_down = false
|
@is_shutting_down = false
|
||||||
|
@ -106,6 +114,38 @@ class TeeworldsServer
|
||||||
@hooks[:shutdown].push(block)
|
@hooks[:shutdown].push(block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def on_emote(&block)
|
||||||
|
@hooks[:emote].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_info(&block)
|
||||||
|
@hooks[:info].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_ready(&block)
|
||||||
|
@hooks[:ready].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_start_info(&block)
|
||||||
|
@hooks[:start_info].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_enter_game(&block)
|
||||||
|
@hooks[:enter_game].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_input(&block)
|
||||||
|
@hooks[:input].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_client_drop(&block)
|
||||||
|
@hooks[:client_drop].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_tick(&block)
|
||||||
|
@hooks[:tick].push(block)
|
||||||
|
end
|
||||||
|
|
||||||
def main_loop
|
def main_loop
|
||||||
loop do
|
loop do
|
||||||
break if @is_shutting_down
|
break if @is_shutting_down
|
||||||
|
|
Loading…
Reference in a new issue