From 0fceb1cf1ab9887040f08f0abf646ef318a65ae3 Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Tue, 5 Aug 2008 21:37:33 +0000 Subject: added documentation --- src/engine/docs/server_op.txt | 39 ++++++++ src/engine/docs/snapshots.txt | 58 +++++++++++ src/engine/e_system.c | 10 +- src/engine/e_system.h | 222 ++++++++++++++++++++++++++++-------------- src/game/server/gs_common.hpp | 38 +++++++- src/game/server/gs_server.cpp | 6 +- 6 files changed, 292 insertions(+), 81 deletions(-) create mode 100644 src/engine/docs/server_op.txt create mode 100644 src/engine/docs/snapshots.txt (limited to 'src') diff --git a/src/engine/docs/server_op.txt b/src/engine/docs/server_op.txt new file mode 100644 index 00000000..59181e62 --- /dev/null +++ b/src/engine/docs/server_op.txt @@ -0,0 +1,39 @@ +Title: Server Operation + +Section: Init + +Section: Running + +Here is an graph over how the server operates on each refresh. + +(start code) +load map +init mod + +while running + if map change then + load new map + shutdown mod + reset clients to init state + init mod + end if + + if new tick then + call + for each client do + create snapshot + send snapshot + end for + end + + process new network messages +end while + +unload map +(end) + + + +Section: Reinit + +Section: Shutdown diff --git a/src/engine/docs/snapshots.txt b/src/engine/docs/snapshots.txt new file mode 100644 index 00000000..647b049a --- /dev/null +++ b/src/engine/docs/snapshots.txt @@ -0,0 +1,58 @@ +Title: Snapshots + +Section: Overview + +Topic: Definitions + +- *Snapshot*. A is a serialized game state from which a client can render the game from. They are sent from the server at a regular interval and is created specificly for each client in order to reduce bandwidth. +- *Delta Snapshot*. A set of data that can be applied to a snapshot in order to create a new snapshot with the updated game state. + +Topic: Structure + +A snapshot contains a series of items. Each item have a type, id and data. + +- *Type*. Type of item. Could be projectile or character for example. +- *Id*. A unique id so the client can identify the item between two snapshots. +- *Data*. A series of 32-bit integers that contains the per item type specific data. + +Section: Server Side + +Topic: Creating + +Items can be added when is called using the function to insert an item to the snapshot. The server can not inspect the snapshot that is in progress of being created. + +Section: Client Side + +Topic: Inspection + is called when a new snapshot has arrived for processing. , and can be used to inspect the current and previous snapshot. This can be done anywhere while the client is running and not just in the function. The client can also call if an item contains improper information that could harm the operation of the client. This should however be done in to assure that no bad data propagates into the rest of the client. + +Topic: Rendering +DOCTODO + +Section: In depth + +Topic: Compression + +After a snapshot have been created, compression is applyed to reduce the bandwidth. There are several steps taken inorder to reduce the size of the size of the snapshot. + +- *Delta*. The server looks in a clients backlog of snapshots to find a previous acked snapshot. It then compares the two snapshots and creates a delta snapshot containing the changes from the previous acked snapshot to the new one. +- *Variable Integers*. The delta snapshot which is only consisting of 32-bit integers is then encoded into variable integers similar to UTF-8. Each byte has a bit that tells the decoder that it needs one more byte to decode the 32-bit integer. The first byte also contains a bit for telling the sign of the integer. + +> ESDDDDDD EDDDDDDD EDDDDDDD EDDDDDDD + +> E = extend +> S = sign +> D = data bit + +- *Huffman*. The last step is to compress the buffer with a huffman encoder. It uses a static tree that is weighted towards 0 because it's where most of the data will be because of the delta compression. + +Topic: Interval + +The interval for how often a client recives a snapshot changes during the course of the connection. There are three different snapshot rates. + +- *Init*. 5 snapshots per second. Used when a client is connecting and used until the client has acknowlaged a snapshot. This mechanism is used because the first snapshot because no delta compression can be done. + +- *Full*. Snapshot for every tick or every even tick depending on server configuration. This is used during normal gameplay and everything is running smooth. + +- *Recovery*. 1 snapshot each second. A client enters recovery rate when it havn't acknowlaged a snapshot over 1 second. This is to let the client to beable to recover if it has a slow connection. + diff --git a/src/engine/e_system.c b/src/engine/e_system.c index eeadbb95..1be7ea30 100644 --- a/src/engine/e_system.c +++ b/src/engine/e_system.c @@ -760,14 +760,14 @@ int fs_storage_path(const char *appname, char *path, int max) HRESULT r; char *home = getenv("APPDATA"); if(!home) - return 1; + return -1; _snprintf(path, max, "%s/%s", home, appname); return 0; #else char *home = getenv("HOME"); int i; if(!home) - return 0; + return -1; #if defined(CONF_PLATFORM_MACOSX) snprintf(path, max, "%s/Library/Application Support/%s", home, appname); @@ -777,7 +777,7 @@ int fs_storage_path(const char *appname, char *path, int max) path[i] = tolower(path[i]); #endif - return 1; + return 0; #endif } @@ -788,13 +788,13 @@ int fs_makedir(const char *path) return 0; if(errno == EEXIST) return 0; - return 1; + return -1; #else if(mkdir(path, 0755) == 0) return 0; if(errno == EEXIST) return 0; - return 1; + return -1; #endif } diff --git a/src/engine/e_system.h b/src/engine/e_system.h index 0b1cbaab..ac9e7cc6 100644 --- a/src/engine/e_system.h +++ b/src/engine/e_system.h @@ -408,7 +408,7 @@ int64 time_freq(); */ unsigned time_timestamp(); -/* Group: Network General ipv4 */ +/* Group: Network General */ typedef int NETSOCKET; enum { @@ -420,13 +420,6 @@ enum NETTYPE_ALL = ~0 }; -/* -typedef struct -{ - unsigned char ip[4]; - unsigned short port; -} NETADDR4;*/ - typedef struct { unsigned int type; @@ -434,15 +427,59 @@ typedef struct unsigned short port; } NETADDR; +/* + Function: net_init + Initiates network functionallity. + + Returns: + Returns 0 on success, + + Remarks: + You must call this function before using any other network + functions. +*/ +int net_init(); + /* Function: net_host_lookup - Does a hostname lookup by name and fills out the passed NETADDR struct with the recieved details. + Does a hostname lookup by name and fills out the passed + NETADDR struct with the recieved details. Returns: 0 on success. */ int net_host_lookup(const char *hostname, NETADDR *addr, int types); +/* + Function: net_addr_comp + Compares two network addresses. + + Parameters: + a - Address to compare + b - Address to compare to. + + Returns: + <0 - Address a is lesser then address b + 0 - Address a is equal to address b + >0 - Address a is greater then address b +*/ +int net_addr_comp(const NETADDR *a, const NETADDR *b); + +/* + Function: net_addr_str + Turns a network address into a representive string. + + Parameters: + addr - Address to turn into a string. + string - Buffer to fill with the string. + max_length - Maximum size of the string. + + Remarks: + - The string will always be zero terminated + +*/ +int net_addr_str(const NETADDR *addr, char *string, int max_length); + /* Group: Network UDP */ /* @@ -450,10 +487,11 @@ int net_host_lookup(const char *hostname, NETADDR *addr, int types); Creates a UDP socket and binds it to a port. Parameters: - port - Port to bind the socket to. + bindaddr - Address to bind the socket to. Returns: - On success it returns an handle to the socket. On failure it returns NETSOCKET_INVALID. + On success it returns an handle to the socket. On failure it + returns NETSOCKET_INVALID. */ NETSOCKET net_udp_create(NETADDR bindaddr); @@ -468,7 +506,8 @@ NETSOCKET net_udp_create(NETADDR bindaddr); size - Size of the packet. Returns: - On success it returns the number of bytes sent. Returns -1 on error. + On success it returns the number of bytes sent. Returns -1 + on error. */ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size); @@ -483,7 +522,8 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size maxsize - Maximum size to recive. Returns: - On success it returns the number of bytes recived. Returns -1 on error. + On success it returns the number of bytes recived. Returns -1 + on error. */ int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize); @@ -504,95 +544,97 @@ int net_udp_close(NETSOCKET sock); /* Function: net_tcp_create + Creates a TCP socket. - DOCTODO: serp -*/ -NETSOCKET net_tcp_create(const NETADDR *a); - -/* - Function: net_tcp_set_non_blocking - - DOCTODO: serp -*/ -int net_tcp_set_non_blocking(NETSOCKET sock); - -/* - Function: net_tcp_set_non_blocking + Parameters: + bindaddr - Address to bind the socket to. - DOCTODO: serp + Returns: + On success it returns an handle to the socket. On failure it returns NETSOCKET_INVALID. */ -int net_tcp_set_blocking(NETSOCKET sock); +NETSOCKET net_tcp_create(const NETADDR *a); /* Function: net_tcp_listen - - DOCTODO: serp + Makes the socket start listening for new connections. + + Parameters: + sock - Socket to start listen to. + backlog - Size of the queue of incomming connections to keep. + + Returns: + Returns 0 on success. */ int net_tcp_listen(NETSOCKET sock, int backlog); /* Function: net_tcp_accept + Polls a listning socket for a new connection. + + Parameters: + sock - Listning socket to poll. + new_sock - Pointer to a socket to fill in with the new socket. + addr - Pointer to an address that will be filled in the remote address (optional, can be NULL). - DOCTODO: serp + Returns: + Returns a non-negative integer on success. Negative integer on failure. */ -int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a); +int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *addr); /* Function: net_tcp_connect - - DOCTODO: serp -*/ -int net_tcp_connect(NETSOCKET sock, const NETADDR *a); + Connects one socket to another. + + Parameters: + sock - Socket to connect. + addr - Address to connect to. -/* - Function: net_tcp_connect_non_blocking - - DOCTODO: serp + Returns: + Returns 0 on success. + */ -int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a); +int net_tcp_connect(NETSOCKET sock, const NETADDR *addr); /* Function: net_tcp_send + Sends data to a TCP stream. - DOCTODO: serp + Parameters: + sock - Socket to send data to. + data - Pointer to the data to send. + size - Size of the data to send. + + Returns: + Number of bytes sent. Negative value on failure. */ int net_tcp_send(NETSOCKET sock, const void *data, int size); /* Function: net_tcp_recv - - DOCTODO: serp + Recvives data from a TCP stream. + + Parameters: + sock - Socket to recvive data from. + data - Pointer to a buffer to write the data to + max_size - Maximum of data to write to the buffer. + + Returns: + Number of bytes recvived. Negative value on failure. */ int net_tcp_recv(NETSOCKET sock, void *data, int maxsize); /* Function: net_tcp_close + Closes a TCP socket. - DOCTODO: serp + Parameters: + sock - Socket to close. + + Returns: + Returns 0 on success. Negative value on failure. */ int net_tcp_close(NETSOCKET sock); -/* - Function: net_errno - - DOCTODO: serp -*/ -int net_errno(); - -/* - Function: net_would_block - - DOCTODO: serp -*/ -int net_would_block(); - -/* - Function: net_init - - DOCTODO: serp -*/ -int net_init(); - /* Group: Strings */ /* @@ -676,7 +718,7 @@ void str_sanitize(char *str); b - String to compare. Returns: - <0 - String g a is lesser then string b + <0 - String a is lesser then string b 0 - String a is equal to string b >0 - String a is greater then string b @@ -720,6 +762,7 @@ const char *str_find_nocase(const char *haystack, const char *needle); */ void str_hex(char *dst, int dst_size, const void *data, int data_size); +/* Group: Filesystem */ /* Function: fs_listdir @@ -731,7 +774,7 @@ void str_hex(char *dst, int dst_size, const void *data, int data_size); user - Pointer to give to the callback Returns: - DOCTODO + Always returns 0. */ typedef void (*fs_listdir_callback)(const char *name, int is_dir, void *user); int fs_listdir(const char *dir, fs_listdir_callback cb, void *user); @@ -744,7 +787,7 @@ int fs_listdir(const char *dir, fs_listdir_callback cb, void *user); path - Directory to create Returns: - DOCTODO + Returns 0 on success. Negative value on failure. Remarks: Does not create several directories if needed. "a/b/c" will result @@ -757,10 +800,11 @@ int fs_makedir(const char *path); Fetches per user configuration directory. Returns: - DOCTODO + Returns 0 on success. Negative value on failure. Remarks: - Returns ~/.appname on UNIX based systems + - Returns ~/Library/Applications Support/appname on Mac OS X - Returns %APPDATA%/Appname on Windows based systems */ int fs_storage_path(const char *appname, char *path, int max); @@ -770,8 +814,42 @@ int fs_storage_path(const char *appname, char *path, int max); Group: Undocumented */ -int net_addr_comp(const NETADDR *a, const NETADDR *b); -int net_addr_str(const NETADDR *addr, char *string, int max_length); + +/* + Function: net_tcp_connect_non_blocking + + DOCTODO: serp +*/ +int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a); + +/* + Function: net_tcp_set_non_blocking + + DOCTODO: serp +*/ +int net_tcp_set_non_blocking(NETSOCKET sock); + +/* + Function: net_tcp_set_non_blocking + + DOCTODO: serp +*/ +int net_tcp_set_blocking(NETSOCKET sock); + +/* + Function: net_errno + + DOCTODO: serp +*/ +int net_errno(); + +/* + Function: net_would_block + + DOCTODO: serp +*/ +int net_would_block(); + int net_socket_read_wait(NETSOCKET sock, int time); void mem_debug_dump(); diff --git a/src/game/server/gs_common.hpp b/src/game/server/gs_common.hpp index ff939116..ce03d728 100644 --- a/src/game/server/gs_common.hpp +++ b/src/game/server/gs_common.hpp @@ -9,6 +9,28 @@ inline int cmask_one(int cid) { return 1<tick(); + //if(world.paused) // make sure that the game object always updates + controller->tick(); for(int i = 0; i < MAX_CLIENTS; i++) { @@ -737,8 +737,8 @@ void GAMECONTEXT::tick() void GAMECONTEXT::snap(int client_id) { world.snap(client_id); - events.snap(client_id); controller->snap(client_id); + events.snap(client_id); for(int i = 0; i < MAX_CLIENTS; i++) { -- cgit 1.4.1