From 16912026dbdd7dc9e238492d9d83e37270ae4f06 Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Sun, 17 Aug 2008 07:05:16 +0000 Subject: [PATCH] added cl_layershot. fixed some bugs in the network --- datasrc/compile.py | 11 + default.bam | 5 +- src/base/system.c | 25 ++ src/base/system.h | 2 +- src/engine/client/ec_client.c | 2 +- src/engine/client/ec_gfx.c | 101 +++--- src/engine/e_config_variables.h | 1 + src/engine/e_huffman.c | 551 +++++++++++++------------------- src/engine/e_huffman.h | 106 ++++-- src/engine/e_if_gfx.h | 16 +- src/engine/e_network.c | 57 +--- src/engine/server/es_server.c | 3 +- src/game/client/gc_render.cpp | 40 ++- src/game/g_variables.hpp | 1 + 14 files changed, 457 insertions(+), 464 deletions(-) diff --git a/datasrc/compile.py b/datasrc/compile.py index 30734a21e..d3970ed68 100644 --- a/datasrc/compile.py +++ b/datasrc/compile.py @@ -36,6 +36,15 @@ if "client_content_source" in sys.argv: gen_client_content_source = True if "server_content_header" in sys.argv: gen_server_content_header = True if "server_content_source" in sys.argv: gen_server_content_source = True +if gen_client_content_header: + print "#ifndef CLIENT_CONTENT_HEADER" + print "#define CLIENT_CONTENT_HEADER" + +if gen_server_content_header: + print "#ifndef SERVER_CONTENT_HEADER" + print "#define SERVER_CONTENT_HEADER" + + if gen_client_content_header or gen_server_content_header: # emit the type declarations contentlines = file("datasrc/content.py").readlines() @@ -210,3 +219,5 @@ if gen_network_source: for l in lines: print l +if gen_client_content_header or gen_server_content_header: + print "#endif" diff --git a/default.bam b/default.bam index 2d10baf29..02c04077e 100644 --- a/default.bam +++ b/default.bam @@ -302,7 +302,10 @@ function build(settings) masterserver = Compile(settings, Collect("src/mastersrv/*.cpp")) game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash, network_source) game_client = Compile(settings, Collect("src/game/client/*.cpp"), client_content_source) - game_server = Compile(settings, Collect("src/game/server/*.cpp"), server_content_source) + game_server = Compile(settings, Collect( + "src/game/server/*.cpp", + "src/game/server/entities/*.cpp", + "src/game/server/gamemodes/*.cpp"), server_content_source) game_editor = Compile(settings, Collect("src/game/editor/*.cpp")) -- build tools (TODO: fix this so we don't get double _d_d stuff) diff --git a/src/base/system.c b/src/base/system.c index 1ac5f2967..bb23a5e5c 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -479,6 +479,7 @@ static void sockaddr_to_netaddr(const struct sockaddr *src, NETADDR *dst) { /* TODO: IPv6 support */ unsigned int ip = htonl(((struct sockaddr_in*)src)->sin_addr.s_addr); + mem_zero(dst, sizeof(NETADDR)); dst->type = NETTYPE_IPV4; dst->port = htons(((struct sockaddr_in*)src)->sin_port); dst->ip[0] = (unsigned char)((ip>>24)&0xFF); @@ -492,6 +493,21 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b) return mem_comp(a, b, sizeof(NETADDR)); } +void net_addr_str(const NETADDR *addr, char *string, int max_length) +{ + if(addr->type == NETTYPE_IPV4) + str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port); + else if(addr->type == NETTYPE_IPV6) + { + str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", + (addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7], + (addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15], + addr->port); + } + else + str_format(string, max_length, "unknown type %d", addr->type); +} + int net_host_lookup(const char *hostname, NETADDR *addr, int types) { /* TODO: IPv6 support */ @@ -554,7 +570,16 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size netaddr_to_sockaddr(addr, &sa); d = sendto((int)sock, (const char*)data, size, 0, &sa, sizeof(sa)); if(d < 0) + { + char addrstr[256]; + net_addr_str(addr, addrstr, sizeof(addrstr)); + dbg_msg("net", "sendto error %d %x", d, d); + dbg_msg("net", "\tsock = %d %x", sock, sock); + dbg_msg("net", "\tsize = %d %x", size, size); + dbg_msg("net", "\taddr = %s", addrstr); + + } network_stats.sent_bytes += size; network_stats.sent_packets++; return d; diff --git a/src/base/system.h b/src/base/system.h index 4449907c9..abb20b422 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -478,7 +478,7 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b); - The string will always be zero terminated */ -int net_addr_str(const NETADDR *addr, char *string, int max_length); +void net_addr_str(const NETADDR *addr, char *string, int max_length); /* Group: Network UDP */ diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c index 5f213ac64..268e82b0b 100644 --- a/src/engine/client/ec_client.c +++ b/src/engine/client/ec_client.c @@ -297,7 +297,7 @@ int client_send_msg() packet.flags = NETSENDFLAG_VITAL; if(info->flags&MSGFLAG_FLUSH) packet.flags = NETSENDFLAG_FLUSH; - + netclient_send(net, &packet); return 0; } diff --git a/src/engine/client/ec_gfx.c b/src/engine/client/ec_gfx.c index 4f258d11a..7b12e15d1 100644 --- a/src/engine/client/ec_gfx.c +++ b/src/engine/client/ec_gfx.c @@ -168,7 +168,7 @@ int gfx_init() /* open window */ if(config.gfx_fullscreen) { - int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 0, 24, 0, GLFW_FULLSCREEN); + int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, config.gfx_alphabits, 24, 0, GLFW_FULLSCREEN); if(result != GL_TRUE) { dbg_msg("game", "failed to create gl context"); @@ -177,7 +177,7 @@ int gfx_init() } else { - int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 0, 24, 0, GLFW_WINDOW); + int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 8, 24, 0, GLFW_WINDOW); if(result != GL_TRUE) { dbg_msg("game", "failed to create gl context"); @@ -600,52 +600,27 @@ void gfx_swap() if(do_screenshot) { - /* fetch image data */ - int y; - int w = screen_width; - int h = screen_height; - unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*3, 1); - unsigned char *temp_row = pixel_data+w*h*3; - glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel_data); - - /* flip the pixel because opengl works from bottom left corner */ - for(y = 0; y < h/2; y++) - { - mem_copy(temp_row, pixel_data+y*w*3, w*3); - mem_copy(pixel_data+y*w*3, pixel_data+(h-y-1)*w*3, w*3); - mem_copy(pixel_data+(h-y-1)*w*3, temp_row,w*3); - } - /* find filename */ - { - char wholepath[1024]; - char filename[128]; - static int index = 1; - png_t png; + char wholepath[1024]; + char filename[128]; + static int index = 1; - for(; index < 1000; index++) - { - IOHANDLE io; - sprintf(filename, "screenshots/screenshot%04d.png", index); - engine_savepath(filename, wholepath, sizeof(wholepath)); - - io = io_open(wholepath, IOFLAG_READ); - if(io) - io_close(io); - else - break; - } - - /* save png */ - dbg_msg("client", "saved screenshot to '%s'", wholepath); - png_open_file_write(&png, wholepath); - png_set_data(&png, w, h, 8, PNG_TRUECOLOR, (unsigned char *)pixel_data); - png_close_file(&png); + for(; index < 1000; index++) + { + IOHANDLE io; + sprintf(filename, "screenshots/screenshot%04d.png", index); + engine_savepath(filename, wholepath, sizeof(wholepath)); + + io = io_open(wholepath, IOFLAG_READ); + if(io) + io_close(io); + else + break; } - /* clean up */ - mem_free(pixel_data); - do_screenshot = 0; + gfx_screenshot_direct(filename); + + do_screenshot = 0; } { @@ -666,6 +641,42 @@ void gfx_swap() } } +void gfx_screenshot_direct(const char *filename) +{ + /* fetch image data */ + int y; + int w = screen_width; + int h = screen_height; + unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*4, 1); + unsigned char *temp_row = pixel_data+w*h*4; + glReadPixels(0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data); + + /* flip the pixel because opengl works from bottom left corner */ + for(y = 0; y < h/2; y++) + { + mem_copy(temp_row, pixel_data+y*w*4, w*4); + mem_copy(pixel_data+y*w*4, pixel_data+(h-y-1)*w*4, w*4); + mem_copy(pixel_data+(h-y-1)*w*4, temp_row,w*4); + } + + /* find filename */ + { + char wholepath[1024]; + png_t png; + + engine_savepath(filename, wholepath, sizeof(wholepath)); + + /* save png */ + dbg_msg("client", "saved screenshot to '%s'", wholepath); + png_open_file_write(&png, wholepath); + png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pixel_data); + png_close_file(&png); + } + + /* clean up */ + mem_free(pixel_data); +} + int gfx_screenwidth() { return screen_width; @@ -690,7 +701,7 @@ void gfx_texture_set(int slot) void gfx_clear(float r, float g, float b) { - glClearColor(r,g,b,1.0f); + glClearColor(r,g,b,0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } diff --git a/src/engine/e_config_variables.h b/src/engine/e_config_variables.h index 3707f0e6e..8396aa884 100644 --- a/src/engine/e_config_variables.h +++ b/src/engine/e_config_variables.h @@ -35,6 +35,7 @@ MACRO_CONFIG_INT(snd_nonactive_mute, 0, 0, 1) MACRO_CONFIG_INT(gfx_screen_width, 800, 0, 0) MACRO_CONFIG_INT(gfx_screen_height, 600, 0, 0) MACRO_CONFIG_INT(gfx_fullscreen, 1, 0, 1) +MACRO_CONFIG_INT(gfx_alphabits, 0, 0, 0) MACRO_CONFIG_INT(gfx_color_depth, 24, 16, 24) MACRO_CONFIG_INT(gfx_clear, 0, 0, 1) MACRO_CONFIG_INT(gfx_vsync, 1, 0, 1) diff --git a/src/engine/e_huffman.c b/src/engine/e_huffman.c index dfb5c8178..8adbb1f78 100644 --- a/src/engine/e_huffman.c +++ b/src/engine/e_huffman.c @@ -1,383 +1,262 @@ -#include -#include -#include -#include +#include /* qsort */ +#include /* memset */ +#include "e_huffman.h" -void huffman_init(HUFFSTATE *huff) +typedef struct HUFFMAN_CONSTRUCT_NODE { - mem_zero(huff, sizeof(HUFFSTATE)); - huff->nodes[0].frequency = 1; - huff->nodes[0].symbol_size = -1; - huff->num_symbols++; - huff->num_nodes++; -} - -void huffman_add_symbol(HUFFSTATE *huff, int frequency, int size, unsigned char *symbol) -{ - huff->nodes[huff->num_nodes].frequency = frequency; - huff->nodes[huff->num_nodes].symbol_size = size; - mem_copy(huff->nodes[huff->num_nodes].symbol, symbol, size); - huff->num_nodes++; - huff->num_symbols++; -} - + unsigned short node_id; + int frequency; +} HUFFMAN_CONSTRUCT_NODE; static int sort_func(const void *a, const void *b) { - if((*(HUFFNODE **)a)->frequency > (*(HUFFNODE **)b)->frequency) + if((*(HUFFMAN_CONSTRUCT_NODE **)a)->frequency > (*(HUFFMAN_CONSTRUCT_NODE **)b)->frequency) return -1; - if((*(HUFFNODE **)a)->frequency < (*(HUFFNODE **)b)->frequency) + if((*(HUFFMAN_CONSTRUCT_NODE **)a)->frequency < (*(HUFFMAN_CONSTRUCT_NODE **)b)->frequency) return 1; return 0; } -void huffman_setbits_r(HUFFNODE *node, int bits, int depth) +static void huffman_setbits_r(HUFFMAN_STATE *huff, HUFFMAN_NODE *node, int bits, int depth) { - if(node->one) - huffman_setbits_r(node->one, (bits<<1)|1, depth+1); - if(node->zero) - huffman_setbits_r(node->zero, (bits<<1), depth+1); + if(node->leafs[1] != 0xffff) + huffman_setbits_r(huff, &huff->nodes[node->leafs[1]], bits|(1<leafs[0] != 0xffff) + huffman_setbits_r(huff, &huff->nodes[node->leafs[0]], bits, depth+1); - if(node->symbol_size) + if(node->num_bits) { node->bits = bits; node->num_bits = depth; } } - -void huffman_checktree_r(HUFFNODE *node, int bits, int depth) + +static void huffman_construct_tree(HUFFMAN_STATE *huff, const unsigned *frequencies) { - if(node->one) - huffman_checktree_r(node->one, (bits<<1)|1, depth+1); - if(node->zero) - huffman_checktree_r(node->zero, (bits<<1), depth+1); - - if(node->symbol_size) + HUFFMAN_CONSTRUCT_NODE nodes_left_storage[HUFFMAN_MAX_NODES]; + HUFFMAN_CONSTRUCT_NODE *nodes_left[HUFFMAN_MAX_NODES]; + int num_nodes_left = HUFFMAN_MAX_SYMBOLS; + int i; + + /* add the symbols */ + for(i = 0; i < HUFFMAN_MAX_SYMBOLS; i++) { - /*dbg_msg("", "%p %p %d %d %d", node->one, node->zero, node->symbol[0], node->bits, node->num_bits);*/ - - if(node->bits != bits || node->num_bits != depth) - { - dbg_msg("", "crap! %d %d=%d %d!=%d", node->bits>>1, node->bits, bits, node->num_bits , depth); - /*dbg_msg("", "%p %p %d", node->one, node->zero, node->symbol[0]);*/ - } + huff->nodes[i].num_bits = -1; + huff->nodes[i].symbol = i; + huff->nodes[i].leafs[0] = -1; + huff->nodes[i].leafs[1] = -1; + + if(i == HUFFMAN_EOF_SYMBOL) + nodes_left_storage[i].frequency = 1; + else + nodes_left_storage[i].frequency = frequencies[i]; + nodes_left_storage[i].node_id = i; + nodes_left[i] = &nodes_left_storage[i]; } -} -void huffman_construct_tree(HUFFSTATE *huff) -{ - HUFFNODE *nodes_left[MAX_NODES]; - int num_nodes_left = huff->num_nodes; - int i, k; - - for(i = 0; i < num_nodes_left; i++) - nodes_left[i] = &huff->nodes[i]; + huff->num_nodes = HUFFMAN_MAX_SYMBOLS; /* construct the table */ while(num_nodes_left > 1) { - qsort(nodes_left, num_nodes_left, sizeof(HUFFNODE *), sort_func); + qsort(nodes_left, num_nodes_left, sizeof(HUFFMAN_CONSTRUCT_NODE *), sort_func); - huff->nodes[huff->num_nodes].symbol_size = 0; - huff->nodes[huff->num_nodes].frequency = nodes_left[num_nodes_left-1]->frequency + nodes_left[num_nodes_left-2]->frequency; - huff->nodes[huff->num_nodes].zero = nodes_left[num_nodes_left-1]; - huff->nodes[huff->num_nodes].one = nodes_left[num_nodes_left-2]; - nodes_left[num_nodes_left-1]->parent = &huff->nodes[huff->num_nodes]; - nodes_left[num_nodes_left-2]->parent = &huff->nodes[huff->num_nodes]; - nodes_left[num_nodes_left-2] = &huff->nodes[huff->num_nodes]; + huff->nodes[huff->num_nodes].num_bits = 0; + huff->nodes[huff->num_nodes].leafs[0] = nodes_left[num_nodes_left-1]->node_id; + huff->nodes[huff->num_nodes].leafs[1] = nodes_left[num_nodes_left-2]->node_id; + nodes_left[num_nodes_left-2]->node_id = huff->num_nodes; + nodes_left[num_nodes_left-2]->frequency = nodes_left[num_nodes_left-1]->frequency + nodes_left[num_nodes_left-2]->frequency; huff->num_nodes++; num_nodes_left--; } - dbg_msg("", "%d", huff->num_nodes); - for(i = 0; i < huff->num_nodes; i++) + /* set start node */ + huff->start_node = &huff->nodes[huff->num_nodes-1]; + + /* build symbol bits */ + huffman_setbits_r(huff, huff->start_node, 0, 0); +} + +void huffman_init(HUFFMAN_STATE *huff, const unsigned *frequencies) +{ + int i; + + /* make sure to cleanout every thing */ + memset(huff, 0, sizeof(HUFFMAN_STATE)); + + /* construct the tree */ + huffman_construct_tree(huff, frequencies); + + /* build decode LUT */ + for(i = 0; i < HUFFMAN_LUTSIZE; i++) { - if(huff->nodes[i].symbol_size && (huff->nodes[i].one || huff->nodes[i].zero)) - dbg_msg("", "tree strangeness"); - - if(!huff->nodes[i].parent) + unsigned bits = i; + int k; + HUFFMAN_NODE *node = huff->start_node; + for(k = 0; k < HUFFMAN_LUTBITS; k++) { - dbg_msg("", "root %p %p", huff->nodes[i].one, huff->nodes[i].zero); - huff->start_node = &huff->nodes[i]; - } - } - - huffman_setbits_r(huff->start_node, 0, 0); - - /* - for(i = 0; i < huff->num_symbols; i++) - { - unsigned bits = 0; - int num_bits = 0; - HUFFNODE *n = &huff->nodes[i]; - HUFFNODE *p = n; - HUFFNODE *c = n->parent; - - while(c) - { - num_bits++; - if(c->one == p) - bits |= 1; - bits <<= 1; - p = c; - c = c->parent; - } + node = &huff->nodes[node->leafs[bits&1]]; + bits >>= 1; - n->bits = bits; - n->num_bits = num_bits; - }*/ - - huffman_checktree_r(huff->start_node, 0, 0); + if(!node) + break; - for(i = 0; i < huff->num_symbols; i++) - { - for(k = 0; k < huff->num_symbols; k++) - { - if(k == i) - continue; - if(huff->nodes[i].num_bits == huff->nodes[k].num_bits && huff->nodes[i].bits == huff->nodes[k].bits) - dbg_msg("", "tree error %d %d %d", i, k, huff->nodes[i].num_bits); - } - } - -} - -typedef struct -{ - unsigned char *data; - unsigned char current_bits; - int num; -} HUFFBITIO; - -int debug_count = 0; - -static void bitio_init(HUFFBITIO *bitio, unsigned char *data) -{ - bitio->data = data; - bitio->num = 0; - bitio->current_bits = 0; -} - -static void bitio_flush(HUFFBITIO *bitio) -{ - if(bitio->num == 8) - *bitio->data = bitio->current_bits << (8-bitio->num); - else - *bitio->data = bitio->current_bits; - bitio->data++; - bitio->num = 0; - bitio->current_bits = 0; -} - -static void bitio_write(HUFFBITIO *bitio, int bit) -{ - bitio->current_bits = (bitio->current_bits<<1)|bit; - bitio->num++; - if(bitio->num == 8) - bitio_flush(bitio); - - if(debug_count) - { - debug_count--; - dbg_msg("", "out %d", bit); - } -} - -static int bitio_read(HUFFBITIO *bitio) -{ - int bit; - - if(!bitio->num) - { - bitio->current_bits = *bitio->data; - bitio->data++; - bitio->num = 8; - } - - bitio->num--; - bit = (bitio->current_bits>>bitio->num)&1; - - if(debug_count) - { - debug_count--; - dbg_msg("", "in %d", bit); - } - return bit; -} - -int huffman_compress(HUFFSTATE *huff, const void *input, int input_size, void *output, int output_size) -{ - const unsigned char *src = (const unsigned char *)input; - int ret = 0; - int quit = 0; - HUFFBITIO io; - - bitio_init(&io, (unsigned char *)output); - - while(!quit) - { - int i; - int best_match = -1; - int best_match_size = 0; - - if(input_size) - { - for(i = 0; i < huff->num_symbols; i++) + if(node->num_bits) { - if(huff->nodes[i].symbol_size <= input_size && huff->nodes[i].symbol_size > best_match_size) - { - if(memcmp(src, huff->nodes[i].symbol, huff->nodes[i].symbol_size) == 0) - { - best_match = i; - best_match_size = huff->nodes[i].symbol_size; - } - } + huff->decode_lut[i] = node; + break; } } + + if(k == HUFFMAN_LUTBITS) + huff->decode_lut[i] = node; + } + +} + +/*****************************************************************/ +int huffman_compress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size) +{ + /* this macro loads a symbol for a byte into bits and bitcount */ +#define HUFFMAN_MACRO_LOADSYMBOL(sym) \ + bits |= huff->nodes[sym].bits << bitcount; \ + bitcount += huff->nodes[sym].num_bits; + + /* this macro writes the symbol stored in bits and bitcount to the dst pointer */ +#define HUFFMAN_MACRO_WRITE() \ + while(bitcount >= 8) \ + { \ + *dst++ = (unsigned char)(bits&0xff); \ + if(dst == dst_end) \ + return -1; \ + bits >>= 8; \ + bitcount -= 8; \ + } + + /* setup buffer pointers */ + const unsigned char *src = (const unsigned char *)input; + const unsigned char *src_end = src + input_size; + unsigned char *dst = (unsigned char *)output; + unsigned char *dst_end = dst + output_size; + + /* symbol variables */ + unsigned bits = 0; + unsigned bitcount = 0; + + /* make sure that we have data that we want to compress */ + if(input_size) + { + /* {A} load the first symbol */ + int symbol = *src++; + + while(src != src_end) + { + /* {B} load the symbol */ + HUFFMAN_MACRO_LOADSYMBOL(symbol) + + /* {C} fetch next symbol, this is done here because it will reduce dependency in the code */ + symbol = *src++; + + /* {B} write the symbol loaded at */ + HUFFMAN_MACRO_WRITE() + } + + /* write the last symbol loaded from {C} or {A} in the case of only 1 byte input buffer */ + HUFFMAN_MACRO_LOADSYMBOL(symbol) + HUFFMAN_MACRO_WRITE() + } + + /* write EOF symbol */ + HUFFMAN_MACRO_LOADSYMBOL(HUFFMAN_EOF_SYMBOL) + HUFFMAN_MACRO_WRITE() + + /* write out the last bits */ + *dst++ = bits; + + /* return the size of the output */ + return (int)(dst - (const unsigned char *)output); + + /* remove macros */ +#undef HUFFMAN_MACRO_LOADSYMBOL +#undef HUFFMAN_MACRO_WRITE +} + +/*****************************************************************/ +int huffman_decompress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size) +{ + /* setup buffer pointers */ + unsigned char *dst = (unsigned char *)output; + unsigned char *src = (unsigned char *)input; + unsigned char *dst_end = dst + output_size; + unsigned char *src_end = src + input_size; + + unsigned bits = 0; + unsigned bitcount = 0; + + HUFFMAN_NODE *eof = &huff->nodes[HUFFMAN_EOF_SYMBOL]; + HUFFMAN_NODE *node = 0; + + while(1) + { + /* {A} try to load a node now, this will reduce dependency at location {D} */ + node = 0; + if(bitcount >= HUFFMAN_LUTBITS) + node = huff->decode_lut[bits&HUFFMAN_LUTMASK]; + + /* {B} fill with new bits */ + while(bitcount < 24 && src != src_end) + { + bits |= (*src++) << bitcount; + bitcount += 8; + } + + /* {C} load symbol now if we didn't that earlier at location {A} */ + if(!node) + node = huff->decode_lut[bits&HUFFMAN_LUTMASK]; + + /* {D} check if we hit a symbol already */ + if(node->num_bits) + { + /* remove the bits for that symbol */ + bits >>= node->num_bits; + bitcount -= node->num_bits; + } else { - best_match = 0; - best_match_size = 0; - quit = 1; - } - - - if(best_match == -1) - { - dbg_msg("huffman", "couldn't find symbol! %d left", input_size); - return -1; - } - - i = huff->nodes[best_match].num_bits; - for(i = huff->nodes[best_match].num_bits-1; i >= 0; i--) - bitio_write(&io, (huff->nodes[best_match].bits>>i)&1); + /* remove the bits that the lut checked up for us */ + bits >>= HUFFMAN_LUTBITS; + bitcount -= HUFFMAN_LUTBITS; - if(debug_count) - dbg_msg("", "--"); - - ret += huff->nodes[best_match].num_bits; - input_size -= best_match_size; - src += best_match_size; - } - - bitio_flush(&io); - return ret; -} + /* walk the tree bit by bit */ + while(1) + { + /* traverse tree */ + node = &huff->nodes[node->leafs[bits&1]]; -int huffman_decompress(HUFFSTATE *huff, const void *input, int input_size, void *output, int output_size) -{ - unsigned char *dst = (unsigned char *)output; - HUFFBITIO io; - int size = 0; - - bitio_init(&io, (unsigned char *)input); - - while(size < 1401) - { - HUFFNODE *node = huff->start_node; - int i; - - while(node) - { - if(node->symbol_size) - break; - - if(bitio_read(&io)) - node = node->one; - else - node = node->zero; + /* remove bit */ + bitcount--; + bits >>= 1; + + /* check if we hit a symbol */ + if(node->num_bits) + break; + + /* no more bits, decoding error */ + if(bitcount == 0) + return -1; + } } - if(debug_count) - dbg_msg("", "-- %d %d", node->bits, node->num_bits); - /* check for eof */ - if(node == &huff->nodes[0]) + if(node == eof) break; - - for(i = 0; i < node->symbol_size; i++) - { - *dst++ = node->symbol[i]; - size++; - } + + /* output character */ + if(dst == dst_end) + return -1; + *dst++ = node->symbol; } - - return size; -} - -unsigned char test_data[1024*64]; -int test_data_size; - -unsigned char compressed_data[1024*64]; -int compressed_data_size; - -unsigned char output_data[1024*64]; -int output_data_size; - -HUFFSTATE state; - -int huffman_test() -{ - huffman_init(&state); - - dbg_msg("", "test test"); - - /* bitio testing */ - { - char bits[] = {1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1,1,1,1,1,1,1,0}; - unsigned char buf[64]; - int i; - HUFFBITIO io; - - bitio_init(&io, buf); - for(i = 0; i < sizeof(bits); i++) - bitio_write(&io, bits[i]); - - bitio_flush(&io); - bitio_init(&io, buf); - for(i = 0; i < sizeof(bits); i++) - { - if(bitio_read(&io) != bits[i]) - dbg_msg("", "bitio failed at %d", i); - } - } - - /* read test data */ - { - IOHANDLE io = io_open("license.txt", IOFLAG_READ); - test_data_size = io_read(io, test_data, sizeof(test_data)); - io_close(io); - } - - /* add symbols */ - { - int counts[256] = {0}; - int i; - for(i = 0; i < test_data_size; i++) - counts[test_data[i]]++; - - for(i = 0; i < 256; i++) - { - unsigned char symbol = (unsigned char )i; - if(counts[i]) - huffman_add_symbol(&state, counts[i], 1, &symbol); - } - } - - huffman_construct_tree(&state); - /*debug_count = 20;*/ - compressed_data_size = huffman_compress(&state, test_data, test_data_size, compressed_data, sizeof(compressed_data)); - /*debug_count = 20;*/ - output_data_size = huffman_decompress(&state, compressed_data, compressed_data_size, output_data, sizeof(output_data)); - - dbg_msg("huffman", "%d -> %d -> %d", test_data_size, compressed_data_size/8, output_data_size); - - /* write test data */ - { - IOHANDLE io = io_open("out.txt", IOFLAG_WRITE); - io_write(io, output_data, output_data_size); - io_close(io); - } - - return 0; + + /* return the size of the decompressed buffer */ + return (int)(dst - (const unsigned char *)output); } diff --git a/src/engine/e_huffman.h b/src/engine/e_huffman.h index 84c71e609..c4e202234 100644 --- a/src/engine/e_huffman.h +++ b/src/engine/e_huffman.h @@ -1,43 +1,91 @@ +#ifndef __HUFFMAN_HEADER__ +#define __HUFFMAN_HEADER__ + +#ifdef __cplusplus +extern "C" { +#endif enum { - MAX_SYMBOL_SIZE=8, - MAX_NODES=1024*8 + HUFFMAN_EOF_SYMBOL = 256, + + HUFFMAN_MAX_SYMBOLS=HUFFMAN_EOF_SYMBOL+1, + HUFFMAN_MAX_NODES=HUFFMAN_MAX_SYMBOLS*2-1, + + HUFFMAN_LUTBITS = 10, + HUFFMAN_LUTSIZE = (1< +*/ +void gfx_screenshot_direct(const char *filename); + /* Function: gfx_clip_enable TODO diff --git a/src/engine/e_network.c b/src/engine/e_network.c index 1e320293d..d3560d849 100644 --- a/src/engine/e_network.c +++ b/src/engine/e_network.c @@ -154,12 +154,8 @@ typedef struct unsigned state; int token; - int remote_closed; - int connected; - int disconnected; - RINGBUFFER buffer; int64 last_update_time; @@ -213,27 +209,10 @@ struct NETCLIENT_t }; static IOHANDLE datalog = 0; -static HUFFSTATE huffmanstate; +static HUFFMAN_STATE huffmanstate; #define COMPRESSION 1 -typedef struct pcap_hdr_s { - unsigned magic_number; /* magic number */ - short version_major; /* major version number */ - short version_minor; /* minor version number */ - int thiszone; /* GMT to local correction */ - unsigned sigfigs; /* accuracy of timestamps */ - unsigned snaplen; /* max length of captured packets, in octets */ - unsigned network; /* data link type */ -} pcap_hdr_t; - -typedef struct pcaprec_hdr_s { - unsigned ts_sec; /* timestamp seconds */ - unsigned ts_usec; /* timestamp microseconds */ - unsigned incl_len; /* number of octets of packet saved in file */ - unsigned orig_len; /* actual length of packet */ -} pcaprec_hdr_t; - /* packs the data tight and sends it */ static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet) { @@ -249,7 +228,7 @@ static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *pac if(COMPRESSION) { - int compressed_size = (huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4)+7)/8; + 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); } else @@ -276,9 +255,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa packet->data_size = size - NET_PACKETHEADERSIZE; if(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); @@ -326,12 +303,7 @@ static void conn_reset(NETCONNECTION *conn) conn->ack = 0; conn->remote_closed = 0; - if(conn->state == NET_CONNSTATE_ONLINE || - conn->state == NET_CONNSTATE_ERROR) - { - conn->disconnected++; - } - + conn->state = NET_CONNSTATE_OFFLINE; conn->state = NET_CONNSTATE_OFFLINE; conn->last_send_time = 0; conn->last_recv_time = 0; @@ -340,6 +312,8 @@ static void conn_reset(NETCONNECTION *conn) mem_zero(&conn->peeraddr, sizeof(conn->peeraddr)); rb_clear(&conn->buffer); + + mem_zero(&conn->construct, sizeof(conn->construct)); } @@ -358,8 +332,6 @@ static void conn_init(NETCONNECTION *conn, NETSOCKET socket) conn_reset(conn); conn_reset_stats(conn); conn->socket = socket; - conn->connected = 0; - conn->disconnected = 0; rb_init(&conn->buffer); mem_zero(conn->error_string, sizeof(conn->error_string)); } @@ -489,6 +461,9 @@ static int conn_connect(NETCONNECTION *conn, NETADDR *addr) static void conn_disconnect(NETCONNECTION *conn, const char *reason) { + if(conn->state == NET_CONNSTATE_OFFLINE) + return; + if(conn->remote_closed == 0) { if(reason) @@ -518,8 +493,6 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETCONSTRUCT *packet, NETADDR *a { int ctrlmsg = packet->chunk_data[0]; - dbg_msg("connection", "\tgot control message %d", ctrlmsg); - if(ctrlmsg == NET_CTRLMSG_CLOSE) { conn->state = NET_CONNSTATE_ERROR; @@ -554,7 +527,6 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETCONSTRUCT *packet, NETADDR *a /* send response and init connection */ conn_reset(conn); conn->state = NET_CONNSTATE_ONLINE; - conn->connected++; conn->peeraddr = *addr; conn->last_send_time = now; conn->last_recv_time = now; @@ -571,7 +543,6 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETCONSTRUCT *packet, NETADDR *a { conn_send_control(conn, NET_CTRLMSG_ACCEPT, 0, 0); conn->state = NET_CONNSTATE_ONLINE; - conn->connected++; if(config.debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } @@ -1088,7 +1059,7 @@ void netcommon_openlog(const char *filename) } -static const int freq_table[256+1] = { +static const unsigned freq_table[256+1] = { 1<<30,4545,2657,431,1950,919,444,482,2244,617,838,542,715,1814,304,240,754,212,647,186, 283,131,146,166,543,164,167,136,179,859,363,113,157,154,204,108,137,180,202,176, 872,404,168,134,151,111,113,109,120,126,129,100,41,20,16,22,18,18,17,19, @@ -1105,13 +1076,5 @@ static const int freq_table[256+1] = { void netcommon_init() { - int i; - huffman_init(&huffmanstate); - for(i = 0; i < 256; i++) - { - unsigned char sym = (unsigned char)i; - huffman_add_symbol(&huffmanstate, freq_table[i], 1, &sym); - } - - huffman_construct_tree(&huffmanstate); + huffman_init(&huffmanstate, freq_table); } diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c index 7ed8712b3..6e015dbed 100644 --- a/src/engine/server/es_server.c +++ b/src/engine/server/es_server.c @@ -331,7 +331,7 @@ int server_send_msg(int client_id) packet.flags |= NETSENDFLAG_VITAL; if(info->flags&MSGFLAG_FLUSH) packet.flags |= NETSENDFLAG_FLUSH; - + if(client_id == -1) { /* broadcast */ @@ -594,6 +594,7 @@ static void server_process_client_packet(NETCHUNK *packet) int cid = packet->client_id; int sys; int msg = msg_unpack_start(packet->data, packet->data_size, &sys); + if(sys) { /* system message */ diff --git a/src/game/client/gc_render.cpp b/src/game/client/gc_render.cpp index 5a2af6970..28e16686f 100644 --- a/src/game/client/gc_render.cpp +++ b/src/game/client/gc_render.cpp @@ -16,6 +16,25 @@ static float sprite_w_scale; static float sprite_h_scale; +static void layershot_begin() +{ + if(!config.cl_layershot) + return; + + gfx_clear(0,0,0); +} + +static void layershot_end() +{ + if(!config.cl_layershot) + return; + + char buf[256]; + str_format(buf, sizeof(buf), "screenshots/layers_%04d.png", config.cl_layershot); + gfx_screenshot_direct(buf); + config.cl_layershot++; +} + void select_sprite(SPRITE *spr, int flags, int sx, int sy) { int x = spr->x+sx; @@ -299,7 +318,7 @@ static void envelope_eval(float time_offset, int env, float *channels) void render_layers(float center_x, float center_y, int pass) { bool passed_gamelayer = false; - + for(int g = 0; g < layers_num_groups(); g++) { MAPITEM_GROUP *group = layers_get_group(g); @@ -353,6 +372,8 @@ void render_layers(float center_x, float center_y, int pass) if(render && !is_game_layer) { + layershot_begin(); + if(layer->type == LAYERTYPE_TILES) { MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer; @@ -381,8 +402,9 @@ void render_layers(float center_x, float center_y, int pass) render_quads(quads, qlayer->num_quads, envelope_eval, LAYERRENDERFLAG_OPAQUE); gfx_blend_normal(); render_quads(quads, qlayer->num_quads, envelope_eval, LAYERRENDERFLAG_TRANSPARENT); - } + + layershot_end(); } } @@ -502,25 +524,39 @@ void render_world(float center_x, float center_y, float zoom) gfx_clip_disable(); // render trails + layershot_begin(); particle_render(PARTGROUP_PROJECTILE_TRAIL); + layershot_end(); // render items + layershot_begin(); render_items(); + layershot_end(); // render players above all + layershot_begin(); render_players(); + layershot_end(); // render particles + layershot_begin(); particle_render(PARTGROUP_EXPLOSIONS); particle_render(PARTGROUP_GENERAL); + layershot_end(); if(config.dbg_flow) flow_dbg_render(); // render foreground layers + layershot_begin(); render_layers(center_x, center_y, 1); + layershot_end(); gfx_clip_disable(); // render damage indications + layershot_begin(); render_damage_indicators(); + layershot_end(); + + config.cl_layershot = 0; } diff --git a/src/game/g_variables.hpp b/src/game/g_variables.hpp index fb69584ee..c0852bc42 100644 --- a/src/game/g_variables.hpp +++ b/src/game/g_variables.hpp @@ -16,6 +16,7 @@ MACRO_CONFIG_INT(cl_mouse_deadzone, 300, 0, 0) MACRO_CONFIG_INT(cl_mouse_followfactor, 60, 0, 200) MACRO_CONFIG_INT(cl_mouse_max_distance, 800, 0, 0) +MACRO_CONFIG_INT(cl_layershot, 0, 0, 1) MACRO_CONFIG_INT(ed_showkeys, 0, 0, 1)