mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +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_CONNLESS=2,
|
||||
NET_PACKETFLAG_RESEND=4,
|
||||
NET_PACKETFLAG_COMPRESSION=8,
|
||||
|
||||
NET_CHUNKFLAG_VITAL=1,
|
||||
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)
|
||||
{
|
||||
unsigned char buffer[NET_MAX_PACKETSIZE];
|
||||
buffer[0] = ((packet->flags<<4)&0xf0)|((packet->ack>>8)&0xf);
|
||||
buffer[1] = packet->ack&0xff;
|
||||
buffer[2] = packet->num_chunks;
|
||||
int compressed_size = -1;
|
||||
int final_size = -1;
|
||||
|
||||
/* log the data */
|
||||
if(datalog)
|
||||
{
|
||||
io_write(datalog, &packet->data_size, sizeof(packet->data_size));
|
||||
io_write(datalog, &packet->chunk_data, packet->data_size);
|
||||
}
|
||||
|
||||
/* compress if its enabled */
|
||||
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);
|
||||
net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+compressed_size);
|
||||
final_size = compressed_size;
|
||||
packet->flags |= NET_PACKETFLAG_COMPRESSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* use uncompressed data */
|
||||
final_size = 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 */
|
||||
if(size < NET_PACKETHEADERSIZE || size > NET_MAX_PACKETSIZE)
|
||||
{
|
||||
dbg_msg("", "packet too small");
|
||||
dbg_msg("", "packet too small, %d", size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -281,7 +299,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa
|
|||
}
|
||||
else
|
||||
{
|
||||
if(COMPRESSION)
|
||||
if(packet->flags&NET_PACKETFLAG_COMPRESSION)
|
||||
huffman_decompress(&huffmanstate, &buffer[3], packet->data_size, packet->chunk_data, sizeof(packet->chunk_data));
|
||||
else
|
||||
mem_copy(packet->chunk_data, &buffer[3], packet->data_size);
|
||||
|
|
|
@ -38,8 +38,6 @@ static int browseinfo_progression = -1;
|
|||
static int64 lastheartbeat;
|
||||
/*static NETADDR4 master_server;*/
|
||||
|
||||
|
||||
|
||||
static char current_map[64];
|
||||
static int current_map_crc;
|
||||
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 */
|
||||
int i;
|
||||
for(i = 0; i < 200; i++)
|
||||
{
|
||||
clients[cid].inputs[i].game_tick = -1;
|
||||
clients[cid].inputs[i].pred_tick = -1;
|
||||
}
|
||||
clients[cid].current_input = 0;
|
||||
|
||||
mem_zero(&clients[cid].latestinput, sizeof(clients[cid].latestinput));
|
||||
|
||||
|
||||
snapstorage_purge_all(&clients[cid].snapshots);
|
||||
clients[cid].last_acked_snapshot = -1;
|
||||
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_INIT;
|
||||
clients[cid].score = 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;
|
||||
}
|
||||
|
||||
static int del_client_callback(int cid, void *user)
|
||||
{
|
||||
/* notify the mod about the drop */
|
||||
if(clients[cid].state == SRVCLIENT_STATE_READY ||
|
||||
clients[cid].state == SRVCLIENT_STATE_INGAME)
|
||||
{
|
||||
if(clients[cid].state >= SRVCLIENT_STATE_READY)
|
||||
mods_client_drop(cid);
|
||||
}
|
||||
|
||||
|
||||
clients[cid].state = SRVCLIENT_STATE_EMPTY;
|
||||
clients[cid].name[0] = 0;
|
||||
clients[cid].clan[0] = 0;
|
||||
|
@ -682,7 +680,7 @@ static void server_process_client_packet(NETCHUNK *packet)
|
|||
int tick, size, i;
|
||||
CLIENT_INPUT *input;
|
||||
int64 tagtime;
|
||||
|
||||
|
||||
clients[cid].last_acked_snapshot = msg_unpack_int();
|
||||
tick = msg_unpack_int();
|
||||
size = msg_unpack_int();
|
||||
|
@ -690,7 +688,7 @@ static void server_process_client_packet(NETCHUNK *packet)
|
|||
/* check for errors */
|
||||
if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
|
||||
return;
|
||||
|
||||
|
||||
if(clients[cid].last_acked_snapshot > 0)
|
||||
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
|
||||
|
||||
|
@ -715,7 +713,8 @@ static void server_process_client_packet(NETCHUNK *packet)
|
|||
clients[cid].current_input %= 200;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -784,7 +783,8 @@ static void server_process_client_packet(NETCHUNK *packet)
|
|||
else
|
||||
{
|
||||
/* 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;
|
||||
|
||||
server_send_map(c);
|
||||
reset_client(c);
|
||||
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();
|
||||
|
@ -1029,7 +1027,8 @@ static int server_run()
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ static INPUT_COUNT count_input(int prev, int cur)
|
|||
return c;
|
||||
}
|
||||
|
||||
|
||||
MACRO_ALLOC_POOL_ID_IMPL(CHARACTER, MAX_CLIENTS)
|
||||
|
||||
// player
|
||||
CHARACTER::CHARACTER()
|
||||
: ENTITY(NETOBJTYPE_CHARACTER)
|
||||
|
|
|
@ -11,19 +11,8 @@
|
|||
|
||||
class CHARACTER : public ENTITY
|
||||
{
|
||||
/*static CHARACTER pool_data[MAX_CLIENTS];
|
||||
static int pool_used[MAX_CLIENTS];*/
|
||||
MACRO_ALLOC_POOL_ID()
|
||||
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
|
||||
class PLAYER *player;
|
||||
|
||||
|
|
|
@ -1,14 +1,59 @@
|
|||
#ifndef GAME_SERVER_ENTITY_H
|
||||
#define GAME_SERVER_ENTITY_H
|
||||
|
||||
#include <new>
|
||||
#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
|
||||
Basic entity class.
|
||||
*/
|
||||
class ENTITY
|
||||
{
|
||||
MACRO_ALLOC_HEAP()
|
||||
private:
|
||||
friend class GAMEWORLD; // thy these?
|
||||
ENTITY *prev_entity;
|
||||
|
@ -21,7 +66,6 @@ protected:
|
|||
int id;
|
||||
int objtype;
|
||||
public:
|
||||
|
||||
ENTITY(int objtype);
|
||||
virtual ~ENTITY();
|
||||
|
||||
|
|
|
@ -7,15 +7,13 @@ GAMECONTEXT game;
|
|||
GAMECONTEXT::GAMECONTEXT()
|
||||
{
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
players[i] = 0;
|
||||
/*players = new PLAYER();
|
||||
players[i].init(-1);*/
|
||||
}
|
||||
}
|
||||
|
||||
GAMECONTEXT::~GAMECONTEXT()
|
||||
{
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
delete players[i];
|
||||
}
|
||||
|
||||
void GAMECONTEXT::clear()
|
||||
|
@ -23,15 +21,6 @@ void GAMECONTEXT::clear()
|
|||
this->~GAMECONTEXT();
|
||||
mem_zero(this, sizeof(*this));
|
||||
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)
|
||||
|
||||
*/
|
||||
|
||||
class GAMECONTEXT
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -73,7 +73,7 @@ void mods_client_enter(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].client_id = client_id;
|
||||
|
||||
|
|
|
@ -5,12 +5,20 @@
|
|||
#include "player.hpp"
|
||||
#include "gamecontext.hpp"
|
||||
|
||||
MACRO_ALLOC_POOL_ID_IMPL(PLAYER, MAX_CLIENTS)
|
||||
|
||||
PLAYER::PLAYER(int client_id)
|
||||
{
|
||||
character = 0;
|
||||
this->client_id = client_id;
|
||||
}
|
||||
|
||||
PLAYER::~PLAYER()
|
||||
{
|
||||
delete character;
|
||||
character = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void PLAYER::init(int client_id)
|
||||
{
|
||||
|
@ -168,7 +176,7 @@ void PLAYER::try_respawn()
|
|||
if(num_ents == 0)
|
||||
{
|
||||
spawning = false;
|
||||
character = new CHARACTER();
|
||||
character = new(client_id) CHARACTER();
|
||||
character->spawn(this, spawnpos, team);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
// player object
|
||||
class PLAYER
|
||||
{
|
||||
MACRO_ALLOC_POOL_ID()
|
||||
private:
|
||||
CHARACTER *character;
|
||||
public:
|
||||
PLAYER(int client_id);
|
||||
~PLAYER();
|
||||
|
||||
// TODO: clean this up
|
||||
char skin_name[64];
|
||||
|
|
Loading…
Reference in a new issue