mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-12 19:18:20 +00:00
cleaned up the code a bit more. pooling of character and player objects with reusable macros. fixed crashing when changing maps and a couple of other bugs
This commit is contained in:
parent
d9d37b945e
commit
eb21e9d6bb
|
@ -47,6 +47,7 @@ enum
|
||||||
NET_PACKETFLAG_CONTROL=1,
|
NET_PACKETFLAG_CONTROL=1,
|
||||||
NET_PACKETFLAG_CONNLESS=2,
|
NET_PACKETFLAG_CONNLESS=2,
|
||||||
NET_PACKETFLAG_RESEND=4,
|
NET_PACKETFLAG_RESEND=4,
|
||||||
|
NET_PACKETFLAG_COMPRESSION=8,
|
||||||
|
|
||||||
NET_CHUNKFLAG_VITAL=1,
|
NET_CHUNKFLAG_VITAL=1,
|
||||||
NET_CHUNKFLAG_RESEND=2,
|
NET_CHUNKFLAG_RESEND=2,
|
||||||
|
@ -234,24 +235,41 @@ static void send_packet_connless(NETSOCKET socket, NETADDR *addr, const void *da
|
||||||
static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet)
|
static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet)
|
||||||
{
|
{
|
||||||
unsigned char buffer[NET_MAX_PACKETSIZE];
|
unsigned char buffer[NET_MAX_PACKETSIZE];
|
||||||
buffer[0] = ((packet->flags<<4)&0xf0)|((packet->ack>>8)&0xf);
|
int compressed_size = -1;
|
||||||
buffer[1] = packet->ack&0xff;
|
int final_size = -1;
|
||||||
buffer[2] = packet->num_chunks;
|
|
||||||
|
/* log the data */
|
||||||
if(datalog)
|
if(datalog)
|
||||||
{
|
{
|
||||||
io_write(datalog, &packet->data_size, sizeof(packet->data_size));
|
io_write(datalog, &packet->data_size, sizeof(packet->data_size));
|
||||||
io_write(datalog, &packet->chunk_data, packet->data_size);
|
io_write(datalog, &packet->chunk_data, packet->data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* compress if its enabled */
|
||||||
if(COMPRESSION)
|
if(COMPRESSION)
|
||||||
|
compressed_size = huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4);
|
||||||
|
|
||||||
|
/* check if the compression was enabled, successful and good enough */
|
||||||
|
if(compressed_size > 0 && compressed_size < packet->data_size)
|
||||||
{
|
{
|
||||||
int compressed_size = huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4);
|
final_size = compressed_size;
|
||||||
net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+compressed_size);
|
packet->flags |= NET_PACKETFLAG_COMPRESSION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* use uncompressed data */
|
||||||
|
final_size = packet->data_size;
|
||||||
mem_copy(&buffer[3], packet->chunk_data, packet->data_size);
|
mem_copy(&buffer[3], packet->chunk_data, packet->data_size);
|
||||||
net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+packet->data_size);
|
packet->flags &= ~NET_PACKETFLAG_COMPRESSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set header and send the packet if all things are good */
|
||||||
|
if(final_size >= 0)
|
||||||
|
{
|
||||||
|
buffer[0] = ((packet->flags<<4)&0xf0)|((packet->ack>>8)&0xf);
|
||||||
|
buffer[1] = packet->ack&0xff;
|
||||||
|
buffer[2] = packet->num_chunks;
|
||||||
|
net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+final_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +279,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa
|
||||||
/* check the size */
|
/* check the size */
|
||||||
if(size < NET_PACKETHEADERSIZE || size > NET_MAX_PACKETSIZE)
|
if(size < NET_PACKETHEADERSIZE || size > NET_MAX_PACKETSIZE)
|
||||||
{
|
{
|
||||||
dbg_msg("", "packet too small");
|
dbg_msg("", "packet too small, %d", size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +299,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(COMPRESSION)
|
if(packet->flags&NET_PACKETFLAG_COMPRESSION)
|
||||||
huffman_decompress(&huffmanstate, &buffer[3], packet->data_size, packet->chunk_data, sizeof(packet->chunk_data));
|
huffman_decompress(&huffmanstate, &buffer[3], packet->data_size, packet->chunk_data, sizeof(packet->chunk_data));
|
||||||
else
|
else
|
||||||
mem_copy(packet->chunk_data, &buffer[3], packet->data_size);
|
mem_copy(packet->chunk_data, &buffer[3], packet->data_size);
|
||||||
|
|
|
@ -38,8 +38,6 @@ static int browseinfo_progression = -1;
|
||||||
static int64 lastheartbeat;
|
static int64 lastheartbeat;
|
||||||
/*static NETADDR4 master_server;*/
|
/*static NETADDR4 master_server;*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char current_map[64];
|
static char current_map[64];
|
||||||
static int current_map_crc;
|
static int current_map_crc;
|
||||||
static unsigned char *current_map_data = 0;
|
static unsigned char *current_map_data = 0;
|
||||||
|
@ -521,40 +519,40 @@ static void server_do_snap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int new_client_callback(int cid, void *user)
|
static void reset_client(int cid)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
clients[cid].state = SRVCLIENT_STATE_CONNECTING;
|
|
||||||
clients[cid].name[0] = 0;
|
|
||||||
clients[cid].clan[0] = 0;
|
|
||||||
|
|
||||||
/* reset input */
|
/* reset input */
|
||||||
|
int i;
|
||||||
for(i = 0; i < 200; i++)
|
for(i = 0; i < 200; i++)
|
||||||
{
|
{
|
||||||
clients[cid].inputs[i].game_tick = -1;
|
clients[cid].inputs[i].game_tick = -1;
|
||||||
clients[cid].inputs[i].pred_tick = -1;
|
clients[cid].inputs[i].pred_tick = -1;
|
||||||
}
|
}
|
||||||
clients[cid].current_input = 0;
|
clients[cid].current_input = 0;
|
||||||
|
|
||||||
mem_zero(&clients[cid].latestinput, sizeof(clients[cid].latestinput));
|
mem_zero(&clients[cid].latestinput, sizeof(clients[cid].latestinput));
|
||||||
|
|
||||||
snapstorage_purge_all(&clients[cid].snapshots);
|
snapstorage_purge_all(&clients[cid].snapshots);
|
||||||
clients[cid].last_acked_snapshot = -1;
|
clients[cid].last_acked_snapshot = -1;
|
||||||
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_INIT;
|
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_INIT;
|
||||||
clients[cid].score = 0;
|
clients[cid].score = 0;
|
||||||
clients[cid].authed = 0;
|
clients[cid].authed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int new_client_callback(int cid, void *user)
|
||||||
|
{
|
||||||
|
clients[cid].state = SRVCLIENT_STATE_CONNECTING;
|
||||||
|
clients[cid].name[0] = 0;
|
||||||
|
clients[cid].clan[0] = 0;
|
||||||
|
reset_client(cid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int del_client_callback(int cid, void *user)
|
static int del_client_callback(int cid, void *user)
|
||||||
{
|
{
|
||||||
/* notify the mod about the drop */
|
/* notify the mod about the drop */
|
||||||
if(clients[cid].state == SRVCLIENT_STATE_READY ||
|
if(clients[cid].state >= SRVCLIENT_STATE_READY)
|
||||||
clients[cid].state == SRVCLIENT_STATE_INGAME)
|
|
||||||
{
|
|
||||||
mods_client_drop(cid);
|
mods_client_drop(cid);
|
||||||
}
|
|
||||||
|
|
||||||
clients[cid].state = SRVCLIENT_STATE_EMPTY;
|
clients[cid].state = SRVCLIENT_STATE_EMPTY;
|
||||||
clients[cid].name[0] = 0;
|
clients[cid].name[0] = 0;
|
||||||
clients[cid].clan[0] = 0;
|
clients[cid].clan[0] = 0;
|
||||||
|
@ -682,7 +680,7 @@ static void server_process_client_packet(NETCHUNK *packet)
|
||||||
int tick, size, i;
|
int tick, size, i;
|
||||||
CLIENT_INPUT *input;
|
CLIENT_INPUT *input;
|
||||||
int64 tagtime;
|
int64 tagtime;
|
||||||
|
|
||||||
clients[cid].last_acked_snapshot = msg_unpack_int();
|
clients[cid].last_acked_snapshot = msg_unpack_int();
|
||||||
tick = msg_unpack_int();
|
tick = msg_unpack_int();
|
||||||
size = msg_unpack_int();
|
size = msg_unpack_int();
|
||||||
|
@ -690,7 +688,7 @@ static void server_process_client_packet(NETCHUNK *packet)
|
||||||
/* check for errors */
|
/* check for errors */
|
||||||
if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
|
if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(clients[cid].last_acked_snapshot > 0)
|
if(clients[cid].last_acked_snapshot > 0)
|
||||||
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
|
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
|
||||||
|
|
||||||
|
@ -715,7 +713,8 @@ static void server_process_client_packet(NETCHUNK *packet)
|
||||||
clients[cid].current_input %= 200;
|
clients[cid].current_input %= 200;
|
||||||
|
|
||||||
/* call the mod with the fresh input data */
|
/* call the mod with the fresh input data */
|
||||||
mods_client_direct_input(cid, clients[cid].latestinput.data);
|
if(clients[cid].state == SRVCLIENT_STATE_INGAME)
|
||||||
|
mods_client_direct_input(cid, clients[cid].latestinput.data);
|
||||||
}
|
}
|
||||||
else if(msg == NETMSG_RCON_CMD)
|
else if(msg == NETMSG_RCON_CMD)
|
||||||
{
|
{
|
||||||
|
@ -784,7 +783,8 @@ static void server_process_client_packet(NETCHUNK *packet)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* game message */
|
/* game message */
|
||||||
mods_message(msg, cid);
|
if(clients[cid].state >= SRVCLIENT_STATE_READY)
|
||||||
|
mods_message(msg, cid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,10 +992,8 @@ static int server_run()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
server_send_map(c);
|
server_send_map(c);
|
||||||
|
reset_client(c);
|
||||||
clients[c].state = SRVCLIENT_STATE_CONNECTING;
|
clients[c].state = SRVCLIENT_STATE_CONNECTING;
|
||||||
clients[c].last_acked_snapshot = -1;
|
|
||||||
clients[c].snap_rate = SRVCLIENT_SNAPRATE_RECOVER;
|
|
||||||
snapstorage_purge_all(&clients[c].snapshots);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
game_start_time = time_get();
|
game_start_time = time_get();
|
||||||
|
@ -1029,7 +1027,8 @@ static int server_run()
|
||||||
{
|
{
|
||||||
if(clients[c].inputs[i].game_tick == server_tick())
|
if(clients[c].inputs[i].game_tick == server_tick())
|
||||||
{
|
{
|
||||||
mods_client_predicted_input(c, clients[c].inputs[i].data);
|
if(clients[c].state == SRVCLIENT_STATE_INGAME)
|
||||||
|
mods_client_predicted_input(c, clients[c].inputs[i].data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,9 @@ static INPUT_COUNT count_input(int prev, int cur)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MACRO_ALLOC_POOL_ID_IMPL(CHARACTER, MAX_CLIENTS)
|
||||||
|
|
||||||
// player
|
// player
|
||||||
CHARACTER::CHARACTER()
|
CHARACTER::CHARACTER()
|
||||||
: ENTITY(NETOBJTYPE_CHARACTER)
|
: ENTITY(NETOBJTYPE_CHARACTER)
|
||||||
|
|
|
@ -11,19 +11,8 @@
|
||||||
|
|
||||||
class CHARACTER : public ENTITY
|
class CHARACTER : public ENTITY
|
||||||
{
|
{
|
||||||
/*static CHARACTER pool_data[MAX_CLIENTS];
|
MACRO_ALLOC_POOL_ID()
|
||||||
static int pool_used[MAX_CLIENTS];*/
|
|
||||||
public:
|
public:
|
||||||
/*
|
|
||||||
void operator delete(void *character)
|
|
||||||
{
|
|
||||||
(CHARACTER *)character
|
|
||||||
int id = (CHARACTER *)character - (CHARACTER *)pool_data;
|
|
||||||
dbg_assert(pool_used[id], "");
|
|
||||||
pool_used[id] = 0;
|
|
||||||
mem_zero(&pool_data[id], sizeof(CHARACTER));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// player controlling this character
|
// player controlling this character
|
||||||
class PLAYER *player;
|
class PLAYER *player;
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,59 @@
|
||||||
#ifndef GAME_SERVER_ENTITY_H
|
#ifndef GAME_SERVER_ENTITY_H
|
||||||
#define GAME_SERVER_ENTITY_H
|
#define GAME_SERVER_ENTITY_H
|
||||||
|
|
||||||
|
#include <new>
|
||||||
#include <base/vmath.hpp>
|
#include <base/vmath.hpp>
|
||||||
|
|
||||||
|
#define MACRO_ALLOC_HEAP() \
|
||||||
|
public: \
|
||||||
|
void *operator new(size_t size) \
|
||||||
|
{ \
|
||||||
|
void *p = mem_alloc(size, 1); \
|
||||||
|
/*dbg_msg("", "++ %p %d", p, size);*/ \
|
||||||
|
mem_zero(p, size); \
|
||||||
|
return p; \
|
||||||
|
} \
|
||||||
|
void operator delete(void *p) \
|
||||||
|
{ \
|
||||||
|
/*dbg_msg("", "-- %p", p);*/ \
|
||||||
|
mem_free(p); \
|
||||||
|
} \
|
||||||
|
private:
|
||||||
|
|
||||||
|
#define MACRO_ALLOC_POOL_ID() \
|
||||||
|
public: \
|
||||||
|
void *operator new(size_t size, int id); \
|
||||||
|
void operator delete(void *p); \
|
||||||
|
private:
|
||||||
|
|
||||||
|
#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, poolsize) \
|
||||||
|
static char pool_data_##POOLTYPE[poolsize][sizeof(POOLTYPE)] = {{0}}; \
|
||||||
|
static int pool_used_##POOLTYPE[poolsize] = {0}; \
|
||||||
|
void *POOLTYPE::operator new(size_t size, int id) \
|
||||||
|
{ \
|
||||||
|
dbg_assert(sizeof(POOLTYPE) == size, "size error"); \
|
||||||
|
dbg_assert(!pool_used_##POOLTYPE[id], "already used"); \
|
||||||
|
/*dbg_msg("pool", "++ %s %d", #POOLTYPE, id);*/ \
|
||||||
|
pool_used_##POOLTYPE[id] = 1; \
|
||||||
|
mem_zero(pool_data_##POOLTYPE[id], size); \
|
||||||
|
return pool_data_##POOLTYPE[id]; \
|
||||||
|
} \
|
||||||
|
void POOLTYPE::operator delete(void *p) \
|
||||||
|
{ \
|
||||||
|
int id = (POOLTYPE*)p - (POOLTYPE*)pool_data_##POOLTYPE; \
|
||||||
|
dbg_assert(pool_used_##POOLTYPE[id], "not used"); \
|
||||||
|
/*dbg_msg("pool", "-- %s %d", #POOLTYPE, id);*/ \
|
||||||
|
pool_used_##POOLTYPE[id] = 0; \
|
||||||
|
mem_zero(pool_data_##POOLTYPE[id], sizeof(POOLTYPE)); \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Class: Entity
|
Class: Entity
|
||||||
Basic entity class.
|
Basic entity class.
|
||||||
*/
|
*/
|
||||||
class ENTITY
|
class ENTITY
|
||||||
{
|
{
|
||||||
|
MACRO_ALLOC_HEAP()
|
||||||
private:
|
private:
|
||||||
friend class GAMEWORLD; // thy these?
|
friend class GAMEWORLD; // thy these?
|
||||||
ENTITY *prev_entity;
|
ENTITY *prev_entity;
|
||||||
|
@ -21,7 +66,6 @@ protected:
|
||||||
int id;
|
int id;
|
||||||
int objtype;
|
int objtype;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ENTITY(int objtype);
|
ENTITY(int objtype);
|
||||||
virtual ~ENTITY();
|
virtual ~ENTITY();
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,13 @@ GAMECONTEXT game;
|
||||||
GAMECONTEXT::GAMECONTEXT()
|
GAMECONTEXT::GAMECONTEXT()
|
||||||
{
|
{
|
||||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||||
{
|
|
||||||
players[i] = 0;
|
players[i] = 0;
|
||||||
/*players = new PLAYER();
|
|
||||||
players[i].init(-1);*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GAMECONTEXT::~GAMECONTEXT()
|
GAMECONTEXT::~GAMECONTEXT()
|
||||||
{
|
{
|
||||||
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||||
|
delete players[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void GAMECONTEXT::clear()
|
void GAMECONTEXT::clear()
|
||||||
|
@ -23,15 +21,6 @@ void GAMECONTEXT::clear()
|
||||||
this->~GAMECONTEXT();
|
this->~GAMECONTEXT();
|
||||||
mem_zero(this, sizeof(*this));
|
mem_zero(this, sizeof(*this));
|
||||||
new (this) GAMECONTEXT();
|
new (this) GAMECONTEXT();
|
||||||
// reset all players
|
|
||||||
/*
|
|
||||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
||||||
players[i].init(-1);
|
|
||||||
|
|
||||||
world.~GAMEWORLD();
|
|
||||||
mem_zero(&world, sizeof(world));
|
|
||||||
world.GAMEWORLD();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
All players (PLAYER::snap)
|
All players (PLAYER::snap)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class GAMECONTEXT
|
class GAMECONTEXT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -73,7 +73,7 @@ void mods_client_enter(int client_id)
|
||||||
|
|
||||||
void mods_connected(int client_id)
|
void mods_connected(int client_id)
|
||||||
{
|
{
|
||||||
game.players[client_id] = new PLAYER(client_id);
|
game.players[client_id] = new(client_id) PLAYER(client_id);
|
||||||
//game.players[client_id].init(client_id);
|
//game.players[client_id].init(client_id);
|
||||||
//game.players[client_id].client_id = client_id;
|
//game.players[client_id].client_id = client_id;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,20 @@
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
#include "gamecontext.hpp"
|
#include "gamecontext.hpp"
|
||||||
|
|
||||||
|
MACRO_ALLOC_POOL_ID_IMPL(PLAYER, MAX_CLIENTS)
|
||||||
|
|
||||||
PLAYER::PLAYER(int client_id)
|
PLAYER::PLAYER(int client_id)
|
||||||
{
|
{
|
||||||
character = 0;
|
character = 0;
|
||||||
this->client_id = client_id;
|
this->client_id = client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PLAYER::~PLAYER()
|
||||||
|
{
|
||||||
|
delete character;
|
||||||
|
character = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void PLAYER::init(int client_id)
|
void PLAYER::init(int client_id)
|
||||||
{
|
{
|
||||||
|
@ -168,7 +176,7 @@ void PLAYER::try_respawn()
|
||||||
if(num_ents == 0)
|
if(num_ents == 0)
|
||||||
{
|
{
|
||||||
spawning = false;
|
spawning = false;
|
||||||
character = new CHARACTER();
|
character = new(client_id) CHARACTER();
|
||||||
character->spawn(this, spawnpos, team);
|
character->spawn(this, spawnpos, team);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
// player object
|
// player object
|
||||||
class PLAYER
|
class PLAYER
|
||||||
{
|
{
|
||||||
|
MACRO_ALLOC_POOL_ID()
|
||||||
|
private:
|
||||||
CHARACTER *character;
|
CHARACTER *character;
|
||||||
public:
|
public:
|
||||||
PLAYER(int client_id);
|
PLAYER(int client_id);
|
||||||
|
~PLAYER();
|
||||||
|
|
||||||
// TODO: clean this up
|
// TODO: clean this up
|
||||||
char skin_name[64];
|
char skin_name[64];
|
||||||
|
|
Loading…
Reference in a new issue