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:
Magnus Auvinen 2008-09-24 09:03:49 +00:00
parent d9d37b945e
commit eb21e9d6bb
10 changed files with 112 additions and 60 deletions

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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)

View file

@ -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;

View file

@ -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();

View file

@ -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();
*/
}

View file

@ -27,7 +27,6 @@
All players (PLAYER::snap)
*/
class GAMECONTEXT
{
public:

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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];