mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 01:24:18 +00:00
lots of cool new features :D new master server
This commit is contained in:
parent
f0e8502050
commit
9e4aea97bd
|
@ -238,6 +238,16 @@ weapons {
|
|||
reloadtime 100
|
||||
visual_size 96
|
||||
}
|
||||
|
||||
rocket_backpack {
|
||||
sprite_body sprites.weapons.weapon_hammer_body
|
||||
sprite_cursor sprites.weapons.weapon_hammer_cursor
|
||||
sprite_proj sprites.weapons.weapon_hammer_proj
|
||||
|
||||
recoil 10
|
||||
reloadtime 100
|
||||
visual_size 64
|
||||
}
|
||||
}
|
||||
|
||||
sprites {
|
||||
|
|
58
default.bam
58
default.bam
|
@ -91,43 +91,57 @@ function DataCompile(datafile, scriptfile, headerfile, sourcefile, outputdatafil
|
|||
return {data = outputdatafile, header=headerfile, source=sourcefile}
|
||||
end
|
||||
|
||||
--baselib = Import("src/baselib/baselib.bam")
|
||||
baselib = Import("../baselib/baselib.bam")
|
||||
config_name = "debug"
|
||||
config_ext = ""
|
||||
|
||||
settings = NewSettings()
|
||||
settings.cc.output = function(input, extention)
|
||||
return Path("objs/" .. PathFilename(input) .. config_ext .. extention)
|
||||
end
|
||||
|
||||
baselib_options = {}
|
||||
baselib_options.settings = settings
|
||||
baselib = Import("../baselib/baselib.bam", baselib_options)
|
||||
baselib.apply(settings, "all")
|
||||
|
||||
server_settings = NewSettings()
|
||||
baselib.apply(server_settings, "network")
|
||||
|
||||
settings.cc.debug = 1
|
||||
settings.cc.optimize = 0
|
||||
if family == "windows" then
|
||||
settings.cc.flags = "/wd4244"
|
||||
else
|
||||
settings.cc.flags = "-Wall"
|
||||
end
|
||||
|
||||
settings.cc.includes:add("src")
|
||||
settings.cc.includes:add("../baselib/src/external/zlib")
|
||||
|
||||
serverdata = DataCompile("datasrc/teewars.ds", "datasrc/server.dts", "src/game/server/data.h", "src/game/server/data/data.cpp", "data/server.dat")
|
||||
clientdata = DataCompile("datasrc/teewars.ds", "datasrc/client.dts", "src/game/client/data.h", "src/game/client/data/data.cpp", "data/client.dat")
|
||||
serverdata = DataCompile("datasrc/teewars.ds", "datasrc/server.dts", "src/game/server/data.h", "src/game/server/data/server_data.cpp", "data/server.dat")
|
||||
clientdata = DataCompile("datasrc/teewars.ds", "datasrc/client.dts", "src/game/client/data.h", "src/game/client/data/client_data.cpp", "data/client.dat")
|
||||
|
||||
engine = Compile(settings, Collect("src/engine/*.cpp"))
|
||||
client = Compile(settings, Collect("src/engine/client/*.cpp", "src/engine/client/pnglite/*.c"))
|
||||
server = Compile(settings, Collect("src/engine/server/*.cpp"))
|
||||
game_shared = Compile(settings, Collect("src/game/*.cpp"))
|
||||
game_client = Compile(settings, Collect("src/game/client/*.cpp"), clientdata.source)
|
||||
game_server = Compile(settings, Collect("src/game/server/*.cpp"), serverdata.source)
|
||||
editor = Compile(settings, Collect("src/editor/*.cpp"))
|
||||
function build(config)
|
||||
engine = Compile(settings, Collect("src/engine/*.cpp"))
|
||||
client = Compile(settings, Collect("src/engine/client/*.cpp", "src/engine/client/pnglite/*.c"))
|
||||
server = Compile(settings, Collect("src/engine/server/*.cpp"))
|
||||
masterserver = Compile(settings, Collect("src/mastersrv/*.cpp"))
|
||||
game_shared = Compile(settings, Collect("src/game/*.cpp"))
|
||||
game_client = Compile(settings, Collect("src/game/client/*.cpp"), clientdata.source)
|
||||
game_server = Compile(settings, Collect("src/game/server/*.cpp"), serverdata.source)
|
||||
editor = Compile(settings, Collect("src/editor/*.cpp"))
|
||||
|
||||
crapnet = Compile(settings, Collect("src/crapnet/*.cpp"))
|
||||
crapnet = Compile(settings, Collect("src/crapnet/*.cpp"))
|
||||
|
||||
client_exe = Link(settings, "teewars", engine, client, editor, game_shared, game_client)
|
||||
server_exe = Link(server_settings, "teewars_srv", engine, server, game_shared, game_server)
|
||||
-- editor_exe = Link(settings, "editor", engine, game_shared, editor)
|
||||
crapnet_exe = Link(server_settings, "crapnet", crapnet)
|
||||
client_exe = Link(settings, "teewars"..config_ext, engine, client, editor, game_shared, game_client)
|
||||
server_exe = Link(server_settings, "teewars_srv"..config_ext, engine, server, game_shared, game_server)
|
||||
masterserver_exe = Link(server_settings, "mastersrv"..config_ext, masterserver, engine)
|
||||
-- editor_exe = Link(settings, "editor", engine, game_shared, editor)
|
||||
crapnet_exe = Link(server_settings, "crapnet"..config_ext, crapnet)
|
||||
|
||||
Target(PseudoTarget("client", client_exe, clientdata.data))
|
||||
Target(PseudoTarget("server", server_exe, serverdata.data))
|
||||
Target(PseudoTarget("tools", crapnet_exe))
|
||||
-- Target(PseudoTarget("editor", editor_exe))
|
||||
Target(PseudoTarget("client", client_exe, clientdata.data))
|
||||
Target(PseudoTarget("server", server_exe, serverdata.data))
|
||||
Target(PseudoTarget("masterserver", masterserver_exe))
|
||||
Target(PseudoTarget("tools", crapnet_exe))
|
||||
-- Target(PseudoTarget("editor", editor_exe))
|
||||
end
|
||||
|
||||
build("debug")
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
baselib = Import("../../baselib/baselib.bam")
|
||||
--scheme = Import("scheme/scheme.bam")
|
||||
|
||||
settings = NewSettings()
|
||||
baselib.use(settings)
|
||||
--scheme.use(settings)
|
||||
settings.cc.includes:add("include")
|
||||
--settings.cc.includes:add("include/python")
|
||||
--settings.cc.frameworks:add("Python")
|
||||
--//settings.linker.libs:add("/opt/local/lib/python2.5/config/libpython2.5.a")
|
||||
--settings.linker.frameworks:add("Python")
|
||||
|
||||
src = Collect("src/*.cpp")
|
||||
objs = Compile(settings, src)
|
||||
exe = Link(settings, "server", objs)
|
||||
|
||||
--Target(baselib.lib)
|
||||
Target(exe)
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
typedef int int32;
|
||||
|
||||
#endif
|
|
@ -1,48 +0,0 @@
|
|||
#ifndef _MASTERSERVER_H
|
||||
#define _MASTERSERVER_H
|
||||
|
||||
#include <baselib/network.h>
|
||||
#include "serverinfo.h"
|
||||
|
||||
using namespace baselib;
|
||||
|
||||
#define HEARTBEAT_SIZE 216
|
||||
#define HEARTBEAT_SIGNATURE 'TWHB'
|
||||
#define HEARTBEAT_LIFETIME 10
|
||||
#define MAXSERVERS 1024
|
||||
#define SERVERINFOOUT_SIZE 212
|
||||
#define SERVERINFOHEADER_SIZE 12
|
||||
#define MASTERSERVER_VERSION 0
|
||||
|
||||
class CMasterServer
|
||||
{
|
||||
CServerInfo m_Servers[MAXSERVERS];
|
||||
int m_ServerCount;
|
||||
socket_udp4 m_UDPSocket;
|
||||
socket_tcp4 m_TCPSocket;
|
||||
int m_CurrentTime;
|
||||
char m_ServerListPacket[MAXSERVERS * SERVERINFOOUT_SIZE + SERVERINFOHEADER_SIZE];
|
||||
int m_ServerListPacketSize;
|
||||
bool m_ServerListPacketIsOld;
|
||||
|
||||
void ListenForServerListPolls();
|
||||
void BuildServerListPacket();
|
||||
void ListenForHeartBeats();
|
||||
void ProcessHeartBeat(CServerInfo info);
|
||||
CServerInfo *FindServerInfo(int32 ip, int32 port);
|
||||
CServerInfo *GetUnusedSlot();
|
||||
void CleanUpServerList();
|
||||
public:
|
||||
CMasterServer()
|
||||
{
|
||||
m_ServerCount = 0;
|
||||
m_ServerListPacketIsOld = true;
|
||||
}
|
||||
|
||||
void Init(int port);
|
||||
void Shutdown();
|
||||
|
||||
void Tick();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef _NETWORK_H
|
||||
#define _NETWORK_H
|
||||
|
||||
#include <cstring>
|
||||
#include "common.h"
|
||||
|
||||
char *WriteInt32(char *buffer, int32 value);
|
||||
char *WriteFixedString(char *buffer, const char *string, int strlen);
|
||||
|
||||
char *ReadInt32(char *buffer, int32 *value);
|
||||
char *ReadFixedString(char *buffer, char *string, int strlen);
|
||||
|
||||
#endif
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef _SERVERINFO_H
|
||||
#define _SERVERINFO_H
|
||||
|
||||
#include <baselib/network.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "network.h"
|
||||
|
||||
class CServerInfo
|
||||
{
|
||||
int32 m_Version;
|
||||
int32 m_IP;
|
||||
int32 m_Port;
|
||||
int32 m_Players;
|
||||
int32 m_MaxPlayers;
|
||||
char m_Name[128];
|
||||
char m_Map[64];
|
||||
|
||||
int m_LastRefresh;
|
||||
|
||||
public:
|
||||
int32 IP() const { return m_IP; }
|
||||
int32 Port() const { return m_Port; }
|
||||
int32 Players() const { return m_Players; }
|
||||
int32 MaxPlayers() const { return m_MaxPlayers; };
|
||||
const char *Name() const { return m_Name; }
|
||||
const char *Map() const { return m_Map; }
|
||||
|
||||
void Refresh(int time) { m_LastRefresh = time; }
|
||||
int LastRefresh() { return m_LastRefresh; }
|
||||
|
||||
void SetAddress(baselib::netaddr4 *addr)
|
||||
{
|
||||
m_IP = addr->ip[0] << 24;
|
||||
m_IP |= addr->ip[1] << 16;
|
||||
m_IP |= addr->ip[2] << 8;
|
||||
m_IP |= addr->ip[3];
|
||||
|
||||
m_Port = addr->port;
|
||||
}
|
||||
|
||||
char *Serialize(char *buffer) const
|
||||
{
|
||||
buffer = WriteInt32(buffer, m_Version);
|
||||
buffer = WriteInt32(buffer, m_IP);
|
||||
buffer = WriteInt32(buffer, m_Port);
|
||||
buffer = WriteInt32(buffer, m_Players);
|
||||
buffer = WriteInt32(buffer, m_MaxPlayers);
|
||||
buffer = WriteFixedString(buffer, m_Name, sizeof(m_Name));
|
||||
buffer = WriteFixedString(buffer, m_Map, sizeof(m_Map));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *Deserialize(char *buffer)
|
||||
{
|
||||
buffer = ReadInt32(buffer, &m_Version);
|
||||
buffer = ReadInt32(buffer, &m_IP);
|
||||
buffer = ReadInt32(buffer, &m_Port);
|
||||
buffer = ReadInt32(buffer, &m_Players);
|
||||
buffer = ReadInt32(buffer, &m_MaxPlayers);
|
||||
buffer = ReadFixedString(buffer, m_Name, sizeof(m_Name));
|
||||
buffer = ReadFixedString(buffer, m_Map, sizeof(m_Map));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "masterserver.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
puts("Usage: masterserver <port> (this will bind the server to the port specified (both udp and tcp).");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
CMasterServer masterServer;
|
||||
masterServer.Init(port);
|
||||
|
||||
while (1)
|
||||
{
|
||||
masterServer.Tick();
|
||||
|
||||
thread_sleep(10);
|
||||
}
|
||||
|
||||
masterServer.Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
#include <ctime>
|
||||
|
||||
#include "masterserver.h"
|
||||
|
||||
void CMasterServer::Init(int port)
|
||||
{
|
||||
netaddr4 addr(0, 0, 0, 0, port);
|
||||
addr.port = port;
|
||||
|
||||
net_init();
|
||||
m_UDPSocket.open(port);
|
||||
m_TCPSocket.open(&addr);
|
||||
m_TCPSocket.set_non_blocking();
|
||||
m_TCPSocket.listen();
|
||||
}
|
||||
|
||||
void CMasterServer::Shutdown()
|
||||
{
|
||||
m_UDPSocket.close();
|
||||
}
|
||||
|
||||
void CMasterServer::Tick()
|
||||
{
|
||||
m_CurrentTime = time(NULL);
|
||||
|
||||
ListenForHeartBeats();
|
||||
ListenForServerListPolls();
|
||||
|
||||
CleanUpServerList();
|
||||
}
|
||||
|
||||
void CMasterServer::ListenForHeartBeats()
|
||||
{
|
||||
netaddr4 from;
|
||||
char data[1024];
|
||||
int dataSize;
|
||||
|
||||
// read udp data while there is data to read :)
|
||||
while ((dataSize = m_UDPSocket.recv(&from, (char *)data, sizeof(data))) > 0)
|
||||
{
|
||||
// compare the received data size to the expected size
|
||||
if (dataSize == HEARTBEAT_SIZE)
|
||||
{
|
||||
char *d = data;
|
||||
int32 signature;
|
||||
d = ReadInt32(d, &signature);
|
||||
|
||||
// make sure the signature is correct
|
||||
if (signature == HEARTBEAT_SIGNATURE)
|
||||
{
|
||||
CServerInfo info;
|
||||
info.Deserialize(d);
|
||||
|
||||
from.port = 8303;
|
||||
info.SetAddress(&from);
|
||||
|
||||
dbg_msg("got heartbeat", "IP: %i.%i.%i.%i:%i", (int)from.ip[0], (int)from.ip[1], (int)from.ip[2], (int)from.ip[3], from.port);
|
||||
|
||||
dbg_msg("refresh", "okay. server count: %i", m_ServerCount);
|
||||
|
||||
ProcessHeartBeat(info);
|
||||
}
|
||||
else
|
||||
{} // unexpected signature
|
||||
}
|
||||
else
|
||||
{} // unknown data received
|
||||
}
|
||||
}
|
||||
|
||||
void CMasterServer::ProcessHeartBeat(CServerInfo info)
|
||||
{
|
||||
// find the corresponding server info
|
||||
CServerInfo *serverInfo = FindServerInfo(info.IP(), info.Port());
|
||||
|
||||
// if it isn't in the list already, try to get an unused slot
|
||||
if (!serverInfo)
|
||||
serverInfo = GetUnusedSlot();
|
||||
|
||||
// if we STILL don't have one, we're out of luck.
|
||||
if (!serverInfo)
|
||||
return;
|
||||
|
||||
*serverInfo = info;
|
||||
serverInfo->Refresh(m_CurrentTime);
|
||||
|
||||
// mark the server list packet as old
|
||||
m_ServerListPacketIsOld = true;
|
||||
}
|
||||
|
||||
CServerInfo *CMasterServer::FindServerInfo(int32 ip, int32 port)
|
||||
{
|
||||
// for now, just loop over the array
|
||||
for (int i = 0; i < m_ServerCount; i++)
|
||||
{
|
||||
CServerInfo *info = &m_Servers[i];
|
||||
if (info->IP() == ip && info->Port() == port)
|
||||
return info;
|
||||
}
|
||||
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
CServerInfo *CMasterServer::GetUnusedSlot()
|
||||
{
|
||||
if (m_ServerCount == MAXSERVERS)
|
||||
return 0x0;
|
||||
else
|
||||
return &m_Servers[m_ServerCount++];
|
||||
}
|
||||
|
||||
void CMasterServer::CleanUpServerList()
|
||||
{
|
||||
for (int i = 0; i < m_ServerCount; i++)
|
||||
{
|
||||
CServerInfo *serverInfo = &m_Servers[i];
|
||||
|
||||
// check if it's time to remove it from the list
|
||||
if (serverInfo->LastRefresh() + HEARTBEAT_LIFETIME < m_CurrentTime)
|
||||
{
|
||||
if (i + 1 == m_ServerCount)
|
||||
{
|
||||
// if we're at the last one, just decrease m_ServerCount
|
||||
--m_ServerCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, copy the last slot here and then decrease i and m_ServerCount
|
||||
*serverInfo = m_Servers[m_ServerCount - 1];
|
||||
--i;
|
||||
--m_ServerCount;
|
||||
}
|
||||
|
||||
// mark the server list packet as old and outdated
|
||||
m_ServerListPacketIsOld = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMasterServer::ListenForServerListPolls()
|
||||
{
|
||||
socket_tcp4 client;
|
||||
|
||||
// accept clients while there are clients to be accepted
|
||||
while (m_TCPSocket.accept(&client))
|
||||
{
|
||||
// maybe we've prepared the packet already... it'd be silly to do it twice
|
||||
if (m_ServerListPacketIsOld)
|
||||
{
|
||||
BuildServerListPacket();
|
||||
}
|
||||
|
||||
// send the server list and then close the socket
|
||||
client.send(m_ServerListPacket, m_ServerListPacketSize);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
void CMasterServer::BuildServerListPacket()
|
||||
{
|
||||
char *d = m_ServerListPacket;
|
||||
|
||||
d = WriteInt32(d, 'TWSL');
|
||||
d = WriteInt32(d, MASTERSERVER_VERSION);
|
||||
|
||||
d = WriteInt32(d, m_ServerCount);
|
||||
|
||||
for (int i = 0; i < m_ServerCount; i++)
|
||||
{
|
||||
CServerInfo *info = &m_Servers[i];
|
||||
d = info->Serialize(d);
|
||||
}
|
||||
|
||||
m_ServerListPacketSize = d - m_ServerListPacket;
|
||||
m_ServerListPacketIsOld = false;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#include <cstring>
|
||||
#include "common.h"
|
||||
#include "network.h"
|
||||
|
||||
char *WriteInt32(char *buffer, int32 value)
|
||||
{
|
||||
buffer[0] = value >> 24;
|
||||
buffer[1] = value >> 16;
|
||||
buffer[2] = value >> 8;
|
||||
buffer[3] = value;
|
||||
|
||||
return buffer + sizeof(int32);
|
||||
}
|
||||
|
||||
char *WriteFixedString(char *buffer, const char *string, int strlen)
|
||||
{
|
||||
memcpy(buffer, string, strlen);
|
||||
|
||||
return buffer + strlen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *ReadInt32(char *buffer, int32 *value)
|
||||
{
|
||||
*value = buffer[0] << 24;
|
||||
*value |= buffer[1] << 16;
|
||||
*value |= buffer[2] << 8;
|
||||
*value |= buffer[3];
|
||||
|
||||
return buffer + sizeof(int32);
|
||||
}
|
||||
|
||||
char *ReadFixedString(char *buffer, char *string, int strlen)
|
||||
{
|
||||
memcpy(string, buffer, strlen);
|
||||
|
||||
return buffer + strlen;
|
||||
}
|
|
@ -476,7 +476,7 @@ class translator:
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void patch_ptr(char **ptr, char *base)
|
||||
static void patch_ptr(char **ptr, char *base)
|
||||
{
|
||||
*ptr = base+(size_t)(*ptr);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <engine/config.h>
|
||||
#include <engine/network.h>
|
||||
|
||||
#include <mastersrv/mastersrv.h>
|
||||
|
||||
using namespace baselib;
|
||||
|
||||
// --- input wrappers ---
|
||||
|
@ -156,15 +158,92 @@ int client_send_msg()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
server_info infos[MAX_SERVERS];
|
||||
int64 request_times[MAX_SERVERS];
|
||||
netaddr4 addresses[MAX_SERVERS];
|
||||
int num;
|
||||
} servers;
|
||||
|
||||
static netaddr4 master_server;
|
||||
|
||||
int client_serverbrowse_getlist(server_info **serverlist)
|
||||
{
|
||||
*serverlist = servers.infos;
|
||||
return servers.num;
|
||||
}
|
||||
|
||||
void client_serverbrowse_refresh()
|
||||
{
|
||||
dbg_msg("client", "requesting server list");
|
||||
NETPACKET packet;
|
||||
packet.client_id = -1;
|
||||
packet.address = master_server;
|
||||
packet.flags = PACKETFLAG_CONNLESS;
|
||||
packet.data_size = sizeof(SERVERBROWSE_GETLIST);
|
||||
packet.data = SERVERBROWSE_GETLIST;
|
||||
net.send(&packet);
|
||||
|
||||
// reset the list
|
||||
servers.num = 0;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
STATE_OFFLINE,
|
||||
STATE_CONNECTING,
|
||||
STATE_LOADING,
|
||||
STATE_ONLINE,
|
||||
STATE_BROKEN,
|
||||
STATE_QUIT,
|
||||
};
|
||||
|
||||
static netaddr4 server_address;
|
||||
|
||||
static int state;
|
||||
static int get_state() { return state; }
|
||||
static void set_state(int s)
|
||||
{
|
||||
dbg_msg("game", "state change. last=%d current=%d", state, s);
|
||||
state = s;
|
||||
}
|
||||
|
||||
|
||||
void client_connect(const char *server_address_str)
|
||||
{
|
||||
char buf[512];
|
||||
strncpy(buf, server_address_str, 512);
|
||||
|
||||
const char *port_str = 0;
|
||||
for(int k = 0; buf[k]; k++)
|
||||
{
|
||||
if(buf[k] == ':')
|
||||
{
|
||||
port_str = &(buf[k+1]);
|
||||
buf[k] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int port = 8303;
|
||||
if(port_str)
|
||||
port = atoi(port_str);
|
||||
|
||||
if(net_host_lookup(buf, port, &server_address) != 0)
|
||||
dbg_msg("client", "could not find the address of %s, connecting to localhost", buf);
|
||||
|
||||
net.connect(&server_address);
|
||||
set_state(STATE_CONNECTING);
|
||||
}
|
||||
|
||||
// --- client ---
|
||||
// TODO: remove this class
|
||||
class client
|
||||
{
|
||||
public:
|
||||
|
||||
//socket_udp4 socket;
|
||||
//connection conn;
|
||||
int64 reconnect_timer;
|
||||
int info_request_begin;
|
||||
int info_request_end;
|
||||
|
||||
int snapshot_part;
|
||||
|
||||
|
@ -173,24 +252,6 @@ public:
|
|||
// data to hold three snapshots
|
||||
// previous,
|
||||
|
||||
enum
|
||||
{
|
||||
STATE_OFFLINE,
|
||||
STATE_CONNECTING,
|
||||
STATE_LOADING,
|
||||
STATE_ONLINE,
|
||||
STATE_BROKEN,
|
||||
STATE_QUIT,
|
||||
};
|
||||
|
||||
int state;
|
||||
int get_state() { return state; }
|
||||
void set_state(int s)
|
||||
{
|
||||
dbg_msg("game", "state change. last=%d current=%d", state, s);
|
||||
state = s;
|
||||
}
|
||||
|
||||
void send_info()
|
||||
{
|
||||
recived_snapshots = 0;
|
||||
|
@ -242,12 +303,6 @@ public:
|
|||
map_unload();
|
||||
}
|
||||
|
||||
void connect(netaddr4 *server_address)
|
||||
{
|
||||
net.connect(server_address);
|
||||
set_state(STATE_CONNECTING);
|
||||
}
|
||||
|
||||
bool load_data()
|
||||
{
|
||||
debug_font = gfx_load_texture("data/debug_font.png");
|
||||
|
@ -293,13 +348,11 @@ public:
|
|||
}
|
||||
else if (get_state() != STATE_CONNECTING && get_state() != STATE_LOADING)
|
||||
{
|
||||
netaddr4 server_address;
|
||||
int status = modmenu_render(&server_address);
|
||||
//netaddr4 server_address;
|
||||
int status = modmenu_render();
|
||||
|
||||
if (status == -1)
|
||||
set_state(STATE_QUIT);
|
||||
else if (status)
|
||||
connect(&server_address);
|
||||
}
|
||||
else if (get_state() == STATE_CONNECTING || get_state() == STATE_LOADING)
|
||||
{
|
||||
|
@ -332,7 +385,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void run(netaddr4 *server_address)
|
||||
void run(const char *direct_connect_server)
|
||||
{
|
||||
local_start_time = time_get();
|
||||
snapshot_part = 0;
|
||||
|
@ -356,20 +409,16 @@ public:
|
|||
// init menu
|
||||
modmenu_init();
|
||||
|
||||
net.open(0);
|
||||
|
||||
// open socket
|
||||
/*
|
||||
if(!socket.open(0))
|
||||
{
|
||||
dbg_msg("network/client", "failed to open socket");
|
||||
return;
|
||||
}*/
|
||||
net.open(0, 0);
|
||||
|
||||
//
|
||||
net_host_lookup(MASTERSERVER_ADDRESS, MASTERSERVER_PORT, &master_server);
|
||||
|
||||
// connect to the server if wanted
|
||||
if(server_address)
|
||||
connect(server_address);
|
||||
|
||||
if(direct_connect_server)
|
||||
client_connect(direct_connect_server);
|
||||
|
||||
//int64 inputs_per_second = 50;
|
||||
//int64 time_per_input = time_freq()/inputs_per_second;
|
||||
int64 game_starttime = time_get();
|
||||
|
@ -413,6 +462,9 @@ public:
|
|||
// pump the network
|
||||
pump_network();
|
||||
|
||||
// update the server browser
|
||||
serverbrowse_update();
|
||||
|
||||
// render
|
||||
render();
|
||||
|
||||
|
@ -457,146 +509,235 @@ public:
|
|||
send_error(msg);
|
||||
set_state(STATE_BROKEN);
|
||||
}
|
||||
|
||||
void serverbrowse_request(int id)
|
||||
{
|
||||
dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
|
||||
servers.addresses[id].ip[0], servers.addresses[id].ip[1], servers.addresses[id].ip[2],
|
||||
servers.addresses[id].ip[3], servers.addresses[id].port);
|
||||
NETPACKET packet;
|
||||
packet.client_id = -1;
|
||||
packet.address = servers.addresses[id];
|
||||
packet.flags = PACKETFLAG_CONNLESS;
|
||||
packet.data_size = sizeof(SERVERBROWSE_GETINFO);
|
||||
packet.data = SERVERBROWSE_GETINFO;
|
||||
net.send(&packet);
|
||||
servers.request_times[id] = time_get();
|
||||
}
|
||||
|
||||
void serverbrowse_update()
|
||||
{
|
||||
int64 timeout = time_freq();
|
||||
int64 now = time_get();
|
||||
int max_requests = 10;
|
||||
|
||||
// timeout old requests
|
||||
while(info_request_begin < servers.num && info_request_begin < info_request_end)
|
||||
{
|
||||
if(now > servers.request_times[info_request_begin]+timeout)
|
||||
info_request_begin++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// send new requests
|
||||
while(info_request_end < servers.num && info_request_end-info_request_begin < max_requests)
|
||||
{
|
||||
serverbrowse_request(info_request_end);
|
||||
info_request_end++;
|
||||
}
|
||||
}
|
||||
|
||||
void process_packet(NETPACKET *packet)
|
||||
{
|
||||
int sys;
|
||||
int msg = msg_unpack_start(packet->data, packet->data_size, &sys);
|
||||
if(sys)
|
||||
if(packet->client_id == -1)
|
||||
{
|
||||
// system message
|
||||
if(msg == NETMSG_MAP)
|
||||
// connectionlesss
|
||||
if(packet->data_size >= (int)sizeof(SERVERBROWSE_LIST) &&
|
||||
memcmp(packet->data, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0)
|
||||
{
|
||||
const char *map = msg_unpack_string();
|
||||
dbg_msg("client/network", "connection accepted, map=%s", map);
|
||||
set_state(STATE_LOADING);
|
||||
|
||||
if(map_load(map))
|
||||
// server listing
|
||||
int size = packet->data_size-sizeof(SERVERBROWSE_LIST);
|
||||
mem_copy(servers.addresses, (char*)packet->data+sizeof(SERVERBROWSE_LIST), size);
|
||||
servers.num = size/sizeof(NETADDR4);
|
||||
|
||||
info_request_begin = 0;
|
||||
info_request_end = 0;
|
||||
|
||||
for(int i = 0; i < servers.num; i++)
|
||||
{
|
||||
modc_entergame();
|
||||
send_entergame();
|
||||
dbg_msg("client/network", "loading done");
|
||||
// now we will wait for two snapshots
|
||||
// to finish the connection
|
||||
}
|
||||
else
|
||||
{
|
||||
error("failure to load map");
|
||||
servers.infos[i].num_players = 0;
|
||||
servers.infos[i].max_players = 0;
|
||||
servers.infos[i].latency = 999;
|
||||
sprintf(servers.infos[i].address, "%d.%d.%d.%d:%d",
|
||||
servers.addresses[i].ip[0], servers.addresses[i].ip[1], servers.addresses[i].ip[2],
|
||||
servers.addresses[i].ip[3], servers.addresses[i].port);
|
||||
}
|
||||
}
|
||||
else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPSMALL || msg == NETMSG_SNAPEMPTY)
|
||||
|
||||
if(packet->data_size >= (int)sizeof(SERVERBROWSE_INFO) &&
|
||||
memcmp(packet->data, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
|
||||
{
|
||||
//dbg_msg("client/network", "got snapshot");
|
||||
int game_tick = msg_unpack_int();
|
||||
int delta_tick = game_tick-msg_unpack_int();
|
||||
int num_parts = 1;
|
||||
int part = 0;
|
||||
int part_size = 0;
|
||||
// we got ze info
|
||||
data_unpacker unpacker;
|
||||
unpacker.reset((unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO));
|
||||
|
||||
if(msg == NETMSG_SNAP)
|
||||
for(int i = 0; i < servers.num; i++)
|
||||
{
|
||||
num_parts = msg_unpack_int();
|
||||
part = msg_unpack_int();
|
||||
}
|
||||
|
||||
if(msg != NETMSG_SNAPEMPTY)
|
||||
part_size = msg_unpack_int();
|
||||
|
||||
if(snapshot_part == part)
|
||||
{
|
||||
// TODO: clean this up abit
|
||||
const char *d = (const char *)msg_unpack_raw(part_size);
|
||||
mem_copy((char*)snapshots[SNAP_INCOMMING] + part*MAX_SNAPSHOT_PACKSIZE, d, part_size);
|
||||
snapshot_part++;
|
||||
|
||||
if(snapshot_part == num_parts)
|
||||
if(net_addr4_cmp(&servers.addresses[i], &packet->address) == 0)
|
||||
{
|
||||
snapshot *tmp = snapshots[SNAP_PREV];
|
||||
snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
|
||||
snapshots[SNAP_CURRENT] = tmp;
|
||||
current_tick = game_tick;
|
||||
|
||||
// decompress snapshot
|
||||
void *deltadata = snapshot_empty_delta();
|
||||
int deltasize = sizeof(int)*3;
|
||||
|
||||
unsigned char tmpbuffer[MAX_SNAPSHOT_SIZE];
|
||||
unsigned char tmpbuffer2[MAX_SNAPSHOT_SIZE];
|
||||
if(part_size)
|
||||
{
|
||||
int compsize = zerobit_decompress(snapshots[SNAP_INCOMMING], part_size, tmpbuffer);
|
||||
int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
|
||||
deltadata = tmpbuffer2;
|
||||
deltasize = intsize;
|
||||
}
|
||||
|
||||
// find snapshot that we should use as delta
|
||||
static snapshot emptysnap;
|
||||
emptysnap.data_size = 0;
|
||||
emptysnap.num_items = 0;
|
||||
|
||||
snapshot *deltashot = &emptysnap;
|
||||
int deltashot_size;
|
||||
|
||||
if(delta_tick >= 0)
|
||||
{
|
||||
void *delta_data;
|
||||
deltashot_size = snapshots_new.get(delta_tick, &delta_data);
|
||||
if(deltashot_size >= 0)
|
||||
{
|
||||
deltashot = (snapshot *)delta_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: handle this
|
||||
dbg_msg("client", "error, couldn't find the delta snapshot");
|
||||
}
|
||||
}
|
||||
|
||||
int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)snapshots[SNAP_CURRENT], deltadata, deltasize);
|
||||
//snapshot *shot = (snapshot *)snapshots[SNAP_CURRENT];
|
||||
|
||||
// purge old snapshots
|
||||
snapshots_new.purge_until(delta_tick);
|
||||
snapshots_new.purge_until(game_tick-50); // TODO: change this to server tickrate
|
||||
|
||||
// add new
|
||||
snapshots_new.add(game_tick, snapsize, snapshots[SNAP_CURRENT]);
|
||||
|
||||
// apply snapshot, cycle pointers
|
||||
recived_snapshots++;
|
||||
snapshot_start_time = time_get();
|
||||
|
||||
// we got two snapshots until we see us self as connected
|
||||
if(recived_snapshots == 2)
|
||||
{
|
||||
local_start_time = time_get();
|
||||
set_state(STATE_ONLINE);
|
||||
}
|
||||
|
||||
if(recived_snapshots > 2)
|
||||
modc_newsnapshot();
|
||||
|
||||
snapshot_part = 0;
|
||||
|
||||
// ack snapshot
|
||||
msg_pack_start_system(NETMSG_SNAPACK, 0);
|
||||
msg_pack_int(game_tick);
|
||||
msg_pack_end();
|
||||
client_send_msg();
|
||||
strncpy(servers.infos[i].name, unpacker.get_string(), 128);
|
||||
strncpy(servers.infos[i].map, unpacker.get_string(), 128);
|
||||
servers.infos[i].max_players = unpacker.get_int();
|
||||
servers.infos[i].num_players = unpacker.get_int();
|
||||
servers.infos[i].latency = ((time_get() - servers.request_times[i])*1000)/time_freq();
|
||||
dbg_msg("client", "got server info");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_msg("client", "snapshot reset!");
|
||||
snapshot_part = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// game message
|
||||
modc_message(msg);
|
||||
|
||||
int sys;
|
||||
int msg = msg_unpack_start(packet->data, packet->data_size, &sys);
|
||||
if(sys)
|
||||
{
|
||||
// system message
|
||||
if(msg == NETMSG_MAP)
|
||||
{
|
||||
const char *map = msg_unpack_string();
|
||||
dbg_msg("client/network", "connection accepted, map=%s", map);
|
||||
set_state(STATE_LOADING);
|
||||
|
||||
if(map_load(map))
|
||||
{
|
||||
modc_entergame();
|
||||
send_entergame();
|
||||
dbg_msg("client/network", "loading done");
|
||||
// now we will wait for two snapshots
|
||||
// to finish the connection
|
||||
}
|
||||
else
|
||||
{
|
||||
error("failure to load map");
|
||||
}
|
||||
}
|
||||
else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPSMALL || msg == NETMSG_SNAPEMPTY)
|
||||
{
|
||||
//dbg_msg("client/network", "got snapshot");
|
||||
int game_tick = msg_unpack_int();
|
||||
int delta_tick = game_tick-msg_unpack_int();
|
||||
int num_parts = 1;
|
||||
int part = 0;
|
||||
int part_size = 0;
|
||||
|
||||
if(msg == NETMSG_SNAP)
|
||||
{
|
||||
num_parts = msg_unpack_int();
|
||||
part = msg_unpack_int();
|
||||
}
|
||||
|
||||
if(msg != NETMSG_SNAPEMPTY)
|
||||
part_size = msg_unpack_int();
|
||||
|
||||
if(snapshot_part == part)
|
||||
{
|
||||
// TODO: clean this up abit
|
||||
const char *d = (const char *)msg_unpack_raw(part_size);
|
||||
mem_copy((char*)snapshots[SNAP_INCOMMING] + part*MAX_SNAPSHOT_PACKSIZE, d, part_size);
|
||||
snapshot_part++;
|
||||
|
||||
if(snapshot_part == num_parts)
|
||||
{
|
||||
snapshot *tmp = snapshots[SNAP_PREV];
|
||||
snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
|
||||
snapshots[SNAP_CURRENT] = tmp;
|
||||
current_tick = game_tick;
|
||||
|
||||
// decompress snapshot
|
||||
void *deltadata = snapshot_empty_delta();
|
||||
int deltasize = sizeof(int)*3;
|
||||
|
||||
unsigned char tmpbuffer[MAX_SNAPSHOT_SIZE];
|
||||
unsigned char tmpbuffer2[MAX_SNAPSHOT_SIZE];
|
||||
if(part_size)
|
||||
{
|
||||
int compsize = zerobit_decompress(snapshots[SNAP_INCOMMING], part_size, tmpbuffer);
|
||||
int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
|
||||
deltadata = tmpbuffer2;
|
||||
deltasize = intsize;
|
||||
}
|
||||
|
||||
// find snapshot that we should use as delta
|
||||
static snapshot emptysnap;
|
||||
emptysnap.data_size = 0;
|
||||
emptysnap.num_items = 0;
|
||||
|
||||
snapshot *deltashot = &emptysnap;
|
||||
int deltashot_size;
|
||||
|
||||
if(delta_tick >= 0)
|
||||
{
|
||||
void *delta_data;
|
||||
deltashot_size = snapshots_new.get(delta_tick, &delta_data);
|
||||
if(deltashot_size >= 0)
|
||||
{
|
||||
deltashot = (snapshot *)delta_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: handle this
|
||||
dbg_msg("client", "error, couldn't find the delta snapshot");
|
||||
}
|
||||
}
|
||||
|
||||
int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)snapshots[SNAP_CURRENT], deltadata, deltasize);
|
||||
//snapshot *shot = (snapshot *)snapshots[SNAP_CURRENT];
|
||||
|
||||
// purge old snapshots
|
||||
snapshots_new.purge_until(delta_tick);
|
||||
snapshots_new.purge_until(game_tick-50); // TODO: change this to server tickrate
|
||||
|
||||
// add new
|
||||
snapshots_new.add(game_tick, snapsize, snapshots[SNAP_CURRENT]);
|
||||
|
||||
// apply snapshot, cycle pointers
|
||||
recived_snapshots++;
|
||||
snapshot_start_time = time_get();
|
||||
|
||||
// we got two snapshots until we see us self as connected
|
||||
if(recived_snapshots == 2)
|
||||
{
|
||||
local_start_time = time_get();
|
||||
set_state(STATE_ONLINE);
|
||||
}
|
||||
|
||||
if(recived_snapshots > 2)
|
||||
modc_newsnapshot();
|
||||
|
||||
snapshot_part = 0;
|
||||
|
||||
// ack snapshot
|
||||
msg_pack_start_system(NETMSG_SNAPACK, 0);
|
||||
msg_pack_int(game_tick);
|
||||
msg_pack_end();
|
||||
client_send_msg();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_msg("client", "snapshot reset!");
|
||||
snapshot_part = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// game message
|
||||
modc_message(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,11 +777,8 @@ int main(int argc, char **argv)
|
|||
config_reset();
|
||||
config_load("teewars.cfg");
|
||||
|
||||
const char *direct_connect_server = 0x0;
|
||||
snd_set_master_volume(config.volume / 255.0f);
|
||||
|
||||
netaddr4 server_address(127, 0, 0, 1, 8303);
|
||||
//const char *name = "nameless jerk";
|
||||
bool connect_at_once = false;
|
||||
bool editor = false;
|
||||
|
||||
// init network, need to be done first so we can do lookups
|
||||
|
@ -653,24 +791,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
// -c SERVER:PORT
|
||||
i++;
|
||||
const char *port_str = 0;
|
||||
for(int k = 0; argv[i][k]; k++)
|
||||
{
|
||||
if(argv[i][k] == ':')
|
||||
{
|
||||
port_str = &(argv[i][k+1]);
|
||||
argv[i][k] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int port = 8303;
|
||||
if(port_str)
|
||||
port = atoi(port_str);
|
||||
|
||||
if(net_host_lookup(argv[i], port, &server_address) != 0)
|
||||
dbg_msg("main", "could not find the address of %s, connecting to localhost", argv[i]);
|
||||
else
|
||||
connect_at_once = true;
|
||||
direct_connect_server = argv[i];
|
||||
}
|
||||
else if(argv[i][0] == '-' && argv[i][1] == 'n' && argv[i][2] == 0 && argc - i > 1)
|
||||
{
|
||||
|
@ -695,7 +816,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
// start the client
|
||||
client c;
|
||||
c.run(connect_at_once ? &server_address : 0x0);
|
||||
c.run(direct_connect_server);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -689,7 +689,7 @@ void modmenu_shutdown();
|
|||
Function: modmenu_render
|
||||
Called every frame to let the menu render it self.
|
||||
*/
|
||||
int modmenu_render(void *server_address);
|
||||
int modmenu_render();
|
||||
|
||||
|
||||
|
||||
|
@ -752,9 +752,19 @@ float gfx_pretty_text_width(float size, const char *text);
|
|||
void mods_message(int msg, int client_id);
|
||||
void modc_message(int msg);
|
||||
|
||||
#define MASTER_SERVER_ADDRESS "master.teewars.com"
|
||||
#define MASTER_SERVER_PORT 8300
|
||||
struct server_info
|
||||
{
|
||||
int max_players;
|
||||
int num_players;
|
||||
int latency; // in ms
|
||||
char name[128];
|
||||
char map[128];
|
||||
char address[128];
|
||||
};
|
||||
|
||||
void client_connect(const char *address);
|
||||
|
||||
void client_serverbrowse_refresh();
|
||||
int client_serverbrowse_getlist(server_info **servers);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,20 +18,6 @@
|
|||
unsigned char crc[2]; 6
|
||||
*/
|
||||
|
||||
|
||||
// move
|
||||
static int net_addr4_cmp(const NETADDR4 *a, const NETADDR4 *b)
|
||||
{
|
||||
if( a->ip[0] != b->ip[0] ||
|
||||
a->ip[1] != b->ip[1] ||
|
||||
a->ip[2] != b->ip[2] ||
|
||||
a->ip[3] != b->ip[3] ||
|
||||
a->port != b->port
|
||||
)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
NETWORK_VERSION = 1,
|
||||
|
@ -51,7 +37,7 @@ enum
|
|||
NETWORK_PACKETFLAG_CLOSE=0x04,
|
||||
NETWORK_PACKETFLAG_VITAL=0x08,
|
||||
NETWORK_PACKETFLAG_RESEND=0x10,
|
||||
//NETWORK_PACKETFLAG_STATELESS=0x20,
|
||||
NETWORK_PACKETFLAG_CONNLESS=0x20,
|
||||
};
|
||||
|
||||
struct NETPACKETDATA
|
||||
|
@ -208,7 +194,7 @@ static void conn_send(NETCONNECTION *conn, int flags, int data_size, const void
|
|||
p.data_size = data_size;
|
||||
p.data = (unsigned char *)data;
|
||||
p.first_send_time = time_get();
|
||||
|
||||
|
||||
if(flags&NETWORK_PACKETFLAG_VITAL)
|
||||
{
|
||||
// save packet if we need to resend
|
||||
|
@ -321,7 +307,7 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr)
|
|||
|
||||
static void conn_update(NETCONNECTION *conn)
|
||||
{
|
||||
if(conn->state == NETWORK_CONNSTATE_ERROR)
|
||||
if(conn->state == NETWORK_CONNSTATE_OFFLINE || conn->state == NETWORK_CONNSTATE_ERROR)
|
||||
return;
|
||||
|
||||
// check for timeout
|
||||
|
@ -479,58 +465,71 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet)
|
|||
int r = check_packet(s->recv_buffer, bytes, &data);
|
||||
if(r == 0)
|
||||
{
|
||||
// ok packet, process it
|
||||
if(data.flags == NETWORK_PACKETFLAG_CONNECT)
|
||||
if(data.flags&NETWORK_PACKETFLAG_CONNLESS)
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
// check if we already got this client
|
||||
for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(s->slots[i].conn.state != NETWORK_CONNSTATE_OFFLINE &&
|
||||
net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0)
|
||||
{
|
||||
found = 1; // silent ignore.. we got this client already
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// client that wants to connect
|
||||
if(!found)
|
||||
{
|
||||
for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(s->slots[i].conn.state == NETWORK_CONNSTATE_OFFLINE)
|
||||
{
|
||||
conn_feed(&s->slots[i].conn, &data, &addr);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
// TODO: send error
|
||||
}
|
||||
// connection less packets
|
||||
packet->client_id = -1;
|
||||
packet->address = addr;
|
||||
packet->flags = PACKETFLAG_CONNLESS;
|
||||
packet->data_size = data.data_size;
|
||||
packet->data = data.data;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// find matching slot
|
||||
for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
|
||||
// ok packet, process it
|
||||
if(data.flags == NETWORK_PACKETFLAG_CONNECT)
|
||||
{
|
||||
if(net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0)
|
||||
int found = 0;
|
||||
|
||||
// check if we already got this client
|
||||
for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(conn_feed(&s->slots[i].conn, &data, &addr))
|
||||
if(s->slots[i].conn.state != NETWORK_CONNSTATE_OFFLINE &&
|
||||
net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0)
|
||||
{
|
||||
if(data.data_size)
|
||||
found = 1; // silent ignore.. we got this client already
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// client that wants to connect
|
||||
if(!found)
|
||||
{
|
||||
for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(s->slots[i].conn.state == NETWORK_CONNSTATE_OFFLINE)
|
||||
{
|
||||
packet->client_id = i;
|
||||
packet->address = addr;
|
||||
packet->flags = 0;
|
||||
packet->data_size = data.data_size;
|
||||
packet->data = data.data;
|
||||
return 1;
|
||||
conn_feed(&s->slots[i].conn, &data, &addr);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
// TODO: send error
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// find matching slot
|
||||
for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0)
|
||||
{
|
||||
if(conn_feed(&s->slots[i].conn, &data, &addr))
|
||||
{
|
||||
if(data.data_size)
|
||||
{
|
||||
packet->client_id = i;
|
||||
packet->address = addr;
|
||||
packet->flags = 0;
|
||||
packet->data_size = data.data_size;
|
||||
packet->data = data.data;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +539,7 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet)
|
|||
else
|
||||
{
|
||||
// errornous packet, drop it
|
||||
dbg_msg("server", "crazy packet");
|
||||
}
|
||||
|
||||
// read header
|
||||
|
@ -551,10 +551,27 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet)
|
|||
|
||||
int net_server_send(NETSERVER *s, NETPACKET *packet)
|
||||
{
|
||||
// TODO: insert stuff for stateless stuff
|
||||
dbg_assert(packet->client_id >= 0, "errornous client id");
|
||||
dbg_assert(packet->client_id < NETWORK_MAX_CLIENTS, "errornous client id");
|
||||
conn_send(&s->slots[packet->client_id].conn, 0, packet->data_size, packet->data);
|
||||
if(packet->flags&PACKETFLAG_CONNLESS)
|
||||
{
|
||||
// send connectionless packet
|
||||
NETPACKETDATA p;
|
||||
p.ID[0] = 'T';
|
||||
p.ID[1] = 'W';
|
||||
p.version = NETWORK_VERSION;
|
||||
p.flags = NETWORK_PACKETFLAG_CONNLESS;
|
||||
p.seq = 0;
|
||||
p.ack = 0;
|
||||
p.crc = 0;
|
||||
p.data_size = packet->data_size;
|
||||
p.data = (unsigned char *)packet->data;
|
||||
send_packet(s->socket, &packet->address, &p);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_assert(packet->client_id >= 0, "errornous client id");
|
||||
dbg_assert(packet->client_id < NETWORK_MAX_CLIENTS, "errornous client id");
|
||||
conn_send(&s->slots[packet->client_id].conn, 0, packet->data_size, packet->data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -574,11 +591,11 @@ void net_server_stats(NETSERVER *s, NETSTATS *stats)
|
|||
}
|
||||
|
||||
//
|
||||
NETCLIENT *net_client_open(int flags)
|
||||
NETCLIENT *net_client_open(int port, int flags)
|
||||
{
|
||||
NETCLIENT *client = (NETCLIENT *)mem_alloc(sizeof(NETCLIENT), 1);
|
||||
mem_zero(client, sizeof(NETCLIENT));
|
||||
client->socket = net_udp4_create(0);
|
||||
client->socket = net_udp4_create(port);
|
||||
conn_init(&client->conn, client->socket);
|
||||
return client;
|
||||
}
|
||||
|
@ -626,23 +643,37 @@ int net_client_recv(NETCLIENT *c, NETPACKET *packet)
|
|||
|
||||
NETPACKETDATA data;
|
||||
int r = check_packet(c->recv_buffer, bytes, &data);
|
||||
if(r == 0 && conn_feed(&c->conn, &data, &addr))
|
||||
{
|
||||
// fill in packet
|
||||
packet->client_id = 0;
|
||||
packet->address = addr;
|
||||
packet->flags = 0;
|
||||
packet->data_size = data.data_size;
|
||||
packet->data = data.data;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// errornous packet, drop it
|
||||
}
|
||||
|
||||
// read header
|
||||
// do checksum
|
||||
if(r == 0)
|
||||
{
|
||||
if(data.flags&NETWORK_PACKETFLAG_CONNLESS)
|
||||
{
|
||||
// connection less packets
|
||||
packet->client_id = -1;
|
||||
packet->address = addr;
|
||||
packet->flags = PACKETFLAG_CONNLESS;
|
||||
packet->data_size = data.data_size;
|
||||
packet->data = data.data;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(conn_feed(&c->conn, &data, &addr))
|
||||
{
|
||||
// fill in packet
|
||||
packet->client_id = 0;
|
||||
packet->address = addr;
|
||||
packet->flags = 0;
|
||||
packet->data_size = data.data_size;
|
||||
packet->data = data.data;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// errornous packet, drop it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -650,9 +681,27 @@ int net_client_recv(NETCLIENT *c, NETPACKET *packet)
|
|||
|
||||
int net_client_send(NETCLIENT *c, NETPACKET *packet)
|
||||
{
|
||||
// TODO: insert stuff for stateless stuff
|
||||
dbg_assert(packet->client_id == 0, "errornous client id");
|
||||
conn_send(&c->conn, 0, packet->data_size, packet->data);
|
||||
if(packet->flags&PACKETFLAG_CONNLESS)
|
||||
{
|
||||
// send connectionless packet
|
||||
NETPACKETDATA p;
|
||||
p.ID[0] = 'T';
|
||||
p.ID[1] = 'W';
|
||||
p.version = NETWORK_VERSION;
|
||||
p.flags = NETWORK_PACKETFLAG_CONNLESS;
|
||||
p.seq = 0;
|
||||
p.ack = 0;
|
||||
p.crc = 0;
|
||||
p.data_size = packet->data_size;
|
||||
p.data = (unsigned char *)packet->data;
|
||||
send_packet(c->socket, &packet->address, &p);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: insert stuff for stateless stuff
|
||||
dbg_assert(packet->client_id == 0, "errornous client id");
|
||||
conn_send(&c->conn, 0, packet->data_size, packet->data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ enum
|
|||
{
|
||||
NETFLAG_ALLOWSTATELESS=1,
|
||||
PACKETFLAG_VITAL=1,
|
||||
PACKETFLAG_CONNLESS=2,
|
||||
|
||||
NETSTATE_OFFLINE=0,
|
||||
NETSTATE_CONNECTING,
|
||||
|
@ -46,7 +47,7 @@ int net_server_delclient(NETSERVER *s); // -1 when no more, else, client id
|
|||
void net_server_stats(NETSERVER *s, NETSTATS *stats);
|
||||
|
||||
// client side
|
||||
NETCLIENT *net_client_open(int flags);
|
||||
NETCLIENT *net_client_open(int port, int flags);
|
||||
int net_client_disconnect(NETCLIENT *c, const char *reason);
|
||||
int net_client_connect(NETCLIENT *c, NETADDR4 *addr);
|
||||
int net_client_recv(NETCLIENT *c, NETPACKET *packet);
|
||||
|
@ -88,7 +89,7 @@ public:
|
|||
net_client() : ptr(0) {}
|
||||
~net_client() { close(); }
|
||||
|
||||
int open(int flags) { ptr = net_client_open(flags); return ptr != 0; }
|
||||
int open(int port, int flags) { ptr = net_client_open(port, flags); return ptr != 0; }
|
||||
int close() { int r = net_client_close(ptr); ptr = 0; return r; }
|
||||
|
||||
int connect(NETADDR4 *addr) { return net_client_connect(ptr, addr); }
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <engine/network.h>
|
||||
#include <engine/config.h>
|
||||
|
||||
#include <mastersrv/mastersrv.h>
|
||||
|
||||
namespace baselib {}
|
||||
using namespace baselib;
|
||||
|
@ -162,11 +163,14 @@ public:
|
|||
//for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
//dbg_msg("network/server", "\t%d: %d", i, clients[i].state);
|
||||
|
||||
if (net_host_lookup(MASTER_SERVER_ADDRESS, MASTER_SERVER_PORT, &master_server) != 0)
|
||||
if (net_host_lookup(MASTERSERVER_ADDRESS, MASTERSERVER_PORT, &master_server) != 0)
|
||||
{
|
||||
// TODO: fix me
|
||||
//master_server = netaddr4(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
dbg_msg("server", "masterserver = %d.%d.%d.%d:%d",
|
||||
master_server.ip[0], master_server.ip[1], master_server.ip[2], master_server.ip[3], master_server.port);
|
||||
|
||||
mods_init();
|
||||
|
||||
|
@ -178,13 +182,15 @@ public:
|
|||
lastheartbeat = 0;
|
||||
|
||||
int64 reporttime = time_get();
|
||||
int64 reportinterval = time_freq()*3;
|
||||
int reportinterval = 3;
|
||||
//int64 reportinterval = time_freq()*3;
|
||||
|
||||
int64 simulationtime = 0;
|
||||
int64 snaptime = 0;
|
||||
int64 networktime = 0;
|
||||
int64 totaltime = 0;
|
||||
|
||||
while(1)
|
||||
while(true)
|
||||
{
|
||||
int64 t = time_get();
|
||||
if(t-lasttick > time_per_tick)
|
||||
|
@ -204,23 +210,11 @@ public:
|
|||
lasttick += time_per_tick;
|
||||
}
|
||||
|
||||
if(send_heartbeats)
|
||||
//if(send_heartbeats)
|
||||
{
|
||||
if (t > lastheartbeat+time_per_heartbeat)
|
||||
{
|
||||
if (master_server.port != 0)
|
||||
{
|
||||
int players = 0;
|
||||
|
||||
for (int i = 0; i < MAX_CLIENTS; i++)
|
||||
if (!clients[i].is_empty())
|
||||
players++;
|
||||
|
||||
// TODO: fix me
|
||||
netaddr4 me(127, 0, 0, 0, 8303);
|
||||
//send_heartbeat(0, &me, players, MAX_CLIENTS, server_name, mapname);
|
||||
}
|
||||
|
||||
send_heartbeat();
|
||||
lastheartbeat = t+time_per_heartbeat;
|
||||
}
|
||||
}
|
||||
|
@ -233,37 +227,21 @@ public:
|
|||
|
||||
if(reporttime < time_get())
|
||||
{
|
||||
int64 totaltime = simulationtime+snaptime+networktime;
|
||||
dbg_msg("server/report", "sim=%.02fms snap=%.02fms net=%.02fms total=%.02fms load=%.02f%%",
|
||||
simulationtime/(float)reportinterval*1000,
|
||||
snaptime/(float)reportinterval*1000,
|
||||
networktime/(float)reportinterval*1000,
|
||||
totaltime/(float)reportinterval*1000,
|
||||
(simulationtime+snaptime+networktime)/(float)reportinterval*100.0f);
|
||||
|
||||
unsigned sent_total=0, recv_total=0;
|
||||
/*
|
||||
for (int i = 0; i < MAX_CLIENTS; i++)
|
||||
if (!clients[i].is_empty())
|
||||
{
|
||||
unsigned s,r;
|
||||
clients[i].conn.counter_get(&s,&r);
|
||||
clients[i].conn.counter_reset();
|
||||
sent_total += s;
|
||||
recv_total += r;
|
||||
}
|
||||
*/
|
||||
|
||||
dbg_msg("server/report", "biggestsnap=%d send=%d recv=%d",
|
||||
biggest_snapshot, sent_total/3, recv_total/3);
|
||||
(simulationtime/reportinterval)/(double)time_freq()*1000,
|
||||
(snaptime/reportinterval)/(double)time_freq()*1000,
|
||||
(networktime/reportinterval)/(double)time_freq()*1000,
|
||||
(totaltime/reportinterval)/(double)time_freq()*1000,
|
||||
(totaltime)/reportinterval/(double)time_freq()*100.0f);
|
||||
|
||||
simulationtime = 0;
|
||||
snaptime = 0;
|
||||
networktime = 0;
|
||||
totaltime = 0;
|
||||
|
||||
reporttime += reportinterval;
|
||||
reporttime += time_freq()*reportinterval;
|
||||
}
|
||||
|
||||
totaltime += time_get()-t;
|
||||
thread_sleep(1);
|
||||
}
|
||||
|
||||
|
@ -382,6 +360,18 @@ public:
|
|||
msg_pack_end();
|
||||
server_send_msg(cid);
|
||||
}
|
||||
|
||||
void send_heartbeat()
|
||||
{
|
||||
dbg_msg("server", "sending heartbeat");
|
||||
NETPACKET packet;
|
||||
packet.client_id = -1;
|
||||
packet.address = master_server;
|
||||
packet.flags = PACKETFLAG_CONNLESS;
|
||||
packet.data_size = sizeof(SERVERBROWSE_HEARTBEAT);
|
||||
packet.data = SERVERBROWSE_HEARTBEAT;
|
||||
net.send(&packet);
|
||||
}
|
||||
|
||||
void drop(int cid, const char *reason)
|
||||
{
|
||||
|
@ -450,6 +440,27 @@ public:
|
|||
drop(clientId, "client timedout");
|
||||
}
|
||||
|
||||
void send_serverinfo(NETADDR4 *addr)
|
||||
{
|
||||
dbg_msg("server", "sending heartbeat");
|
||||
NETPACKET packet;
|
||||
|
||||
data_packer packer;
|
||||
packer.reset();
|
||||
packer.add_raw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
|
||||
packer.add_string(server_name, 128);
|
||||
packer.add_string(map_name, 128);
|
||||
packer.add_int(8); // max_players
|
||||
packer.add_int(0); // num_players
|
||||
|
||||
packet.client_id = -1;
|
||||
packet.address = *addr;
|
||||
packet.flags = PACKETFLAG_CONNLESS;
|
||||
packet.data_size = packer.size();
|
||||
packet.data = packer.data();
|
||||
net.send(&packet);
|
||||
}
|
||||
|
||||
void pump_network()
|
||||
{
|
||||
net.update();
|
||||
|
@ -458,10 +469,16 @@ public:
|
|||
NETPACKET packet;
|
||||
while(net.recv(&packet))
|
||||
{
|
||||
|
||||
if(packet.client_id == -1)
|
||||
{
|
||||
// stateless
|
||||
if(packet.data_size == sizeof(SERVERBROWSE_GETINFO) &&
|
||||
memcmp(packet.data, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
|
||||
{
|
||||
dbg_msg("server", "info requested");
|
||||
send_serverinfo(&packet.address);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
process_client_packet(&packet);
|
||||
|
|
|
@ -201,7 +201,7 @@ public:
|
|||
{
|
||||
i->pos = pos;
|
||||
i->life = 0.75f;
|
||||
i->dir = dir;
|
||||
i->dir = dir*-1;
|
||||
i->startangle = (( (float)rand()/(float)RAND_MAX) - 1.0f) * 2.0f * pi;
|
||||
}
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ void modc_init()
|
|||
{
|
||||
// load the data container
|
||||
data = load_data_container("data/client.dat");
|
||||
|
||||
|
||||
// load sounds
|
||||
for(int s = 0; s < data->num_sounds; s++)
|
||||
for(int i = 0; i < data->sounds[s].num_sounds; i++)
|
||||
|
@ -505,15 +505,17 @@ static void render_projectile(obj_projectile *prev, obj_projectile *current)
|
|||
gfx_quads_begin();
|
||||
|
||||
select_sprite(data->weapons[current->type%data->num_weapons].sprite_proj);
|
||||
vec2 vel(current->vx, current->vy);
|
||||
vec2 vel = mix(vec2(prev->vx, prev->vy), vec2(current->vx, current->vy), client_intratick());
|
||||
vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
|
||||
|
||||
// TODO: interpolare angle aswell
|
||||
if(length(vel) > 0.00001f)
|
||||
gfx_quads_setrotation(get_angle(vel));
|
||||
else
|
||||
gfx_quads_setrotation(0);
|
||||
|
||||
vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
|
||||
// TODO: do this, but nice
|
||||
//temp_system.new_particle(pos, vec2(0,0), 0.3f, 14.0f, 0, 0.95f);
|
||||
|
||||
gfx_quads_draw(pos.x, pos.y,32,32);
|
||||
gfx_quads_setrotation(0);
|
||||
gfx_quads_end();
|
||||
|
@ -898,7 +900,8 @@ void modc_render()
|
|||
if(mouse_pos.x < 0)
|
||||
a = a+pi;
|
||||
|
||||
input.angle = (int)(a*256.0f);
|
||||
input.target_x = (int)mouse_pos.x; //(int)(a*256.0f);
|
||||
input.target_y = (int)mouse_pos.y; //(int)(a*256.0f);
|
||||
input.activeweapon = -1;
|
||||
|
||||
if(!chat_active)
|
||||
|
@ -912,10 +915,8 @@ void modc_render()
|
|||
input.blink = inp_key_pressed('S');
|
||||
|
||||
// Weapon switching
|
||||
input.activeweapon = inp_key_pressed('1') ? 0 : input.activeweapon;
|
||||
input.activeweapon = inp_key_pressed('2') ? 1 : input.activeweapon;
|
||||
input.activeweapon = inp_key_pressed('3') ? 2 : input.activeweapon;
|
||||
input.activeweapon = inp_key_pressed('4') ? 3 : input.activeweapon;
|
||||
for(int i = 0; i < 8; i++)
|
||||
input.activeweapon = inp_key_pressed('1'+i) ? i : input.activeweapon;
|
||||
}
|
||||
|
||||
snap_input(&input, sizeof(input));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <baselib/system.h>
|
||||
#include <baselib/input.h>
|
||||
#include <baselib/network.h>
|
||||
#include <baselib/math.h>
|
||||
|
||||
#include <engine/interface.h>
|
||||
#include <engine/versions.h>
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include <engine/config.h>
|
||||
|
||||
#include "data.h"
|
||||
#include <mastersrv/mastersrv.h>
|
||||
|
||||
extern data_container *data;
|
||||
|
||||
|
@ -234,6 +236,7 @@ void draw_teewars_button(void *id, const char *text, int checked, float x, float
|
|||
ui_do_label(x + w/2 - text_width/2, y, text, 46);
|
||||
}
|
||||
|
||||
/*
|
||||
struct server_info
|
||||
{
|
||||
int version;
|
||||
|
@ -242,11 +245,10 @@ struct server_info
|
|||
netaddr4 address;
|
||||
char name[129];
|
||||
char map[65];
|
||||
};
|
||||
};*/
|
||||
|
||||
struct server_list
|
||||
{
|
||||
server_info infos[10];
|
||||
int active_count, info_count;
|
||||
int scroll_index;
|
||||
int selected_index;
|
||||
|
@ -555,7 +557,7 @@ int do_scroll_bar_vert(void *id, float x, float y, float height, int steps, int
|
|||
return r;
|
||||
}
|
||||
|
||||
static int do_server_list(server_list *list, float x, float y, int visible_items)
|
||||
static int do_server_list(float x, float y, int *scroll_index, int *selected_index, int visible_items)
|
||||
{
|
||||
const float spacing = 3.f;
|
||||
const float item_height = 28;
|
||||
|
@ -563,22 +565,27 @@ static int do_server_list(server_list *list, float x, float y, int visible_items
|
|||
const float real_width = item_width + 20;
|
||||
const float real_height = item_height * visible_items + spacing * (visible_items - 1);
|
||||
|
||||
server_info *servers;
|
||||
int num_servers = client_serverbrowse_getlist(&servers);
|
||||
|
||||
int r = -1;
|
||||
|
||||
for (int i = 0; i < visible_items; i++)
|
||||
{
|
||||
int item_index = i + list->scroll_index;
|
||||
if (item_index >= list->active_count);
|
||||
int item_index = i + *scroll_index;
|
||||
if (item_index >= num_servers)
|
||||
;
|
||||
//ui_do_image(empty_item_texture, x, y + i * item_height + i * spacing, item_width, item_height);
|
||||
else
|
||||
{
|
||||
server_info *item = &list->infos[item_index];
|
||||
server_info *item = &servers[item_index];
|
||||
|
||||
bool clicked = false;
|
||||
clicked = ui_do_button(item, item->name, 0, x, y + i * item_height + i * spacing, item_width, item_height, draw_menu_button, (list->selected_index == item_index) ? (void *)1 : 0);
|
||||
clicked = ui_do_button(item, item->name, 0, x, y + i * item_height + i * spacing, item_width, item_height,
|
||||
draw_menu_button, (*selected_index == item_index) ? (void *)1 : 0);
|
||||
|
||||
char temp[64]; // plenty of extra room so we don't get sad :o
|
||||
sprintf(temp, "%i/%i", item->players, item->max_players);
|
||||
sprintf(temp, "%i/%i %3d", item->num_players, item->max_players, item->latency);
|
||||
|
||||
ui_do_label(x + 600, y + i * item_height + i * spacing, temp, item_height);
|
||||
ui_do_label(x + 360, y + i * item_height + i * spacing, item->map, item_height);
|
||||
|
@ -586,136 +593,17 @@ static int do_server_list(server_list *list, float x, float y, int visible_items
|
|||
if (clicked)
|
||||
{
|
||||
r = item_index;
|
||||
list->selected_index = item_index;
|
||||
*selected_index = item_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list->scroll_index = do_scroll_bar_vert(&list->scroll_index, x + real_width - 16, y, real_height, list->active_count - visible_items, list->scroll_index);
|
||||
*scroll_index = do_scroll_bar_vert(scroll_index, x + real_width - 16, y, real_height,
|
||||
min(num_servers - visible_items, 0), *scroll_index);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *read_int(char *buffer, int *value)
|
||||
{
|
||||
*value = buffer[0] << 24;
|
||||
*value |= buffer[1] << 16;
|
||||
*value |= buffer[2] << 8;
|
||||
*value |= buffer[3];
|
||||
|
||||
return buffer + 4;
|
||||
}
|
||||
|
||||
static char *read_netaddr(char *buffer, netaddr4 *addr)
|
||||
{
|
||||
addr->ip[0] = *buffer++;
|
||||
addr->ip[1] = *buffer++;
|
||||
addr->ip[2] = *buffer++;
|
||||
addr->ip[3] = *buffer++;
|
||||
|
||||
int port;
|
||||
buffer = read_int(buffer, &port);
|
||||
|
||||
addr->port = port;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void refresh_list(server_list *list)
|
||||
{
|
||||
netaddr4 addr;
|
||||
netaddr4 me(0, 0, 0, 0, 0);
|
||||
|
||||
list->selected_index = -1;
|
||||
|
||||
if (net_host_lookup(MASTER_SERVER_ADDRESS, MASTER_SERVER_PORT, &addr) == 0)
|
||||
{
|
||||
socket_tcp4 sock;
|
||||
sock.open(&me);
|
||||
|
||||
//sock.set_non_blocking();
|
||||
|
||||
// try and connect with a timeout of 1 second
|
||||
if (sock.connect_non_blocking(&addr))
|
||||
{
|
||||
char data[256];
|
||||
int total_received = 0;
|
||||
int received;
|
||||
|
||||
int master_server_version = -1;
|
||||
int server_count = -1;
|
||||
|
||||
// read header
|
||||
while (total_received < 12 && (received = sock.recv(data + total_received, 12 - total_received)) > 0)
|
||||
total_received += received;
|
||||
|
||||
// see if we have the header
|
||||
if (total_received == 12)
|
||||
{
|
||||
int signature;
|
||||
read_int(data, &signature);
|
||||
|
||||
// check signature
|
||||
if(signature == 'TWSL')
|
||||
{
|
||||
read_int(data + 4, &master_server_version);
|
||||
read_int(data + 8, &server_count);
|
||||
|
||||
// TODO: handle master server version O.o
|
||||
|
||||
const int server_info_size = 212;
|
||||
|
||||
list->active_count = 0;
|
||||
|
||||
for (int i = 0; i < server_count; i++)
|
||||
{
|
||||
total_received = 0;
|
||||
|
||||
// read data for a server
|
||||
while (sock.is_connected() && total_received < server_info_size && (received = sock.recv(data + total_received, server_info_size - total_received)) > 0)
|
||||
total_received += received;
|
||||
|
||||
// check if we got enough data
|
||||
if (total_received == server_info_size)
|
||||
{
|
||||
char *d = data;
|
||||
|
||||
server_info *info = &list->infos[i];
|
||||
|
||||
d = read_int(d, &info->version);
|
||||
d = read_netaddr(d, &info->address);
|
||||
|
||||
//dbg_msg("menu/got_serverinfo", "IP: %i.%i.%i.%i:%i", (int)info->address.ip[0], (int)info->address.ip[1], (int)info->address.ip[2], (int)info->address.ip[3], info->address.port);
|
||||
|
||||
d = read_int(d, &info->players);
|
||||
d = read_int(d, &info->max_players);
|
||||
memcpy(info->name, d, 128);
|
||||
d += 128;
|
||||
memcpy(info->map, d, 64);
|
||||
|
||||
// let's be safe.
|
||||
info->name[128] = 0;
|
||||
info->map[64] = 0;
|
||||
|
||||
++list->active_count;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (list->scroll_index >= list->active_count)
|
||||
list->scroll_index = list->active_count - 1;
|
||||
|
||||
if (list->scroll_index < 0)
|
||||
list->scroll_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
SCREEN_MAIN,
|
||||
|
@ -737,41 +625,45 @@ const float row2_y = row1_y + 40;
|
|||
const float row3_y = row2_y + 40;
|
||||
const float row4_y = row3_y + 40;
|
||||
|
||||
static int main_render(netaddr4 *server_address)
|
||||
static int main_render()
|
||||
{
|
||||
static server_list list;
|
||||
static bool inited = false;
|
||||
|
||||
if (!inited)
|
||||
{
|
||||
/*
|
||||
list.info_count = 256;
|
||||
|
||||
list.scroll_index = 0;
|
||||
list.selected_index = -1;
|
||||
*/
|
||||
|
||||
inited = true;
|
||||
|
||||
refresh_list(&list);
|
||||
client_serverbrowse_refresh();
|
||||
}
|
||||
|
||||
do_server_list(&list, 20, 160, 8);
|
||||
static int scoll_index = 0, selected_index = -1;
|
||||
do_server_list(20, 160, &scoll_index, &selected_index, 8);
|
||||
|
||||
static int refresh_button, join_button, quit_button;
|
||||
|
||||
if (ui_do_button(&refresh_button, "Refresh", 0, 440, 420, 170, 48, draw_teewars_button))
|
||||
{
|
||||
refresh_list(&list);
|
||||
}
|
||||
client_serverbrowse_refresh();
|
||||
|
||||
if (list.selected_index == -1)
|
||||
if (selected_index == -1)
|
||||
{
|
||||
ui_do_button(&join_button, "Join", 0, 620, 420, 128, 48, draw_teewars_button, (void *)1);
|
||||
}
|
||||
else if (ui_do_button(&join_button, "Join", 0, 620, 420, 128, 48, draw_teewars_button))
|
||||
{
|
||||
*server_address = list.infos[list.selected_index].address;
|
||||
// *server_address = list.infos[list.selected_index].address;
|
||||
|
||||
server_info *servers;
|
||||
int num_servers = client_serverbrowse_getlist(&servers);
|
||||
|
||||
dbg_msg("menu/join_button", "IP: %i.%i.%i.%i:%i", (int)server_address->ip[0], (int)server_address->ip[1], (int)server_address->ip[2], (int)server_address->ip[3], server_address->port);
|
||||
client_connect(servers[selected_index].address);
|
||||
//dbg_msg("menu/join_button", "IP: %i.%i.%i.%i:%i", (int)server_address->ip[0], (int)server_address->ip[1], (int)server_address->ip[2], (int)server_address->ip[3], server_address->port);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1123,7 +1015,7 @@ static int kerning_render()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int menu_render(netaddr4 *server_address)
|
||||
static int menu_render()
|
||||
{
|
||||
// background color
|
||||
gfx_clear(0.65f,0.78f,0.9f);
|
||||
|
@ -1147,7 +1039,7 @@ static int menu_render(netaddr4 *server_address)
|
|||
|
||||
switch (screen)
|
||||
{
|
||||
case SCREEN_MAIN: return main_render(server_address);
|
||||
case SCREEN_MAIN: return main_render();
|
||||
case SCREEN_SETTINGS_GENERAL:
|
||||
case SCREEN_SETTINGS_CONTROLS:
|
||||
case SCREEN_SETTINGS_VIDEO:
|
||||
|
@ -1176,7 +1068,7 @@ void modmenu_shutdown()
|
|||
{
|
||||
}
|
||||
|
||||
int modmenu_render(void *ptr)
|
||||
int modmenu_render()
|
||||
{
|
||||
static int mouse_x = 0;
|
||||
static int mouse_y = 0;
|
||||
|
@ -1187,8 +1079,6 @@ int modmenu_render(void *ptr)
|
|||
music_menu_id = snd_play(music_menu, SND_LOOP);
|
||||
}
|
||||
|
||||
netaddr4 *server_address = (netaddr4 *)ptr;
|
||||
|
||||
// handle mouse movement
|
||||
float mx, my;
|
||||
{
|
||||
|
@ -1214,7 +1104,7 @@ int modmenu_render(void *ptr)
|
|||
}
|
||||
|
||||
//int r = menu_render(server_address, str, max_len);
|
||||
int r = menu_render(server_address);
|
||||
int r = menu_render();
|
||||
|
||||
// render butt ugly mouse cursor
|
||||
// TODO: render nice cursor
|
||||
|
|
|
@ -58,7 +58,10 @@ struct player_input
|
|||
{
|
||||
int left;
|
||||
int right;
|
||||
int angle;
|
||||
|
||||
int target_x;
|
||||
int target_y;
|
||||
|
||||
int jump;
|
||||
int fire;
|
||||
int hook;
|
||||
|
|
|
@ -464,7 +464,8 @@ void projectile::tick()
|
|||
lifespan--;
|
||||
|
||||
// check player intersection as well
|
||||
entity *targetplayer = (entity*)intersect_player(oldpos, pos, oldpos, powner);
|
||||
vec2 new_pos;
|
||||
entity *targetplayer = (entity*)intersect_player(oldpos, pos, new_pos, powner);
|
||||
if(targetplayer || lifespan < 0 || col_check_point((int)pos.x, (int)pos.y))
|
||||
{
|
||||
if (lifespan >= 0)
|
||||
|
@ -489,6 +490,74 @@ void projectile::snap(int snapping_client)
|
|||
proj->type = type;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// projectile_backpackrocket
|
||||
//////////////////////////////////////////////////
|
||||
projectile_backpackrocket::projectile_backpackrocket(baselib::vec2 pos, baselib::vec2 target, int owner, entity* powner)
|
||||
: projectile(WEAPON_PROJECTILETYPE_ROCKET, owner, pos, vec2(0,0), 100, powner, 0, 0, 0, -1, WEAPON_ROCKET_BACKPACK)
|
||||
{
|
||||
stage = 0;
|
||||
start_tick = server_tick();
|
||||
vel = vec2(0,-10.0f);
|
||||
this->target = target;
|
||||
start = pos;
|
||||
midpoint = pos;
|
||||
midpoint.y = target.y;
|
||||
direction = normalize(target-midpoint);
|
||||
deply_ticks = (int)( distance(start, midpoint)/(float)server_tickspeed() * 5.0f );
|
||||
dbg_msg("rocket_bp", "%f %d", distance(start, midpoint), deply_ticks);
|
||||
}
|
||||
|
||||
void projectile_backpackrocket::tick()
|
||||
{
|
||||
lifespan--;
|
||||
if(!lifespan)
|
||||
world.destroy_entity(this);
|
||||
|
||||
vec2 oldpos = pos;
|
||||
|
||||
if(stage == 0)
|
||||
{
|
||||
float time = (server_tick()-start_tick)/(float)(deply_ticks);
|
||||
if(midpoint.y > start.y)
|
||||
pos.y = mix(start.y, midpoint.y, 1-sinf((1-time)*pi/2));
|
||||
else
|
||||
pos.y = mix(start.y, midpoint.y, sinf(time*pi/2));
|
||||
|
||||
float a = (server_tick()-start_tick)/(float)server_tickspeed()*pi*7.5f;
|
||||
vel.x = sinf(a)*30.0f;
|
||||
vel.y = cosf(a)*30.0f;
|
||||
|
||||
if(server_tick() > start_tick+deply_ticks)
|
||||
{
|
||||
pos = midpoint;
|
||||
direction = normalize(target-pos);
|
||||
vel = vec2(0,0);
|
||||
stage = 1;
|
||||
}
|
||||
}
|
||||
else if(stage == 1)
|
||||
{
|
||||
vel += direction*1.5f;
|
||||
vel.x = clamp(vel.x, -20.0f, 20.0f);
|
||||
pos += vel;
|
||||
}
|
||||
|
||||
// check player intersection as well
|
||||
vec2 new_pos;
|
||||
entity *targetplayer = (entity*)intersect_player(oldpos, pos, new_pos, powner);
|
||||
if(targetplayer || lifespan < 0 || col_check_point((int)pos.x, (int)pos.y))
|
||||
{
|
||||
if (lifespan >= 0)
|
||||
create_sound(pos, sound_impact);
|
||||
|
||||
create_explosion(oldpos, owner, weapon, false);
|
||||
|
||||
world.destroy_entity(this);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// player
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -556,6 +625,11 @@ void player::respawn()
|
|||
weapons[WEAPON_HAMMER].ammo = -1;
|
||||
weapons[WEAPON_GUN].got = true;
|
||||
weapons[WEAPON_GUN].ammo = 10;
|
||||
|
||||
// TEMP DEBUG
|
||||
weapons[WEAPON_ROCKET_BACKPACK].got = true;
|
||||
weapons[WEAPON_ROCKET_BACKPACK].ammo = 10;
|
||||
|
||||
active_weapon = WEAPON_GUN;
|
||||
reload_timer = 0;
|
||||
|
||||
|
@ -620,7 +694,7 @@ void player::handle_weapons()
|
|||
break;
|
||||
|
||||
case WEAPON_GUN:
|
||||
new projectile(WEAPON_PROJECTILETYPE_GUN,
|
||||
new projectile(projectile::WEAPON_PROJECTILETYPE_GUN,
|
||||
client_id,
|
||||
pos+vec2(0,0),
|
||||
direction*30.0f,
|
||||
|
@ -630,7 +704,7 @@ void player::handle_weapons()
|
|||
create_sound(pos, SOUND_GUN_FIRE);
|
||||
break;
|
||||
case WEAPON_ROCKET:
|
||||
new projectile(WEAPON_PROJECTILETYPE_ROCKET,
|
||||
new projectile(projectile::WEAPON_PROJECTILETYPE_ROCKET,
|
||||
client_id,
|
||||
pos+vec2(0,0),
|
||||
direction*15.0f,
|
||||
|
@ -644,7 +718,7 @@ void player::handle_weapons()
|
|||
{
|
||||
float a = get_angle(direction);
|
||||
a += i*0.075f;
|
||||
new projectile(WEAPON_PROJECTILETYPE_SHOTGUN,
|
||||
new projectile(projectile::WEAPON_PROJECTILETYPE_SHOTGUN,
|
||||
client_id,
|
||||
pos+vec2(0,0),
|
||||
vec2(cosf(a), sinf(a))*25.0f,
|
||||
|
@ -655,6 +729,13 @@ void player::handle_weapons()
|
|||
}
|
||||
create_sound(pos, SOUND_SHOTGUN_FIRE);
|
||||
break;
|
||||
case WEAPON_ROCKET_BACKPACK:
|
||||
new projectile_backpackrocket(
|
||||
pos+vec2(0,0),
|
||||
pos+vec2(input.target_x,input.target_y),
|
||||
client_id,
|
||||
this);
|
||||
break;
|
||||
}
|
||||
|
||||
weapons[active_weapon].ammo--;
|
||||
|
@ -662,10 +743,11 @@ void player::handle_weapons()
|
|||
else
|
||||
{
|
||||
// click!!! click
|
||||
// TODO: make sound here
|
||||
}
|
||||
|
||||
attack_tick = server_tick();
|
||||
reload_timer = 10; // make this variable depending on weapon
|
||||
reload_timer = 10; // TODO: make this variable depending on weapon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -685,7 +767,7 @@ void player::tick()
|
|||
|
||||
// fetch some info
|
||||
bool grounded = is_grounded();
|
||||
direction = get_direction(input.angle);
|
||||
direction = normalize(vec2(input.target_x, input.target_y));
|
||||
|
||||
float max_speed = grounded ? ground_control_speed : air_control_speed;
|
||||
float accel = grounded ? ground_control_accel : air_control_accel;
|
||||
|
@ -950,8 +1032,13 @@ void player::snap(int snaping_client)
|
|||
player->hook_active = hook_state>0?1:0;
|
||||
player->hook_x = (int)hook_pos.x;
|
||||
player->hook_y = (int)hook_pos.y;
|
||||
|
||||
float a = atan((float)input.target_y/(float)input.target_x);
|
||||
if(input.target_x < 0)
|
||||
a = a+pi;
|
||||
|
||||
player->angle = input.angle;
|
||||
player->angle = (int)(a*256.0f);
|
||||
|
||||
player->score = score;
|
||||
}
|
||||
|
||||
|
@ -1079,15 +1166,17 @@ void create_explosion(vec2 p, int owner, int weapon, bool bnodamage)
|
|||
// deal damage
|
||||
entity *ents[64];
|
||||
const float radius = 128.0f;
|
||||
const float innerradius = 42.0f;
|
||||
int num = world.find_entities(p, radius, ents, 64);
|
||||
for(int i = 0; i < num; i++)
|
||||
{
|
||||
vec2 diff = ents[i]->pos - p;
|
||||
vec2 forcedir(0,1);
|
||||
if (length(diff))
|
||||
forcedir = normalize(diff);
|
||||
float l = length(diff);
|
||||
float dmg = 5 * (1 - (l/radius));
|
||||
if(l)
|
||||
forcedir = normalize(diff);
|
||||
l = 1-clamp((l-innerradius)/(radius-innerradius), 0.0f, 1.0f);
|
||||
float dmg = 6 * l;
|
||||
if((int)dmg)
|
||||
ents[i]->take_damage(forcedir*dmg*2, (int)dmg, owner, weapon);
|
||||
}
|
||||
|
|
|
@ -146,6 +146,10 @@ public:
|
|||
enum
|
||||
{
|
||||
PROJECTILE_FLAGS_EXPLODE = 1 << 0,
|
||||
|
||||
WEAPON_PROJECTILETYPE_GUN = 0,
|
||||
WEAPON_PROJECTILETYPE_ROCKET = 1,
|
||||
WEAPON_PROJECTILETYPE_SHOTGUN = 2,
|
||||
};
|
||||
|
||||
baselib::vec2 vel;
|
||||
|
@ -166,19 +170,26 @@ public:
|
|||
virtual void snap(int snapping_client);
|
||||
};
|
||||
|
||||
class projectile_backpackrocket : public projectile
|
||||
{
|
||||
int stage;
|
||||
int start_tick;
|
||||
int deply_ticks;
|
||||
baselib::vec2 target;
|
||||
baselib::vec2 start;
|
||||
baselib::vec2 midpoint;
|
||||
baselib::vec2 direction;
|
||||
public:
|
||||
projectile_backpackrocket(baselib::vec2 pos, baselib::vec2 target, int owner, entity* powner);
|
||||
virtual void tick();
|
||||
};
|
||||
|
||||
// player entity
|
||||
class player : public entity
|
||||
{
|
||||
public:
|
||||
static const int phys_size = 28;
|
||||
|
||||
enum // what are these?
|
||||
{
|
||||
WEAPON_PROJECTILETYPE_GUN = 0,
|
||||
WEAPON_PROJECTILETYPE_ROCKET = 1,
|
||||
WEAPON_PROJECTILETYPE_SHOTGUN = 2,
|
||||
};
|
||||
|
||||
// weapon info
|
||||
struct weaponstat
|
||||
{
|
||||
|
|
118
src/mastersrv/mastersrv.cpp
Normal file
118
src/mastersrv/mastersrv.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
#include <string.h>
|
||||
#include <baselib/system.h>
|
||||
#include <engine/network.h>
|
||||
|
||||
#include "mastersrv.h"
|
||||
|
||||
enum {
|
||||
MTU = 1400,
|
||||
EXPIRE_TIME = 90
|
||||
};
|
||||
|
||||
static struct packet_data
|
||||
{
|
||||
unsigned char header[sizeof(SERVERBROWSE_LIST)];
|
||||
NETADDR4 servers[MAX_SERVERS];
|
||||
} data;
|
||||
static int64 server_expire[MAX_SERVERS];
|
||||
static int num_servers = 0;
|
||||
|
||||
static net_client net;
|
||||
|
||||
void add_server(NETADDR4 *info)
|
||||
{
|
||||
// see if server already exists in list
|
||||
int i;
|
||||
for(i = 0; i < num_servers; i++)
|
||||
{
|
||||
if(net_addr4_cmp(&data.servers[i], info) == 0)
|
||||
{
|
||||
dbg_msg("mastersrv", "updated: %d.%d.%d.%d:%d",
|
||||
info->ip[0], info->ip[1], info->ip[2], info->ip[3], info->port);
|
||||
server_expire[i] = time_get()+time_freq()*EXPIRE_TIME;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// add server
|
||||
if(num_servers == MAX_SERVERS)
|
||||
{
|
||||
dbg_msg("mastersrv", "error: mastersrv is full");
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_msg("mastersrv", "added: %d.%d.%d.%d:%d",
|
||||
info->ip[0], info->ip[1], info->ip[2], info->ip[3], info->port);
|
||||
data.servers[num_servers] = *info;
|
||||
server_expire[num_servers] = time_get()+time_freq()*EXPIRE_TIME;
|
||||
num_servers++;
|
||||
}
|
||||
|
||||
void purge_servers()
|
||||
{
|
||||
int64 now = time_get();
|
||||
int i = 0;
|
||||
while(i < num_servers)
|
||||
{
|
||||
if(server_expire[i] < now)
|
||||
{
|
||||
// remove server
|
||||
dbg_msg("mastersrv", "expired: %d.%d.%d.%d:%d",
|
||||
data.servers[i].ip[0], data.servers[i].ip[1],
|
||||
data.servers[i].ip[2], data.servers[i].ip[3], data.servers[i].port);
|
||||
data.servers[i] = data.servers[num_servers-1];
|
||||
server_expire[i] = server_expire[num_servers-1];
|
||||
num_servers--;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
net.open(MASTERSERVER_PORT, 0);
|
||||
// TODO: check socket for errors
|
||||
|
||||
mem_copy(data.header, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
|
||||
dbg_msg("mastersrv", "started");
|
||||
|
||||
while(1)
|
||||
{
|
||||
net.update();
|
||||
|
||||
// process packets
|
||||
NETPACKET packet;
|
||||
while(net.recv(&packet))
|
||||
{
|
||||
if(packet.data_size == sizeof(SERVERBROWSE_HEARTBEAT) &&
|
||||
memcmp(packet.data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0)
|
||||
{
|
||||
// add it
|
||||
add_server(&packet.address);
|
||||
}
|
||||
else if(packet.data_size == sizeof(SERVERBROWSE_GETLIST) &&
|
||||
memcmp(packet.data, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0)
|
||||
{
|
||||
// someone requested the list
|
||||
dbg_msg("mastersrv", "requested, responding with %d servers", num_servers);
|
||||
NETPACKET p;
|
||||
p.client_id = -1;
|
||||
p.address = packet.address;
|
||||
p.flags = PACKETFLAG_CONNLESS;
|
||||
p.data_size = num_servers*sizeof(NETADDR4)+sizeof(SERVERBROWSE_LIST);
|
||||
p.data = &data;
|
||||
net.send(&p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: shouldn't be done every fuckin frame
|
||||
purge_servers();
|
||||
|
||||
// be nice to the CPU
|
||||
thread_sleep(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
src/mastersrv/mastersrv.h
Normal file
19
src/mastersrv/mastersrv.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
static const char *MASTERSERVER_ADDRESS = "localhost";
|
||||
static const int MASTERSERVER_PORT = 8383;
|
||||
|
||||
static const int MAX_SERVERS = 200;
|
||||
|
||||
/*enum {
|
||||
SERVERBROWSE_NULL=0,
|
||||
SERVERBROWSE_HEARTBEAT,
|
||||
SERVERBROWSE_GETLIST,
|
||||
SERVERBROWSE_LIST,
|
||||
SERVERBROWSE_GETINFO,
|
||||
SERVERBROWSE_INFO,
|
||||
};*/
|
||||
|
||||
static const unsigned char SERVERBROWSE_HEARTBEAT[] = {255, 255, 255, 255, 'b', 'e', 'a', 't'};
|
||||
static const unsigned char SERVERBROWSE_GETLIST[] = {255, 255, 255, 255, 'r', 'e', 'q', 't'};
|
||||
static const unsigned char SERVERBROWSE_LIST[] = {255, 255, 255, 255, 'l', 'i', 's', 't'};
|
||||
static const unsigned char SERVERBROWSE_GETINFO[] = {255, 255, 255, 255, 'g', 'i', 'e', 'f'};
|
||||
static const unsigned char SERVERBROWSE_INFO[] = {255, 255, 255, 255, 'i', 'n', 'f', 'o'};
|
Loading…
Reference in a new issue