larger restructure to improve security

This commit is contained in:
Magnus Auvinen 2008-02-24 16:03:58 +00:00
parent 1ea859c431
commit 4739966e14
34 changed files with 1145 additions and 312 deletions

View file

@ -81,4 +81,3 @@ const array:int image = images.*
const array:int sprite = sprites.*.*
const array:int anim = animations.*
const array:int powerup = powerups.*
const array:int gametype = playerstats.*

View file

@ -1,7 +1,6 @@
const array:int sound = sounds.*
const array:int weapon = weapons.*
const array:int powerup = powerups.*
const array:int gametype = playerstats.*
struct weapon {
int firedelay = firedelay@1

View file

@ -5,6 +5,11 @@ if family == "windows" then
dc_compiler = "scripts\\compiler.py"
end
netobj_compiler = "python scripts/netobj.py"
if family == "windows" then
netobj_compiler = "scripts\\netobj.py"
end
dat2c_compiler = "python scripts/dat2c.py"
if family == "windows" then
dat2c_compiler = "scripts\\dat2c.py"
@ -56,6 +61,15 @@ function dc_cdata(output, data, script)
return os.execute(dc_compiler .. " " .. data .. " " .. script .. " -c " .. output)
end
function netobj_source(output, proto)
print("netobj source " .. PathFilename(output) .. " = " .. PathFilename(proto))
return os.execute(netobj_compiler .. " source " .. proto .. " " .. output)
end
function netobj_header(output, proto)
print("netobj header " .. PathFilename(output) .. " = " .. PathFilename(proto))
return os.execute(netobj_compiler .. " header " .. proto .. " " .. output)
end
function CHash(output, ...)
local inputs = {}
@ -91,6 +105,17 @@ function Dat2c(datafile, sourcefile, arrayname)
return sourcefile
end
function NetObjCompile(protofile, sourcefile, headerfile)
protofile = Path(protofile)
sourcefile = Path(sourcefile)
headerfile = Path(headerfile)
bam_add_job("netobj_source", sourcefile, protofile)
bam_add_job("netobj_header", headerfile, protofile)
bam_add_dependency(sourcefile, protofile)
bam_add_dependency(headerfile, protofile)
return {source = sourcefile, header=headerfile}
end
function DataCompile(datafile, scriptfile, headerfile, sourcefile, outputdatafile)
datafile = Path(datafile)
scriptfile = Path(scriptfile)
@ -137,11 +162,16 @@ networkdata = DataCompile(
"datasrc/network.dts",
"src/game/generated/g_protocol_ids.h",
"src/game/generated/g_protocol_ids.cpp")
netobj = NetObjCompile(
"src/game/g_protocol.def",
"src/game/generated/g_protocol.cpp",
"src/game/generated/g_protocol.h")
nethash = CHash(
"src/game/generated/nethash.c",
"src/engine/e_protocol.h",
"src/game/g_protocol.h",
"src/game/generated/g_protocol.h",
"src/game/g_tuning.h",
"src/game/g_game.cpp", networkdata.header)
@ -260,7 +290,7 @@ function build(settings)
server = Compile(server_settings, Collect("src/engine/server/*.c"))
masterserver = Compile(settings, Collect("src/mastersrv/*.cpp"))
game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash)
game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash, netobj.source)
game_client = Compile(settings, Collect("src/game/client/*.cpp"), clientdata.source, clientdata.cdata)
game_server = Compile(settings, Collect("src/game/server/*.cpp"), serverdata.source, serverdata.cdata)
game_editor = Compile(settings, Collect("src/game/editor/*.cpp"))

View file

@ -487,8 +487,8 @@ class translator:
for s in self.structs:
s.emit_header_code(out)
print >>out, ""
print >>out, "data_container *load_data_from_file(const char *filename);"
print >>out, "data_container *load_data_from_memory(unsigned char *filename);"
print >>out, "struct data_container *load_data_from_file(const char *filename);"
print >>out, "struct data_container *load_data_from_memory(unsigned char *filename);"
print >>out, ""

270
scripts/netobj.py Normal file
View file

@ -0,0 +1,270 @@
import sys, os
line_count = 0
class variable:
name = "unknown"
def __init__(self, args, name):
global line_count
self.name = name
self.line = line_count
def emit_declaration(self):
return ["\tint %s;" % self.name]
def linedef(self):
return "#line %d" % self.line
def emit_secure(self):
return []
class var_any(variable):
def __init__(self, args, name):
variable.__init__(self, args, name)
class var_range(variable):
def __init__(self, args, name):
variable.__init__(self, args, name)
self.min = args[0]
self.max = args[1]
def emit_secure(self):
return [self.linedef(), "obj->%s = netobj_clamp_int(obj->%s, %s, %s);" % (self.name, self.name, self.min, self.max)]
class var_clientid(variable):
def __init__(self, args, name):
variable.__init__(self, args, name)
def emit_secure(self):
return [self.linedef(), "obj->%s = netobj_clamp_int(obj->%s, -1, MAX_CLIENTS);" % (self.name, self.name)]
class var_string(variable):
def __init__(self, args, name):
variable.__init__(self, args, name)
class object:
def __init__(self, line):
fields = line.split()
self.name = fields[1]
self.extends = None
if len(fields) == 4 and fields[2] == "extends":
self.extends = fields[3]
self.enum_name = "NETOBJTYPE_%s" % self.name.upper()
self.struct_name = "NETOBJ_%s" % self.name.upper()
self.members = []
def parse(self, lines):
global line_count
for index in xrange(0, len(lines)):
line_count += 1
line = lines[index]
if not len(line):
continue
if line == "end":
return lines[index+1:]
else:
# check for argument
fields = line.split(")", 1)
if len(fields) == 2:
names = [line.strip() for line in fields[1].split(",")]
l = fields[0].split("(", 1)
type = l[0]
args = [line.strip() for line in l[1].split(",")]
else:
l = fields[0].split(None, 1)
type = l[0]
args = []
names = [line.strip() for line in l[1].split(",")]
for name in names:
create_string = 'var_%s(%s, "%s")' % (type, args, name)
new_member = eval(create_string)
self.members += [new_member]
raise BaseException("Parse error")
def emit_declaration(self):
lines = []
if self.extends:
lines += ["struct %s : public NETOBJ_%s\n {" % (self.struct_name, self.extends.upper())]
else:
lines += ["struct %s\n {" % self.struct_name]
for m in self.members:
lines += m.emit_declaration()
lines += ["};"]
return lines
def emit_secure(self):
lines = []
for m in self.members:
lines += m.emit_secure()
return lines
class event(object):
def __init__(self, line):
object.__init__(self, line)
self.enum_name = "NETEVENTTYPE_%s" % self.name.upper()
self.struct_name = "NETEVENT_%s" % self.name.upper()
class raw_reader:
def __init__(self):
self.raw_lines = []
def parse(self, lines):
global line_count
for index in xrange(0, len(lines)):
line_count += 1
line = lines[index]
if not len(line):
continue
if line == "end":
return lines[index+1:]
else:
self.raw_lines += [line]
raise BaseException("Parse error")
class proto:
def __init__(self):
self.objects = []
self.source_raw = []
self.header_raw = []
def load(filename):
# read the file
global line_count
line_count = 0
lines = [line.strip() for line in file(filename).readlines()]
p = proto()
while len(lines):
line_count += 1
line = lines[0]
line = line.split("//", 2)[0] # strip comment
if not len(line):
del lines[0]
continue
fields = line.split(None, 1)
del lines[0]
if fields[0] == "object" or fields[0] == "msg":
new_obj = object(line)
lines = new_obj.parse(lines)
p.objects += [new_obj]
elif fields[0] == "event":
new_obj = event(line)
lines = new_obj.parse(lines)
p.objects += [new_obj]
elif fields[0] == "raw_source":
raw = raw_reader()
lines = raw.parse(lines)
p.source_raw += raw.raw_lines
elif fields[0] == "raw_header":
raw = raw_reader()
lines = raw.parse(lines)
p.header_raw += raw.raw_lines
else:
print "error, strange line:", line
return p
def emit_header_file(f, p):
for l in p.header_raw:
print >>f, l
if 1: # emit the enum table
print >>f, "enum {"
print >>f, "\tNETOBJTYPE_INVALID=0,"
for obj in p.objects:
print >>f, "\t%s," % obj.enum_name
print >>f, "\tNUM_NETOBJTYPES"
print >>f, "};"
print >>f, ""
print >>f, "int netobj_secure(int type, void *data, int size);"
print >>f, "const char *netobj_get_name(int type);"
print >>f, ""
for obj in p.objects:
for l in obj.emit_declaration():
print >>f, l
print >>f, ""
def emit_source_file(f, p, protofilename):
print >>f, "#line 1 \"%s\"" % os.path.abspath(protofilename)
for l in p.source_raw:
print >>f, l
print >>f, "static int netobj_clamp_int(int v, int min, int max)"
print >>f, "{"
print >>f, "if(v<min) return min;"
print >>f, "if(v>max) return max;"
print >>f, "return v;"
print >>f, "}"
print >>f, ""
if 1: # names
print >>f, "static const char *object_names[] = {"
print >>f, "\t" + '"invalid",'
for obj in p.objects:
print >>f, '\t"%s",' % obj.name
print >>f, '\t""'
print >>f, "};"
print >>f, ""
if 1: # secure functions
print >>f, "static int secure_object_invalid(void *data, int size) { return 0; }"
for obj in p.objects:
print >>f, "static int secure_%s(void *data, int size)" % obj.name
print >>f, "{"
print >>f, "\t%s *obj = (%s *)data;" % (obj.struct_name, obj.struct_name)
print >>f, "\t(void)obj;" # to get rid of "unused variable" warning
print >>f, "\tif(size != sizeof(%s)) return -1;" % obj.struct_name
if obj.extends:
print >>f, "\tif(secure_%s(data, sizeof(NETOBJ_%s)) != 0) return -1;" % (obj.extends, obj.extends.upper())
for l in obj.emit_secure():
print >>f, "\t" + l
print >>f, "\treturn 0;";
print >>f, "}"
print >>f, ""
if 1: # secure function table
print >>f, "typedef static int(*SECUREFUNC)(void *data, int size);"
print >>f, "static SECUREFUNC secure_funcs[] = {"
print >>f, "\t" + 'secure_object_invalid,'
for obj in p.objects:
print >>f, "\tsecure_%s," % obj.name
print >>f, "\t" + '0x0'
print >>f, "};"
print >>f, ""
if 1:
print >>f, "int netobj_secure(int type, void *data, int size)"
print >>f, "{"
print >>f, "\tif(type < 0 || type >= NUM_NETOBJTYPES) return -1;"
print >>f, "\treturn secure_funcs[type](data, size);"
print >>f, "};"
print >>f, ""
if 1:
print >>f, "const char *netobj_get_name(int type)"
print >>f, "{"
print >>f, "\tif(type < 0 || type >= NUM_NETOBJTYPES) return \"(invalid)\";"
print >>f, "\treturn object_names[type];"
print >>f, "};"
print >>f, ""
if sys.argv[1] == "header":
p = load(sys.argv[2])
emit_header_file(file(sys.argv[3], "w"), p)
elif sys.argv[1] == "source":
p = load(sys.argv[2])
emit_source_file(file(sys.argv[3], "w"), p, sys.argv[2])
else:
print "invalid command"
sys.exit(-1)

View file

@ -211,30 +211,48 @@ enum
NUM_SNAPSHOT_TYPES=2
};
/* the game snapshots are modifiable by the game */
SNAPSTORAGE snapshot_storage;
static SNAPSTORAGE_HOLDER *snapshots[NUM_SNAPSHOT_TYPES];
static int recived_snapshots;
static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE];
/* --- */
const void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
{
SNAPSHOT_ITEM *i;
dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
i = snapshot_get_item(snapshots[snapid]->snap, index);
i = snapshot_get_item(snapshots[snapid]->alt_snap, index);
item->datasize = snapshot_get_item_datasize(snapshots[snapid]->alt_snap, index);
item->type = snapitem_type(i);
item->id = snapitem_id(i);
return (void *)snapitem_data(i);
}
const void *snap_find_item(int snapid, int type, int id)
void snap_invalidate_item(int snapid, int index)
{
SNAPSHOT_ITEM *i;
dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
i = snapshot_get_item(snapshots[snapid]->alt_snap, index);
if(i)
{
if((char *)i < (char *)snapshots[snapid]->alt_snap || (char *)i > (char *)snapshots[snapid]->alt_snap + snapshots[snapid]->snap_size)
dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
if((char *)i >= (char *)snapshots[snapid]->snap && (char *)i < (char *)snapshots[snapid]->snap + snapshots[snapid]->snap_size)
dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
i->type_and_id = -1;
}
}
void *snap_find_item(int snapid, int type, int id)
{
/* TODO: linear search. should be fixed. */
int i;
for(i = 0; i < snapshots[snapid]->snap->num_items; i++)
{
SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->snap, i);
SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->alt_snap, i);
if(snapitem_type(itm) == type && snapitem_id(itm) == id)
return (void *)snapitem_data(itm);
}
@ -762,6 +780,11 @@ static void client_process_packet(NETPACKET *packet)
int total_size = msg_unpack_int();
int size = msg_unpack_int();
const unsigned char *data = msg_unpack_raw(size);
/* check fior errors */
if(msg_unpack_error() || size <= 0 || total_size <= 0)
return;
io_write(mapdownload_file, data, size);
mapdownload_totalsize = total_size;
@ -834,7 +857,7 @@ static void client_process_packet(NETPACKET *packet)
crc = msg_unpack_int();
part_size = msg_unpack_int();
}
data = (const char *)msg_unpack_raw(part_size);
if(msg_unpack_error())
@ -882,6 +905,7 @@ static void client_process_packet(NETPACKET *packet)
complete_size = (num_parts-1) * MAX_SNAPSHOT_PACKSIZE + part_size;
/* reset snapshoting */
snapshot_part = 0;
/* find snapshot that we should use as delta */
@ -891,7 +915,7 @@ static void client_process_packet(NETPACKET *packet)
/* find delta */
if(delta_tick >= 0)
{
int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot);
int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot, 0);
if(deltashot_size < 0)
{
@ -912,17 +936,28 @@ static void client_process_packet(NETPACKET *packet)
deltasize = sizeof(int)*3;
if(complete_size)
{
{
int intsize;
int compsize = zerobit_decompress(snapshot_incomming_data, complete_size, tmpbuffer);
int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
if(compsize < 0) /* failure during decompression, bail */
return;
intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
if(intsize < 0) /* failure during decompression, bail */
return;
deltadata = tmpbuffer2;
deltasize = intsize;
}
/*dbg_msg("UNPACK", "%d unpacked with %d", game_tick, delta_tick); */
/* unpack delta */
purgetick = delta_tick;
snapsize = snapshot_unpack_delta(deltashot, (SNAPSHOT*)tmpbuffer3, deltadata, deltasize);
if(snapsize < 0)
return;
if(msg != NETMSG_SNAPEMPTY && snapshot_crc((SNAPSHOT*)tmpbuffer3) != crc)
{
if(config.debug)
@ -950,10 +985,9 @@ static void client_process_packet(NETPACKET *packet)
if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->tick < purgetick)
purgetick = snapshots[SNAP_PREV]->tick;
snapstorage_purge_until(&snapshot_storage, purgetick);
/*client_snapshot_purge_until(game_tick-50); */
/* add new */
snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3);
snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3, 1);
/* apply snapshot, cycle pointers */
recived_snapshots++;

View file

@ -125,9 +125,8 @@ long zerobit_decompress(const void *src_, int size, void *dst_)
unsigned char *src = (unsigned char *)src_;
unsigned char *dst = (unsigned char *)dst_;
unsigned char *end = src + size;
while(src != end)
while(src < end)
{
unsigned char bit = 0x80;
unsigned char mask = *src++;
@ -140,6 +139,9 @@ long zerobit_decompress(const void *src_, int size, void *dst_)
else
*dst++ = 0;
}
if(src > end)
return -1;
}
return (long)(dst-(unsigned char *)dst_);

View file

@ -1,6 +1,7 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <engine/e_system.h>
#include <engine/e_server_interface.h>
@ -25,6 +26,15 @@ const char *engine_savepath(const char *filename, char *buffer, int max)
}
int engine_stress(float probability)
{
if(!config.dbg_stress)
return 0;
if(rand()/(float)RAND_MAX < probability)
return 1;
return 0;
}
void engine_init(const char *appname)
{
dbg_msg("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING);

View file

@ -4,6 +4,7 @@ const char *engine_savepath(const char *filename, char *buffer, int max);
void engine_init(const char *appname);
void engine_parse_arguments(int argc, char **argv);
void engine_writeconfig();
int engine_stress(float probability);
enum

View file

@ -34,6 +34,7 @@ typedef struct
{
int type;
int id;
int datasize;
} SNAP_ITEM;
/*
@ -234,7 +235,7 @@ int snap_num_items(int snapid);
Returns:
Returns a pointer to the item if it exists, otherwise NULL.
*/
const void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
/*
Function: snap_find_item
@ -250,7 +251,19 @@ const void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
Returns:
Returns a pointer to the item if it exists, otherwise NULL.
*/
const void *snap_find_item(int snapid, int type, int id);
void *snap_find_item(int snapid, int type, int id);
/*
Function: snap_invalidate_item
Marks an item as invalid byt setting type and id to 0xffffffff.
Arguments:
snapid - Snapshot ID to the data to fetch.
* SNAP_PREV for previous snapshot.
* SNAP_CUR for current snapshot.
index - Index of the item.
*/
void snap_invalidate_item(int snapid, int index);
/*
Function: snap_input

View file

@ -54,7 +54,6 @@ typedef struct
unsigned char *data;
} NETPACKETDATA;
static void send_packet(NETSOCKET socket, NETADDR4 *addr, NETPACKETDATA *packet)
{
unsigned char buffer[NETWORK_MAX_PACKET_SIZE];
@ -356,7 +355,18 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr)
conn->remote_closed = 1;
if(p->data_size)
conn_set_error(conn, (char *)p->data);
{
/* make sure to sanitize the error string form the other party*/
char str[128];
if(p->data_size < 128)
str_copy(str, (char *)p->data, p->data_size);
else
str_copy(str, (char *)p->data, 128);
str_sanitize_strong(str);
/* set the error string */
conn_set_error(conn, str);
}
else
conn_set_error(conn, "no reason given");
if(config.debug)
@ -739,7 +749,7 @@ int netserver_recv(NETSERVER *s, NETPACKET *packet)
else
{
/* errornous packet, drop it */
dbg_msg("server", "crazy packet");
/* dbg_msg("server", "crazy packet"); */
}
/* read header */
@ -751,7 +761,11 @@ int netserver_recv(NETSERVER *s, NETPACKET *packet)
int netserver_send(NETSERVER *s, NETPACKET *packet)
{
dbg_assert(packet->data_size < NETWORK_MAX_PAYLOAD, "packet payload too big");
if(packet->data_size >= NETWORK_MAX_PAYLOAD)
{
dbg_msg("netserver", "packet payload too big. %d. dropping packet", packet->data_size);
return -1;
}
if(packet->flags&PACKETFLAG_CONNLESS)
{
@ -898,7 +912,11 @@ int netclient_recv(NETCLIENT *c, NETPACKET *packet)
int netclient_send(NETCLIENT *c, NETPACKET *packet)
{
dbg_assert(packet->data_size < NETWORK_MAX_PAYLOAD, "packet payload too big");
if(packet->data_size >= NETWORK_MAX_PAYLOAD)
{
dbg_msg("netclient", "packet payload too big. %d. dropping packet", packet->data_size);
return -1;
}
if(packet->flags&PACKETFLAG_CONNLESS)
{

View file

@ -1,12 +1,39 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <stdlib.h>
#include "e_system.h"
#include "e_packer.h"
#include "e_compression.h"
#include "e_engine.h"
/* useful for debugging */
#define packing_error(p) p->error = 1
/* #define packing_error(p) p->error = 1; dbg_break() */
#if 0
#define packing_error(p) p->error = 1; dbg_break()
#else
#define packing_error(p) p->error = 1
#endif
int stress_get_int()
{
static const int nasty[] = {-1, 0, 1, 66000, -66000, (-1<<31), 0x7fffffff};
if(rand()&1)
return rand();
return nasty[rand()%6];
}
const char *stress_get_string(int *size)
{
static char noise[1024];
int i;
int s;
s = (rand()%1024)-1;
for(i = 0; i < s; i++)
noise[i] = (rand()%254)+1;
noise[s] = 0;
if(size)
*size = s;
return noise;
}
void packer_reset(PACKER *p)
{
@ -19,6 +46,9 @@ void packer_add_int(PACKER *p, int i)
{
if(p->error)
return;
/*if(engine_stress(0.05f))
i = stress_get_int();*/
/* make sure that we have space enough */
if(p->end - p->current < 6)
@ -35,6 +65,15 @@ void packer_add_string(PACKER *p, const char *str, int limit)
if(p->error)
return;
/* STRESS: do this better */
/*
if(engine_stress(0.1f))
{
str = stress_get_string(0);
limit = 0;
}*/
/* */
if(limit > 0)
{
while(*str && limit != 0)
@ -105,8 +144,14 @@ void unpacker_reset(UNPACKER *p, const unsigned char *data, int size)
int unpacker_get_int(UNPACKER *p)
{
int i;
if(p->error || p->current >= p->end)
if(p->error)
return 0;
if(p->current >= p->end)
{
packing_error(p);
return 0;
}
p->current = vint_unpack(p->current, &i);
if(p->current > p->end)
{
@ -118,11 +163,11 @@ int unpacker_get_int(UNPACKER *p)
const char *unpacker_get_string(UNPACKER *p)
{
const char *ptr;
char *ptr;
if(p->error || p->current >= p->end)
return "";
ptr = (const char *)p->current;
ptr = (char *)p->current;
while(*p->current) /* skip the string */
{
p->current++;
@ -133,17 +178,26 @@ const char *unpacker_get_string(UNPACKER *p)
}
}
p->current++;
/* sanitize all strings */
str_sanitize(ptr);
return ptr;
}
const unsigned char *unpacker_get_raw(UNPACKER *p, int size)
{
const unsigned char *ptr = p->current;
p->current += size;
if(p->current > p->end)
if(p->error)
return 0;
/* check for nasty sizes */
if(size < 0 || p->current+size > p->end)
{
packing_error(p);
return 0;
}
/* "unpack" the data */
p->current += size;
return ptr;
}

View file

@ -1,6 +1,7 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <stdlib.h>
#include "e_snapshot.h"
#include "e_engine.h"
#include "e_compression.h"
#include "e_common_interface.h"
@ -317,6 +318,8 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_
SNAPBUILD builder;
SNAPSHOT_DELTA *delta = (SNAPSHOT_DELTA *)srcdata;
int *data = (int *)delta->data;
int *end = (int *)(((char *)srcdata + data_size));
SNAPSHOT_ITEM *fromitem;
int i, d, keep, itemsize;
int *deleted;
@ -329,6 +332,8 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_
/* unpack deleted stuff */
deleted = data;
data += delta->num_deleted_items;
if(data > end)
return -1;
/* copy all non deleted stuff */
for(i = 0; i < from->num_items; i++)
@ -358,11 +363,17 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_
/* unpack updated stuff */
for(i = 0; i < delta->num_update_items; i++)
{
if(data+3 > end)
return -1;
itemsize = *data++;
type = *data++;
id = *data++;
snapshot_current = type;
if(data+itemsize/4 > end)
return -1;
key = (type<<16)|id;
/* create the item if needed */
@ -442,10 +453,16 @@ void snapstorage_purge_until(SNAPSTORAGE *ss, int tick)
ss->last = 0;
}
void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data)
void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data, int create_alt)
{
/* allocate memory for holder + snapshot_data */
SNAPSTORAGE_HOLDER *h = (SNAPSTORAGE_HOLDER *)mem_alloc(sizeof(SNAPSTORAGE_HOLDER)+data_size, 1);
SNAPSTORAGE_HOLDER *h;
int total_size = sizeof(SNAPSTORAGE_HOLDER)+data_size;
if(create_alt)
total_size += data_size;
h = (SNAPSTORAGE_HOLDER *)mem_alloc(total_size, 1);
/* set data */
h->tick = tick;
@ -453,6 +470,15 @@ void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, vo
h->snap_size = data_size;
h->snap = (SNAPSHOT*)(h+1);
mem_copy(h->snap, data, data_size);
if(create_alt) /* create alternative if wanted */
{
h->alt_snap = (SNAPSHOT*)(((char *)h->snap) + data_size);
mem_copy(h->alt_snap, data, data_size);
}
else
h->alt_snap = 0;
/* link */
h->next = 0;
@ -464,7 +490,7 @@ void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, vo
ss->last = h;
}
int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data)
int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data, SNAPSHOT **alt_data)
{
SNAPSTORAGE_HOLDER *h = ss->first;
@ -476,6 +502,8 @@ int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data)
*tagtime = h->tagtime;
if(data)
*data = h->snap;
if(alt_data)
*alt_data = h->alt_snap;
return h->snap_size;
}
@ -524,6 +552,14 @@ int snapbuild_finish(SNAPBUILD *sb, void *snapdata)
void *snapbuild_new_item(SNAPBUILD *sb, int type, int id, int size)
{
SNAPSHOT_ITEM *obj = (SNAPSHOT_ITEM *)(sb->data+sb->data_size);
if(engine_stress(0.01f))
{
size += ((rand()%5) - 2)*4;
if(size < 0)
size = 0;
}
mem_zero(obj, sizeof(SNAPSHOT_ITEM) + size);
obj->type_and_id = (type<<16)|id;
sb->offsets[sb->num_items] = sb->data_size;

View file

@ -52,6 +52,7 @@ typedef struct SNAPSTORAGE_HOLDER_t
int snap_size;
SNAPSHOT *snap;
SNAPSHOT *alt_snap;
} SNAPSTORAGE_HOLDER;
typedef struct SNAPSTORAGE_t
@ -63,8 +64,8 @@ typedef struct SNAPSTORAGE_t
void snapstorage_init(SNAPSTORAGE *ss);
void snapstorage_purge_all(SNAPSTORAGE *ss);
void snapstorage_purge_until(SNAPSTORAGE *ss, int tick);
void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data);
int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data);
void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data, int create_alt);
int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data, SNAPSHOT **alt_data);
/* SNAPBUILD */

View file

@ -47,6 +47,10 @@
extern "C" {
#endif
IOHANDLE io_stdin() { return (IOHANDLE)stdin; }
IOHANDLE io_stdout() { return (IOHANDLE)stdout; }
IOHANDLE io_stderr() { return (IOHANDLE)stderr; }
IOHANDLE logfile = 0;
void dbg_assert_imp(const char *filename, int line, int test, const char *msg)
@ -462,19 +466,21 @@ int net_addr4_cmp(const NETADDR4 *a, const NETADDR4 *b)
int net_host_lookup(const char *hostname, unsigned short port, NETADDR4 *addr)
{
struct hostent* ip = gethostbyname(hostname);
struct addrinfo hints;
struct addrinfo *result;
int e;
mem_zero(&hints, sizeof(hints));
hints.ai_family = AF_INET;
if(ip && ip->h_length > 0)
{
addr->ip[0] = ip->h_addr_list[0][0];
addr->ip[1] = ip->h_addr_list[0][1];
addr->ip[2] = ip->h_addr_list[0][2];
addr->ip[3] = ip->h_addr_list[0][3];
addr->port = port;
return 0;
}
e = getaddrinfo(hostname, NULL, &hints, &result);
if(e != 0 || !result)
return -1;
return -1;
sockaddr_to_netaddr4(result->ai_addr, addr);
freeaddrinfo(result);
addr->port = port;
return 0;
}
NETSOCKET net_udp4_create(NETADDR4 bindaddr)
@ -842,6 +848,31 @@ void str_format(char *buffer, int buffer_size, const char *format, ...)
buffer[buffer_size-1] = 0; /* assure null termination */
}
/* makes sure that the string only contains the characters between 32 and 127 */
void str_sanitize_strong(char *str)
{
while(*str)
{
*str &= 0x7f;
if(*str < 32)
*str = 32;
str++;
}
}
/* makes sure that the string only contains the characters between 32 and 255 + \r\n\t */
void str_sanitize(char *str)
{
while(*str)
{
if(*str < 32 && !(*str == '\r') && !(*str == '\n') && !(*str == '\t'))
*str = ' ';
str++;
}
}
#if defined(__cplusplus)
}
#endif

View file

@ -526,6 +526,12 @@ void pstr_format(pstr *str, )*/
void str_append(char *dst, const char *src, int dst_size);
void str_copy(char *dst, const char *src, int dst_size);
void str_format(char *buffer, int buffer_size, const char *format, ...);
void str_sanitize_strong(char *str);
void str_sanitize(char *str);
IOHANDLE io_stdin();
IOHANDLE io_stdout();
IOHANDLE io_stderr();
#ifdef __cplusplus
}

View file

@ -371,14 +371,14 @@ static void server_do_snap()
snapstorage_purge_until(&clients[i].snapshots, current_tick-SERVER_TICK_SPEED);
/* save it the snapshot */
snapstorage_add(&clients[i].snapshots, current_tick, time_get(), snapshot_size, data);
snapstorage_add(&clients[i].snapshots, current_tick, time_get(), snapshot_size, data, 0);
/* find snapshot that we can preform delta against */
emptysnap.data_size = 0;
emptysnap.num_items = 0;
{
deltashot_size = snapstorage_get(&clients[i].snapshots, clients[i].last_acked_snapshot, 0, &deltashot);
deltashot_size = snapstorage_get(&clients[i].snapshots, clients[i].last_acked_snapshot, 0, &deltashot, 0);
if(deltashot_size >= 0)
delta_tick = clients[i].last_acked_snapshot;
else
@ -625,15 +625,19 @@ static void server_process_client_packet(NETPACKET *packet)
int64 tagtime;
clients[cid].last_acked_snapshot = msg_unpack_int();
if(clients[cid].last_acked_snapshot > 0)
clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0) >= 0)
clients[cid].latency = (int)(((time_get()-tagtime)*1000)/time_freq());
tick = msg_unpack_int();
size = msg_unpack_int();
/* 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;
if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0, 0) >= 0)
clients[cid].latency = (int)(((time_get()-tagtime)*1000)/time_freq());
input = &clients[cid].inputs[clients[cid].current_input];
input->timeleft = server_tick_start_time(tick)-time_get();
input->pred_tick = tick;

View file

@ -27,7 +27,7 @@ extern "C" {
struct data_container *data = 0;
int64 debug_firedelay = 0;
player_input input_data = {0};
NETOBJ_PLAYER_INPUT input_data = {0};
int input_target_lock = 0;
int chat_mode = CHATMODE_NONE;
@ -40,11 +40,16 @@ tuning_params tuning;
vec2 mouse_pos;
vec2 local_character_pos;
vec2 local_target_pos;
const obj_player_character *local_character = 0;
const obj_player_character *local_prev_character = 0;
const obj_player_info *local_info = 0;
const obj_flag *flags[2] = {0,0};
const obj_game *gameobj = 0;
/*
const NETOBJ_PLAYER_CHARACTER *local_character = 0;
const NETOBJ_PLAYER_CHARACTER *local_prev_character = 0;
const NETOBJ_PLAYER_INFO *local_info = 0;
const NETOBJ_FLAG *flags[2] = {0,0};
const NETOBJ_GAME *gameobj = 0;
*/
snapstate netobjects;
int picked_up_weapon = -1;
@ -54,7 +59,7 @@ void client_data::update_render_info()
render_info = skin_info;
// force team colors
if(gameobj && gameobj->gametype != GAMETYPE_DM)
if(netobjects.gameobj && netobjects.gameobj->gametype != GAMETYPE_DM)
{
const int team_colors[2] = {65387, 10223467};
if(team >= 0 || team <= 1)
@ -232,7 +237,7 @@ void chat_add_line(int client_id, int team, const char *line)
if(client_datas[client_id].team == -1)
chat_lines[chat_current_line].name_color = -1;
if(gameobj && gameobj->gametype != GAMETYPE_DM)
if(netobjects.gameobj && netobjects.gameobj->gametype != GAMETYPE_DM)
{
if(client_datas[client_id].team == 0)
chat_lines[chat_current_line].name_color = 0;
@ -261,41 +266,40 @@ void process_events(int snaptype)
SNAP_ITEM item;
const void *data = snap_get_item(snaptype, index, &item);
if(item.type == EVENT_DAMAGEINDICATION)
if(item.type == NETEVENTTYPE_DAMAGEIND)
{
ev_damageind *ev = (ev_damageind *)data;
NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)data;
effect_damage_indicator(vec2(ev->x, ev->y), get_direction(ev->angle));
}
else if(item.type == EVENT_AIR_JUMP)
else if(item.type == NETEVENTTYPE_AIR_JUMP)
{
ev_common *ev = (ev_common *)data;
NETEVENT_COMMON *ev = (NETEVENT_COMMON *)data;
effect_air_jump(vec2(ev->x, ev->y));
}
else if(item.type == EVENT_EXPLOSION)
else if(item.type == NETEVENTTYPE_EXPLOSION)
{
ev_explosion *ev = (ev_explosion *)data;
NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)data;
effect_explosion(vec2(ev->x, ev->y));
}
else if(item.type == EVENT_SMOKE)
/*else if(item.type == EVENT_SMOKE)
{
ev_explosion *ev = (ev_explosion *)data;
EV_EXPLOSION *ev = (EV_EXPLOSION *)data;
vec2 p(ev->x, ev->y);
}
else if(item.type == EVENT_PLAYERSPAWN)
}*/
else if(item.type == NETEVENTTYPE_SPAWN)
{
ev_explosion *ev = (ev_explosion *)data;
NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)data;
effect_playerspawn(vec2(ev->x, ev->y));
}
else if(item.type == EVENT_DEATH)
else if(item.type == NETEVENTTYPE_DEATH)
{
ev_explosion *ev = (ev_explosion *)data;
NETEVENT_DEATH *ev = (NETEVENT_DEATH *)data;
effect_playerdeath(vec2(ev->x, ev->y));
}
else if(item.type == EVENT_SOUND_WORLD)
else if(item.type == NETEVENTTYPE_SOUND_WORLD)
{
ev_sound *ev = (ev_sound *)data;
if(ev->sound >= 0 && ev->sound < NUM_SOUNDS)
snd_play_random(CHN_WORLD, ev->sound, 1.0f, vec2(ev->x, ev->y));
NETEVENT_SOUND_WORLD *ev = (NETEVENT_SOUND_WORLD *)data;
snd_play_random(CHN_WORLD, ev->soundid, 1.0f, vec2(ev->x, ev->y));
}
}
}
@ -303,12 +307,7 @@ void process_events(int snaptype)
void clear_object_pointers()
{
// clear out the invalid pointers
local_character = 0;
local_prev_character = 0;
local_info = 0;
flags[0] = 0;
flags[1] = 0;
gameobj = 0;
mem_zero(&netobjects, sizeof(netobjects));
}
void send_info(bool start)
@ -526,16 +525,16 @@ void render_goals(float x, float y, float w)
// render goals
//y = ystart+h-54;
if(gameobj && gameobj->time_limit)
if(netobjects.gameobj && netobjects.gameobj->time_limit)
{
char buf[64];
str_format(buf, sizeof(buf), "Time Limit: %d min", gameobj->time_limit);
str_format(buf, sizeof(buf), "Time Limit: %d min", netobjects.gameobj->time_limit);
gfx_text(0, x+w/2, y, 24.0f, buf, -1);
}
if(gameobj && gameobj->score_limit)
if(netobjects.gameobj && netobjects.gameobj->score_limit)
{
char buf[64];
str_format(buf, sizeof(buf), "Score Limit: %d", gameobj->score_limit);
str_format(buf, sizeof(buf), "Score Limit: %d", netobjects.gameobj->score_limit);
gfx_text(0, x+40, y, 24.0f, buf, -1);
}
}
@ -560,14 +559,14 @@ void render_spectators(float x, float y, float w)
SNAP_ITEM item;
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
if(item.type == OBJTYPE_PLAYER_INFO)
if(item.type == NETOBJTYPE_PLAYER_INFO)
{
const obj_player_info *info = (const obj_player_info *)data;
const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
if(info->team == -1)
{
if(count)
strcat(buffer, ", ");
strcat(buffer, client_datas[info->clientid].name);
strcat(buffer, client_datas[info->cid].name);
count++;
}
}
@ -595,7 +594,7 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
// render title
if(!title)
{
if(gameobj->game_over)
if(netobjects.gameobj->game_over)
title = "Game Over";
else
title = "Score Board";
@ -611,10 +610,11 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
{
gfx_text(0, x+10, y, 48, title, -1);
if(gameobj)
if(netobjects.gameobj)
{
char buf[128];
str_format(buf, sizeof(buf), "%d", gameobj->teamscore[team&1]);
int score = team ? netobjects.gameobj->teamscore_blue : netobjects.gameobj->teamscore_red;
str_format(buf, sizeof(buf), "%d", score);
tw = gfx_text_width(0, 48, buf, -1);
gfx_text(0, x+w-tw-30, y, 48, buf, -1);
}
@ -623,16 +623,16 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
y += 54.0f;
// find players
const obj_player_info *players[MAX_CLIENTS] = {0};
const NETOBJ_PLAYER_INFO *players[MAX_CLIENTS] = {0};
int num_players = 0;
for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
{
SNAP_ITEM item;
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
if(item.type == OBJTYPE_PLAYER_INFO)
if(item.type == NETOBJTYPE_PLAYER_INFO)
{
players[num_players] = (const obj_player_info *)data;
players[num_players] = (const NETOBJ_PLAYER_INFO *)data;
num_players++;
}
}
@ -644,7 +644,7 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
{
if(players[i]->score < players[i+1]->score)
{
const obj_player_info *tmp = players[i];
const NETOBJ_PLAYER_INFO *tmp = players[i];
players[i] = players[i+1];
players[i+1] = tmp;
}
@ -660,7 +660,7 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
// render player scores
for(int i = 0; i < num_players; i++)
{
const obj_player_info *info = players[i];
const NETOBJ_PLAYER_INFO *info = players[i];
// make sure that we render the correct team
if(team == -1 || info->team != team)
@ -683,18 +683,19 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
if(config.cl_show_player_ids)
{
str_format(buf, sizeof(buf), "%d | %s", info->clientid, client_datas[info->clientid].name);
str_format(buf, sizeof(buf), "%d | %s", info->cid, client_datas[info->cid].name);
gfx_text(0, x+128, y, font_size, buf, -1);
}
else
gfx_text(0, x+128, y, font_size, client_datas[info->clientid].name, -1);
gfx_text(0, x+128, y, font_size, client_datas[info->cid].name, -1);
str_format(buf, sizeof(buf), "%4d", info->latency);
float tw = gfx_text_width(0, font_size, buf, -1);
gfx_text(0, x+w-tw-35, y, font_size, buf, -1);
// render avatar
if((flags[0] && flags[0]->carried_by == info->clientid) || (flags[1] && flags[1]->carried_by == info->clientid))
if((netobjects.flags[0] && netobjects.flags[0]->carried_by == info->cid) ||
(netobjects.flags[1] && netobjects.flags[1]->carried_by == info->cid))
{
gfx_blend_normal();
gfx_texture_set(data->images[IMAGE_GAME].id);
@ -708,7 +709,7 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
gfx_quads_end();
}
render_tee(&idlestate, &client_datas[info->clientid].render_info, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28));
render_tee(&idlestate, &client_datas[info->cid].render_info, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28));
y += 50.0f;
@ -739,21 +740,21 @@ void render_game()
if(config.cl_predict)
{
if(!local_character || (local_character->health < 0) || (gameobj && gameobj->game_over))
if(!netobjects.local_character || (netobjects.local_character->health < 0) || (netobjects.gameobj && netobjects.gameobj->game_over))
{
// don't use predicted
}
else
local_character_pos = mix(predicted_prev_player.pos, predicted_player.pos, client_predintratick());
}
else if(local_character && local_prev_character)
else if(netobjects.local_character && netobjects.local_prev_character)
{
local_character_pos = mix(
vec2(local_prev_character->x, local_prev_character->y),
vec2(local_character->x, local_character->y), client_intratick());
vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y),
vec2(netobjects.local_character->x, netobjects.local_character->y), client_intratick());
}
if(local_info && local_info->team == -1)
if(netobjects.local_info && netobjects.local_info->team == -1)
spectate = true;
animstate idlestate;
@ -1089,7 +1090,7 @@ void render_game()
gfx_quads_end();
}*/
if(local_character && !spectate && !(gameobj && gameobj->game_over))
if(netobjects.local_character && !spectate && !(netobjects.gameobj && netobjects.gameobj->game_over))
{
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
@ -1097,7 +1098,7 @@ void render_game()
// render cursor
if (!menu_active && !emoticon_selector_active)
{
select_sprite(data->weapons[local_character->weapon%data->num_weapons].sprite_cursor);
select_sprite(data->weapons[netobjects.local_character->weapon%data->num_weapons].sprite_cursor);
float cursorsize = 64;
draw_sprite(local_target_pos.x, local_target_pos.y, cursorsize);
}
@ -1113,10 +1114,10 @@ void render_game()
// if weaponstage is active, put a "glow" around the stage ammo
select_sprite(SPRITE_TEE_BODY);
for (int i = 0; i < local_character->weaponstage; i++)
gfx_quads_drawTL(x+local_character->ammocount * 12 -i*12, y+22, 11, 11);
select_sprite(data->weapons[local_character->weapon%data->num_weapons].sprite_proj);
for (int i = 0; i < min(local_character->ammocount, 10); i++)
for (int i = 0; i < netobjects.local_character->weaponstage; i++)
gfx_quads_drawTL(x+netobjects.local_character->ammocount * 12 -i*12, y+22, 11, 11);
select_sprite(data->weapons[netobjects.local_character->weapon%data->num_weapons].sprite_proj);
for (int i = 0; i < min(netobjects.local_character->ammocount, 10); i++)
gfx_quads_drawTL(x+i*12,y+24,10,10);
gfx_quads_end();
@ -1127,7 +1128,7 @@ void render_game()
// render health
select_sprite(SPRITE_HEALTH_FULL);
for(; h < local_character->health; h++)
for(; h < netobjects.local_character->health; h++)
gfx_quads_drawTL(x+h*12,y,10,10);
select_sprite(SPRITE_HEALTH_EMPTY);
@ -1137,7 +1138,7 @@ void render_game()
// render armor meter
h = 0;
select_sprite(SPRITE_ARMOR_FULL);
for(; h < local_character->armor; h++)
for(; h < netobjects.local_character->armor; h++)
gfx_quads_drawTL(x+h*12,y+12,10,10);
select_sprite(SPRITE_ARMOR_EMPTY);
@ -1172,7 +1173,7 @@ void render_game()
// render victim tee
x -= 24.0f;
if(gameobj && gameobj->gametype == GAMETYPE_CTF)
if(netobjects.gameobj && netobjects.gameobj->gametype == GAMETYPE_CTF)
{
if(killmsgs[r].mode_special&1)
{
@ -1206,7 +1207,7 @@ void render_game()
if(killmsgs[r].victim != killmsgs[r].killer)
{
if(gameobj && gameobj->gametype == GAMETYPE_CTF)
if(netobjects.gameobj && netobjects.gameobj->gametype == GAMETYPE_CTF)
{
if(killmsgs[r].mode_special&2)
{
@ -1305,34 +1306,34 @@ void render_game()
}
// render goals
if(gameobj)
if(netobjects.gameobj)
{
int gametype = gameobj->gametype;
int gametype = netobjects.gameobj->gametype;
float whole = 300*gfx_screenaspect();
float half = whole/2.0f;
gfx_mapscreen(0,0,300*gfx_screenaspect(),300);
if(!gameobj->sudden_death)
if(!netobjects.gameobj->sudden_death)
{
char buf[32];
int time = 0;
if(gameobj->time_limit)
if(netobjects.gameobj->time_limit)
{
time = gameobj->time_limit*60 - ((client_tick()-gameobj->round_start_tick)/client_tickspeed());
time = netobjects.gameobj->time_limit*60 - ((client_tick()-netobjects.gameobj->round_start_tick)/client_tickspeed());
if(gameobj->game_over)
if(netobjects.gameobj->game_over)
time = 0;
}
else
time = (client_tick()-gameobj->round_start_tick)/client_tickspeed();
time = (client_tick()-netobjects.gameobj->round_start_tick)/client_tickspeed();
str_format(buf, sizeof(buf), "%d:%02d", time /60, time %60);
float w = gfx_text_width(0, 16, buf, -1);
gfx_text(0, half-w/2, 2, 16, buf, -1);
}
if(gameobj->sudden_death)
if(netobjects.gameobj->sudden_death)
{
const char *text = "Sudden Death";
float w = gfx_text_width(0, 16, text, -1);
@ -1340,7 +1341,7 @@ void render_game()
}
// render small score hud
if(!(gameobj && gameobj->game_over) && (gametype == GAMETYPE_TDM || gametype == GAMETYPE_CTF))
if(!(netobjects.gameobj && netobjects.gameobj->game_over) && (gametype == GAMETYPE_TDM || gametype == GAMETYPE_CTF))
{
for(int t = 0; t < 2; t++)
{
@ -1355,15 +1356,15 @@ void render_game()
gfx_quads_end();
char buf[32];
str_format(buf, sizeof(buf), "%d", gameobj->teamscore[t]);
str_format(buf, sizeof(buf), "%d", t?netobjects.gameobj->teamscore_blue:netobjects.gameobj->teamscore_red);
float w = gfx_text_width(0, 14, buf, -1);
if(gametype == GAMETYPE_CTF)
{
gfx_text(0, whole-20-w/2+5, 300-40-15+t*20+2, 14, buf, -1);
if(flags[t])
if(netobjects.flags[t])
{
if(flags[t]->carried_by == -2 || (flags[t]->carried_by == -1 && ((client_tick()/10)&1)))
if(netobjects.flags[t]->carried_by == -2 || (netobjects.flags[t]->carried_by == -1 && ((client_tick()/10)&1)))
{
gfx_blend_normal();
gfx_texture_set(data->images[IMAGE_GAME].id);
@ -1376,9 +1377,9 @@ void render_game()
gfx_quads_drawTL(whole-40+5, 300-40-15+t*20+1, size/2, size);
gfx_quads_end();
}
else if(flags[t]->carried_by >= 0)
else if(netobjects.flags[t]->carried_by >= 0)
{
int id = flags[t]->carried_by%MAX_CLIENTS;
int id = netobjects.flags[t]->carried_by%MAX_CLIENTS;
const char *name = client_datas[id].name;
float w = gfx_text_width(0, 10, name, -1);
gfx_text(0, whole-40-5-w, 300-40-15+t*20+2, 10, name, -1);
@ -1396,15 +1397,15 @@ void render_game()
}
// render warmup timer
if(gameobj->warmup)
if(netobjects.gameobj->warmup)
{
char buf[256];
float w = gfx_text_width(0, 24, "Warmup", -1);
gfx_text(0, 150*gfx_screenaspect()+-w/2, 50, 24, "Warmup", -1);
int seconds = gameobj->warmup/SERVER_TICK_SPEED;
int seconds = netobjects.gameobj->warmup/SERVER_TICK_SPEED;
if(seconds < 5)
str_format(buf, sizeof(buf), "%d.%d", seconds, (gameobj->warmup*10/SERVER_TICK_SPEED)%10);
str_format(buf, sizeof(buf), "%d.%d", seconds, (netobjects.gameobj->warmup*10/SERVER_TICK_SPEED)%10);
else
str_format(buf, sizeof(buf), "%d", seconds);
w = gfx_text_width(0, 24, buf, -1);
@ -1439,12 +1440,12 @@ void render_game()
}
}
if(config.debug && local_character && local_prev_character)
if(config.debug && netobjects.local_character && netobjects.local_prev_character)
{
gfx_mapscreen(0, 0, 300*gfx_screenaspect(), 300);
float speed = distance(vec2(local_prev_character->x, local_prev_character->y),
vec2(local_character->x, local_character->y));
float speed = distance(vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y),
vec2(netobjects.local_character->x, netobjects.local_character->y));
char buf[512];
str_format(buf, sizeof(buf), "%.2f", speed/2);
@ -1453,15 +1454,15 @@ void render_game()
// render score board
if(inp_key_pressed(KEY_TAB) || // user requested
(!spectate && (!local_character || local_character->health < 0)) || // not spectating and is dead
(gameobj && gameobj->game_over) // game over
(!spectate && (!netobjects.local_character || netobjects.local_character->health < 0)) || // not spectating and is dead
(netobjects.gameobj && netobjects.gameobj->game_over) // game over
)
{
gfx_mapscreen(0, 0, width, height);
float w = 650.0f;
if (gameobj && gameobj->gametype == GAMETYPE_DM)
if(netobjects.gameobj && netobjects.gameobj->gametype == GAMETYPE_DM)
{
render_scoreboard(width/2-w/2, 150.0f, w, 0, 0);
//render_scoreboard(gameobj, 0, 0, -1, 0);
@ -1469,12 +1470,12 @@ void render_game()
else
{
if(gameobj && gameobj->game_over)
if(netobjects.gameobj && netobjects.gameobj->game_over)
{
const char *text = "DRAW!";
if(gameobj->teamscore[0] > gameobj->teamscore[1])
if(netobjects.gameobj->teamscore_red > netobjects.gameobj->teamscore_blue)
text = "Red Team Wins!";
else if(gameobj->teamscore[1] > gameobj->teamscore[0])
else if(netobjects.gameobj->teamscore_blue > netobjects.gameobj->teamscore_red)
text = "Blue Team Wins!";
float w = gfx_text_width(0, 92.0f, text, -1);

View file

@ -20,11 +20,29 @@ extern vec2 local_character_pos;
extern vec2 local_target_pos;
// snap pointers
extern const obj_player_character *local_character;
extern const obj_player_character *local_prev_character;
extern const obj_player_info *local_info;
extern const obj_flag *flags[2];
extern const obj_game *gameobj;
struct snapstate
{
const NETOBJ_PLAYER_CHARACTER *local_character;
const NETOBJ_PLAYER_CHARACTER *local_prev_character;
const NETOBJ_PLAYER_INFO *local_info;
const NETOBJ_FLAG *flags[2];
const NETOBJ_GAME *gameobj;
const NETOBJ_PLAYER_INFO *player_infos[MAX_CLIENTS];
const NETOBJ_PLAYER_INFO *info_by_score[MAX_CLIENTS];
int num_players;
};
extern snapstate netobjects;
/*
extern const NETOBJ_PLAYER_CHARACTER *local_character;
extern const NETOBJ_PLAYER_CHARACTER *local_prev_character;
extern const NETOBJ_PLAYER_INFO *local_info;
extern const NETOBJ_FLAG *flags[2];
extern const NETOBJ_GAME *gameobj;
* */
extern tuning_params tuning;
// predicted players
@ -33,7 +51,7 @@ extern player_core predicted_player;
// input
extern int picked_up_weapon;
extern player_input input_data;
extern NETOBJ_PLAYER_INPUT input_data;
extern int input_target_lock;
// debug
@ -45,7 +63,7 @@ enum
MAX_EXTRA_PROJECTILES=32,
};
extern obj_projectile extraproj_projectiles[MAX_EXTRA_PROJECTILES];
extern NETOBJ_PROJECTILE extraproj_projectiles[MAX_EXTRA_PROJECTILES];
extern int extraproj_num;
void extraproj_reset();

View file

@ -120,17 +120,17 @@ extern "C" void modc_predict()
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
int client_id = item.id;
if(item.type == OBJTYPE_PLAYER_CHARACTER)
if(item.type == NETOBJTYPE_PLAYER_CHARACTER)
{
const obj_player_character *character = (const obj_player_character *)data;
const NETOBJ_PLAYER_CHARACTER *character = (const NETOBJ_PLAYER_CHARACTER *)data;
client_datas[client_id].predicted.world = &world;
world.players[client_id] = &client_datas[client_id].predicted;
client_datas[client_id].predicted.read(character);
}
else if(item.type == OBJTYPE_PLAYER_INFO)
else if(item.type == NETOBJTYPE_PLAYER_INFO)
{
const obj_player_info *info = (const obj_player_info *)data;
const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
if(info->local)
local_cid = client_id;
}
@ -155,7 +155,7 @@ extern "C" void modc_predict()
// apply player input
int *input = client_get_input(tick);
if(input)
world.players[c]->input = *((player_input*)input);
world.players[c]->input = *((NETOBJ_PLAYER_INPUT*)input);
}
world.players[c]->tick();
@ -230,6 +230,23 @@ extern "C" void modc_newsnapshot()
static int snapshot_count = 0;
snapshot_count++;
// secure snapshot
{
int num = snap_num_items(SNAP_CURRENT);
for(int index = 0; index < num; index++)
{
SNAP_ITEM item;
void *data = snap_get_item(SNAP_CURRENT, index, &item);
if(netobj_secure(item.type, data, item.datasize) != 0)
{
if(config.debug)
dbg_msg("game", "invalidated %d %d (%s) %d", index, item.type, netobj_get_name(item.type), item.id);
snap_invalidate_item(SNAP_CURRENT, index);
}
}
}
process_events(SNAP_CURRENT);
if(config.dbg_stress)
@ -256,32 +273,32 @@ extern "C" void modc_newsnapshot()
SNAP_ITEM item;
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
if(item.type == OBJTYPE_PLAYER_INFO)
if(item.type == NETOBJTYPE_PLAYER_INFO)
{
const obj_player_info *info = (const obj_player_info *)data;
const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
client_datas[info->clientid].team = info->team;
client_datas[info->cid].team = info->team;
if(info->local)
{
local_info = info;
const void *data = snap_find_item(SNAP_CURRENT, OBJTYPE_PLAYER_CHARACTER, item.id);
netobjects.local_info = info;
const void *data = snap_find_item(SNAP_CURRENT, NETOBJTYPE_PLAYER_CHARACTER, item.id);
if(data)
{
local_character = (const obj_player_character *)data;
local_character_pos = vec2(local_character->x, local_character->y);
netobjects.local_character = (const NETOBJ_PLAYER_CHARACTER *)data;
local_character_pos = vec2(netobjects.local_character->x, netobjects.local_character->y);
const void *p = snap_find_item(SNAP_PREV, OBJTYPE_PLAYER_CHARACTER, item.id);
const void *p = snap_find_item(SNAP_PREV, NETOBJTYPE_PLAYER_CHARACTER, item.id);
if(p)
local_prev_character = (obj_player_character *)p;
netobjects.local_prev_character = (NETOBJ_PLAYER_CHARACTER *)p;
}
}
}
else if(item.type == OBJTYPE_GAME)
gameobj = (obj_game *)data;
else if(item.type == OBJTYPE_FLAG)
else if(item.type == NETOBJTYPE_GAME)
netobjects.gameobj = (NETOBJ_GAME *)data;
else if(item.type == NETOBJTYPE_FLAG)
{
flags[item.id%2] = (const obj_flag *)data;
netobjects.flags[item.id%2] = (const NETOBJ_FLAG *)data;
}
}
}
@ -394,7 +411,7 @@ extern "C" void modc_statechange(int state, int old)
}
}
obj_projectile extraproj_projectiles[MAX_EXTRA_PROJECTILES];
NETOBJ_PROJECTILE extraproj_projectiles[MAX_EXTRA_PROJECTILES];
int extraproj_num;
void extraproj_reset()
@ -409,6 +426,11 @@ extern "C" void modc_message(int msg)
int cid = msg_unpack_int();
int team = msg_unpack_int();
const char *message = msg_unpack_string();
/* check for errors and invalid inputs */
if(msg_unpack_error() || cid < 0 || cid >= MAX_CLIENTS)
return;
dbg_msg("message", "chat cid=%d team=%d msg='%s'", cid, team, message);
chat_add_line(cid, team, message);
@ -423,10 +445,13 @@ extern "C" void modc_message(int msg)
for(int k = 0; k < num; k++)
{
obj_projectile proj;
for(unsigned i = 0; i < sizeof(obj_projectile)/sizeof(int); i++)
NETOBJ_PROJECTILE proj;
for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
((int *)&proj)[i] = msg_unpack_int();
if(msg_unpack_error())
return;
if(extraproj_num != MAX_EXTRA_PROJECTILES)
{
extraproj_projectiles[extraproj_num] = proj;
@ -440,6 +465,10 @@ extern "C" void modc_message(int msg)
const char *name = msg_unpack_string();
const char *skinname = msg_unpack_string();
/* check for errors and invalid inputs */
if(msg_unpack_error() || cid < 0 || cid >= MAX_CLIENTS)
return;
strncpy(client_datas[cid].name, name, 64);
strncpy(client_datas[cid].skin_name, skinname, 64);
@ -466,13 +495,24 @@ extern "C" void modc_message(int msg)
}
else if(msg == MSG_TUNE_PARAMS)
{
int *params = (int *)&tuning;
// unpack the new tuning
tuning_params new_tuning;
int *params = (int *)&new_tuning;
for(unsigned i = 0; i < sizeof(tuning_params)/sizeof(int); i++)
params[i] = msg_unpack_int();
// check for unpacking errors
if(msg_unpack_error())
return;
// apply new tuning
tuning = new_tuning;
}
else if(msg == MSG_WEAPON_PICKUP)
{
int weapon = msg_unpack_int();
if(msg_unpack_error())
return;
picked_up_weapon = weapon+1;
}
else if(msg == MSG_READY_TO_ENTER)
@ -481,23 +521,41 @@ extern "C" void modc_message(int msg)
}
else if(msg == MSG_KILLMSG)
{
// unpack messages
killmsg msg;
msg.killer = msg_unpack_int();
msg.victim = msg_unpack_int();
msg.weapon = msg_unpack_int();
msg.mode_special = msg_unpack_int();
msg.tick = client_tick();
// check for unpacking errors
if(msg_unpack_error() || msg.killer >= MAX_CLIENTS || msg.victim >= MAX_CLIENTS || msg.weapon >= NUM_WEAPONS)
return;
// add the message
killmsg_current = (killmsg_current+1)%killmsg_max;
killmsgs[killmsg_current].killer = msg_unpack_int();
killmsgs[killmsg_current].victim = msg_unpack_int();
killmsgs[killmsg_current].weapon = msg_unpack_int();
killmsgs[killmsg_current].mode_special = msg_unpack_int();
killmsgs[killmsg_current].tick = client_tick();
killmsgs[killmsg_current] = msg;
}
else if (msg == MSG_EMOTICON)
{
// unpack
int cid = msg_unpack_int();
int emoticon = msg_unpack_int();
// check for errors
if(msg_unpack_error() || cid < 0 || cid >= MAX_CLIENTS)
return;
// apply
client_datas[cid].emoticon = emoticon;
client_datas[cid].emoticon_start = client_tick();
}
else if(msg == MSG_SOUND_GLOBAL)
{
int soundid = msg_unpack_int();
if(msg_unpack_error() || soundid < 0)
return;
snd_play_random(CHN_GLOBAL, soundid, 1.0f, vec2(0,0));
}
}

View file

@ -27,10 +27,6 @@ extern "C" {
extern data_container *data;
// abit uglyness
extern const obj_player_info *local_info;
extern const obj_game *gameobj;
extern bool menu_active;
extern bool menu_game_active;
@ -1614,9 +1610,9 @@ static void menu2_render_game(RECT main_view)
if(ui_do_button(&disconnect_button, "Disconnect", 0, &button, ui_draw_menu_button, 0))
client_disconnect();
if(local_info && gameobj)
if(netobjects.local_info && netobjects.gameobj)
{
if(local_info->team != -1)
if(netobjects.local_info->team != -1)
{
ui_vsplit_l(&main_view, 10.0f, &button, &main_view);
ui_vsplit_l(&main_view, 120.0f, &button, &main_view);
@ -1628,9 +1624,9 @@ static void menu2_render_game(RECT main_view)
}
}
if(gameobj->gametype == GAMETYPE_DM)
if(netobjects.gameobj->gametype == GAMETYPE_DM)
{
if(local_info->team != 0)
if(netobjects.local_info->team != 0)
{
ui_vsplit_l(&main_view, 10.0f, &button, &main_view);
ui_vsplit_l(&main_view, 120.0f, &button, &main_view);
@ -1644,7 +1640,7 @@ static void menu2_render_game(RECT main_view)
}
else
{
if(local_info->team != 0)
if(netobjects.local_info->team != 0)
{
ui_vsplit_l(&main_view, 10.0f, &button, &main_view);
ui_vsplit_l(&main_view, 120.0f, &button, &main_view);
@ -1656,7 +1652,7 @@ static void menu2_render_game(RECT main_view)
}
}
if(local_info->team != 1)
if(netobjects.local_info->team != 1)
{
ui_vsplit_l(&main_view, 10.0f, &button, &main_view);
ui_vsplit_l(&main_view, 120.0f, &button, &main_view);

View file

@ -349,25 +349,25 @@ static void render_items()
SNAP_ITEM item;
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
if(item.type == OBJTYPE_PROJECTILE)
if(item.type == NETOBJTYPE_PROJECTILE)
{
render_projectile((const obj_projectile *)data, item.id);
render_projectile((const NETOBJ_PROJECTILE *)data, item.id);
}
else if(item.type == OBJTYPE_POWERUP)
else if(item.type == NETOBJTYPE_POWERUP)
{
const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
if(prev)
render_powerup((const obj_powerup *)prev, (const obj_powerup *)data);
render_powerup((const NETOBJ_POWERUP *)prev, (const NETOBJ_POWERUP *)data);
}
else if(item.type == OBJTYPE_LASER)
else if(item.type == NETOBJTYPE_LASER)
{
render_laser((const obj_laser *)data);
render_laser((const NETOBJ_LASER *)data);
}
else if(item.type == OBJTYPE_FLAG)
else if(item.type == NETOBJTYPE_FLAG)
{
const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
if (prev)
render_flag((const obj_flag *)prev, (const obj_flag *)data);
render_flag((const NETOBJ_FLAG *)prev, (const NETOBJ_FLAG *)data);
}
}
@ -393,19 +393,19 @@ static void render_players()
SNAP_ITEM item;
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
if(item.type == OBJTYPE_PLAYER_CHARACTER)
if(item.type == NETOBJTYPE_PLAYER_CHARACTER)
{
const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
const void *prev_info = snap_find_item(SNAP_PREV, OBJTYPE_PLAYER_INFO, item.id);
const void *info = snap_find_item(SNAP_CURRENT, OBJTYPE_PLAYER_INFO, item.id);
const void *prev_info = snap_find_item(SNAP_PREV, NETOBJTYPE_PLAYER_INFO, item.id);
const void *info = snap_find_item(SNAP_CURRENT, NETOBJTYPE_PLAYER_INFO, item.id);
if(prev && prev_info && info)
{
render_player(
(const obj_player_character *)prev,
(const obj_player_character *)data,
(const obj_player_info *)prev_info,
(const obj_player_info *)info
(const NETOBJ_PLAYER_CHARACTER *)prev,
(const NETOBJ_PLAYER_CHARACTER *)data,
(const NETOBJ_PLAYER_INFO *)prev_info,
(const NETOBJ_PLAYER_INFO *)info
);
}
}

View file

@ -54,13 +54,13 @@ void render_particles();
// object render methods (gc_render_obj.cpp)
void render_tee(class animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos);
void render_flag(const struct obj_flag *prev, const struct obj_flag *current);
void render_powerup(const struct obj_powerup *prev, const struct obj_powerup *current);
void render_projectile(const struct obj_projectile *current, int itemid);
void render_laser(const struct obj_laser *current);
void render_flag(const struct NETOBJ_FLAG *prev, const struct NETOBJ_FLAG *current);
void render_powerup(const struct NETOBJ_POWERUP *prev, const struct NETOBJ_POWERUP *current);
void render_projectile(const struct NETOBJ_PROJECTILE *current, int itemid);
void render_laser(const struct NETOBJ_LASER *current);
void render_player(
const struct obj_player_character *prev_char, const struct obj_player_character *player_char,
const struct obj_player_info *prev_info, const struct obj_player_info *player_info);
const struct NETOBJ_PLAYER_CHARACTER *prev_char, const struct NETOBJ_PLAYER_CHARACTER *player_char,
const struct NETOBJ_PLAYER_INFO *prev_info, const struct NETOBJ_PLAYER_INFO *player_info);
// map render methods (gc_render_map.cpp)
void render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result);

View file

@ -11,7 +11,7 @@
#include "gc_client.h"
void render_projectile(const obj_projectile *current, int itemid)
void render_projectile(const NETOBJ_PROJECTILE *current, int itemid)
{
if(debug_firedelay)
{
@ -34,7 +34,7 @@ void render_projectile(const obj_projectile *current, int itemid)
vec2 pos = calc_pos(startpos, startvel, gravity, ct);
vec2 prevpos = calc_pos(startpos, startvel, gravity, ct-0.001f);
select_sprite(data->weapons[current->type%data->num_weapons].sprite_proj);
select_sprite(data->weapons[clamp(current->type, 0, NUM_WEAPONS-1)].sprite_proj);
vec2 vel = pos-prevpos;
//vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
@ -63,7 +63,7 @@ void render_projectile(const obj_projectile *current, int itemid)
gfx_quads_end();
}
void render_powerup(const obj_powerup *prev, const obj_powerup *current)
void render_powerup(const NETOBJ_POWERUP *prev, const NETOBJ_POWERUP *current)
{
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
@ -73,8 +73,8 @@ void render_powerup(const obj_powerup *prev, const obj_powerup *current)
if (current->type == POWERUP_WEAPON)
{
angle = 0; //-pi/6;//-0.25f * pi * 2.0f;
select_sprite(data->weapons[current->subtype%data->num_weapons].sprite_body);
size = data->weapons[current->subtype%data->num_weapons].visual_size;
select_sprite(data->weapons[clamp(current->subtype, 0, NUM_WEAPONS-1)].sprite_body);
size = data->weapons[clamp(current->subtype, 0, NUM_WEAPONS-1)].visual_size;
}
else
{
@ -107,7 +107,7 @@ void render_powerup(const obj_powerup *prev, const obj_powerup *current)
gfx_quads_end();
}
void render_flag(const obj_flag *prev, const obj_flag *current)
void render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current)
{
float angle = 0.0f;
float size = 42.0f;
@ -125,7 +125,7 @@ void render_flag(const obj_flag *prev, const obj_flag *current)
vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
if(local_info && current->carried_by == local_info->clientid)
if(netobjects.local_info && current->carried_by == netobjects.local_info->cid)
pos = local_character_pos;
//gfx_setcolor(current->team ? 0 : 1,0,current->team ? 1 : 0,1);
@ -135,7 +135,7 @@ void render_flag(const obj_flag *prev, const obj_flag *current)
}
void render_laser(const struct obj_laser *current)
void render_laser(const struct NETOBJ_LASER *current)
{
vec2 pos = vec2(current->x, current->y);
@ -245,19 +245,19 @@ static void render_hand(tee_render_info *info, vec2 center_pos, vec2 dir, float
}
void render_player(
const obj_player_character *prev_char,
const obj_player_character *player_char,
const obj_player_info *prev_info,
const obj_player_info *player_info
const NETOBJ_PLAYER_CHARACTER *prev_char,
const NETOBJ_PLAYER_CHARACTER *player_char,
const NETOBJ_PLAYER_INFO *prev_info,
const NETOBJ_PLAYER_INFO *player_info
)
{
obj_player_character prev;
obj_player_character player;
NETOBJ_PLAYER_CHARACTER prev;
NETOBJ_PLAYER_CHARACTER player;
prev = *prev_char;
player = *player_char;
obj_player_info info = *player_info;
tee_render_info render_info = client_datas[info.clientid].render_info;
NETOBJ_PLAYER_INFO info = *player_info;
tee_render_info render_info = client_datas[info.cid].render_info;
float intratick = client_intratick();
float ticktime = client_ticktime();
@ -267,7 +267,7 @@ void render_player(
if(info.local && config.cl_predict)
{
if(!local_character || (local_character->health < 0) || (gameobj && gameobj->game_over))
if(!netobjects.local_character || (netobjects.local_character->health < 0) || (netobjects.gameobj && netobjects.gameobj->game_over))
{
}
else
@ -329,7 +329,7 @@ void render_player(
if(player_char->hooked_player != -1)
{
if(local_info && player_char->hooked_player == local_info->clientid)
if(netobjects.local_info && player_char->hooked_player == netobjects.local_info->cid)
{
hook_pos = mix(vec2(predicted_prev_player.pos.x, predicted_prev_player.pos.y),
vec2(predicted_player.pos.x, predicted_player.pos.y), client_predintratick());
@ -351,7 +351,8 @@ void render_player(
// render chain
select_sprite(SPRITE_HOOK_CHAIN);
for(float f = 24; f < d; f += 24)
int i = 0;
for(float f = 24; f < d && i < 1024; f += 24, i++)
{
vec2 p = hook_pos + dir*f;
gfx_quads_draw(p.x, p.y,24,16);
@ -360,7 +361,7 @@ void render_player(
gfx_quads_setrotation(0);
gfx_quads_end();
render_hand(&client_datas[info.clientid].render_info, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0));
render_hand(&client_datas[info.cid].render_info, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0));
}
// draw gun
@ -478,9 +479,9 @@ void render_player(
switch (player.weapon)
{
case WEAPON_GUN: render_hand(&client_datas[info.clientid].render_info, p, direction, -3*pi/4, vec2(-15, 4)); break;
case WEAPON_SHOTGUN: render_hand(&client_datas[info.clientid].render_info, p, direction, -pi/2, vec2(-5, 4)); break;
case WEAPON_GRENADE: render_hand(&client_datas[info.clientid].render_info, p, direction, -pi/2, vec2(-4, 7)); break;
case WEAPON_GUN: render_hand(&client_datas[info.cid].render_info, p, direction, -3*pi/4, vec2(-15, 4)); break;
case WEAPON_SHOTGUN: render_hand(&client_datas[info.cid].render_info, p, direction, -pi/2, vec2(-5, 4)); break;
case WEAPON_GRENADE: render_hand(&client_datas[info.cid].render_info, p, direction, -pi/2, vec2(-4, 7)); break;
}
}
@ -507,13 +508,13 @@ void render_player(
gfx_quads_end();
}
if (client_datas[info.clientid].emoticon_start != -1 && client_datas[info.clientid].emoticon_start + 2 * client_tickspeed() > client_tick())
if (client_datas[info.cid].emoticon_start != -1 && client_datas[info.cid].emoticon_start + 2 * client_tickspeed() > client_tick())
{
gfx_texture_set(data->images[IMAGE_EMOTICONS].id);
gfx_quads_begin();
int since_start = client_tick() - client_datas[info.clientid].emoticon_start;
int from_end = client_datas[info.clientid].emoticon_start + 2 * client_tickspeed() - client_tick();
int since_start = client_tick() - client_datas[info.cid].emoticon_start;
int from_end = client_datas[info.cid].emoticon_start + 2 * client_tickspeed() - client_tick();
float a = 1;
@ -534,7 +535,7 @@ void render_player(
gfx_setcolor(1.0f,1.0f,1.0f,a);
// client_datas::emoticon is an offset from the first emoticon
select_sprite(SPRITE_OOP + client_datas[info.clientid].emoticon);
select_sprite(SPRITE_OOP + client_datas[info.cid].emoticon);
gfx_quads_draw(position.x, position.y - 23 - 32*h, 64, 64*h);
gfx_quads_end();
}
@ -547,7 +548,7 @@ void render_player(
if(config.cl_nameplates_always == 0)
a = clamp(1-powf(distance(local_target_pos, position)/200.0f,16.0f), 0.0f, 1.0f);
const char *name = client_datas[info.clientid].name;
const char *name = client_datas[info.cid].name;
float tw = gfx_text_width(0, 28.0f, name, -1);
gfx_text_color(1,1,1,a);
gfx_text(0, position.x-tw/2.0f, position.y-60, 28.0f, name, -1);

View file

@ -400,7 +400,7 @@ void player_core::move()
move_box(&pos, &vel, vec2(28.0f, 28.0f), 0);
}
void player_core::write(obj_player_core *obj_core)
void player_core::write(NETOBJ_PLAYER_CORE *obj_core)
{
obj_core->x = (int)pos.x;
obj_core->y = (int)pos.y;
@ -427,7 +427,7 @@ void player_core::write(obj_player_core *obj_core)
obj_core->angle = (int)(a*256.0f);
}
void player_core::read(const obj_player_core *obj_core)
void player_core::read(const NETOBJ_PLAYER_CORE *obj_core)
{
pos.x = obj_core->x;
pos.y = obj_core->y;
@ -445,7 +445,7 @@ void player_core::read(const obj_player_core *obj_core)
void player_core::quantize()
{
obj_player_core c;
NETOBJ_PLAYER_CORE c;
write(&c);
read(&c);
}

View file

@ -133,15 +133,15 @@ public:
int hooked_player;
int jumped;
player_input input;
NETOBJ_PLAYER_INPUT input;
int triggered_events;
void tick();
void move();
void read(const obj_player_core *obj_core);
void write(obj_player_core *obj_core);
void read(const NETOBJ_PLAYER_CORE *obj_core);
void write(NETOBJ_PLAYER_CORE *obj_core);
void quantize();
};

View file

@ -33,12 +33,10 @@ void layers_init()
if(tilemap->flags&1)
{
dbg_msg("layers", "game");
game_layer = tilemap;
p = 2;
}
}
dbg_msg("layers", "%d %d", i, layer->type);
}
}
}

211
src/game/g_protocol.def Normal file
View file

@ -0,0 +1,211 @@
raw_source
#include "g_protocol.h"
#include "g_protocol_ids.h"
#include <engine/e_common_interface.h>
#define max_int 100000
end
raw_header
enum
{
// emotes
EMOTE_NORMAL=0,
EMOTE_PAIN,
EMOTE_HAPPY,
EMOTE_SURPRISE,
EMOTE_ANGRY,
EMOTE_BLINK,
NUM_EMOTES,
// playerstates
PLAYERSTATE_UNKNOWN=0,
PLAYERSTATE_PLAYING,
PLAYERSTATE_IN_MENU,
PLAYERSTATE_CHATTING,
NUM_PLAYERSTATES,
// game types
GAMETYPE_DM=0,
GAMETYPE_TDM,
GAMETYPE_CTF,
NUM_GAMETYPES,
// other stuff
INPUT_STATE_MASK=0x1f,
};
enum
{
MSG_NULL=0,
MSG_SAY, // client -> server
MSG_CHAT, // server -> client
MSG_SETINFO, // server -> client - contains name, skin and color info
MSG_KILLMSG, // server -> client
MSG_SETTEAM,
MSG_JOIN,
MSG_QUIT,
MSG_EMOTICON,
MSG_STARTINFO, // client -> server
MSG_CHANGEINFO, // client -> server
MSG_READY_TO_ENTER, // server -> client
MSG_WEAPON_PICKUP,
MSG_SOUND_GLOBAL,
MSG_TUNE_PARAMS,
MSG_KILL,
MSG_EXTRA_PROJECTILE, // server -> client
};
end
object player_input
any left
any right
any target_x
any target_y
any jump
any fire
any hook
any blink
any player_state
any wanted_weapon
any next_weapon
any prev_weapon
end
object projectile
any x, y
any vx, vy
range(0, NUM_WEAPONS) type
range(0, max_int) start_tick
end
object laser
any x
any y
any from_x
any from_y
range(0, max_int) eval_tick
end
object powerup
any x, y
range(0, max_int) type
range(0, max_int) subtype
end
object flag
any x, y
range(0, 1) team
clientid carried_by
end
object game
range(0, max_int) round_start_tick
range(0, 1) game_over
range(0, 1) sudden_death
range(0, 1) paused
range(0, max_int) score_limit
range(0, max_int) time_limit
range(0, NUM_GAMETYPES-1) gametype
range(0, max_int) warmup
any teamscore_red
any teamscore_blue
end
// core object needed for physics
object player_core
any x, y
any vx, vy
any angle
range(0, 2) jumped
clientid hooked_player
range(0, 3) hook_state
range(0, max_int) hook_tick
any hook_x
any hook_y
any hook_dx
any hook_dy
end
// info about the player that is only needed when it's on screen
object player_character extends player_core
range(0, NUM_PLAYERSTATES-1) player_state
range(0, 10) health
range(0, 10) armor
range(0, 10) ammocount
range(0, 10) weaponstage
range(0, NUM_WEAPONS-1) weapon
range(0, NUM_EMOTES-1) emote
range(0, max_int) attacktick
end
// information about the player that is always needed
object player_info
range(0, 1) local
clientid cid
range(-1, 1) team
any score
any latency
any latency_flux
end
event common
any x, y
end
event explosion
any x, y
end
event spawn
any x, y
end
event death
any x, y
end
event air_jump
any x, y
end
event sound_global
any x, y
range(0, NUM_SOUNDS-1) soundid
end
event sound_world
any x, y
range(0, NUM_SOUNDS-1) soundid
end
event damageind
any x, y
any angle
end
//msg say
// clientid cid
// range(-1, 1) team
// string message
//end

View file

@ -4,7 +4,10 @@
#ifndef GAME_PROTOCOL_H
#define GAME_PROTOCOL_H
#include <game/generated/g_protocol.h>
// Network stuff
/*
enum
{
OBJTYPE_NULL=0,
@ -209,6 +212,6 @@ struct obj_player_info
int score;
int latency;
int latency_flux;
};
};*/
#endif

View file

@ -204,7 +204,7 @@ public:
projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner,
int damage, int flags, float force, int sound_impact, int weapon);
void fill_info(obj_projectile *proj);
void fill_info(NETOBJ_PROJECTILE *proj);
virtual void reset();
virtual void tick();
@ -270,12 +270,12 @@ public:
int color_feet;
// these are non-heldback inputs
player_input latest_previnput;
player_input latest_input;
NETOBJ_PLAYER_INPUT latest_previnput;
NETOBJ_PLAYER_INPUT latest_input;
// input
player_input previnput;
player_input input;
NETOBJ_PLAYER_INPUT previnput;
NETOBJ_PLAYER_INPUT input;
int num_inputs;
int jumped;
@ -332,7 +332,7 @@ public:
int handle_weapons();
int handle_ninja();
void on_direct_input(player_input *input);
void on_direct_input(NETOBJ_PLAYER_INPUT *input);
void fire_weapon();
virtual void tick();

View file

@ -6,7 +6,7 @@
#include "gs_common.h"
gameobject::gameobject()
: entity(OBJTYPE_GAME)
: entity(NETOBJTYPE_GAME)
{
// select gametype
if(strcmp(config.sv_gametype, "ctf") == 0)
@ -260,7 +260,7 @@ void gameobject::tick()
void gameobject::snap(int snapping_client)
{
obj_game *game = (obj_game *)snap_new_item(OBJTYPE_GAME, 0, sizeof(obj_game));
NETOBJ_GAME *game = (NETOBJ_GAME *)snap_new_item(NETOBJTYPE_GAME, 0, sizeof(NETOBJ_GAME));
game->paused = world->paused;
game->game_over = game_over_tick==-1?0:1;
game->sudden_death = sudden_death;
@ -272,8 +272,8 @@ void gameobject::snap(int snapping_client)
game->warmup = warmup;
game->teamscore[0] = teamscore[0];
game->teamscore[1] = teamscore[1];
game->teamscore_red = teamscore[0];
game->teamscore_blue = teamscore[1];
}
int gameobject::getteam(int notthisid)

View file

@ -99,7 +99,7 @@ void gameobject_ctf::tick()
else
{
player *close_players[MAX_CLIENTS];
int types[] = {OBJTYPE_PLAYER_CHARACTER};
int types[] = {NETOBJTYPE_PLAYER_CHARACTER};
int num = world->find_entities(f->pos, 32.0f, (entity**)close_players, MAX_CLIENTS, types, 1);
for(int i = 0; i < num; i++)
{
@ -161,7 +161,7 @@ void gameobject_ctf::tick()
// Flag
flag::flag(int _team)
: entity(OBJTYPE_FLAG)
: entity(NETOBJTYPE_FLAG)
{
team = _team;
proximity_radius = phys_size;
@ -183,7 +183,7 @@ void flag::reset()
void flag::snap(int snapping_client)
{
obj_flag *flag = (obj_flag *)snap_new_item(OBJTYPE_FLAG, team, sizeof(obj_flag));
NETOBJ_FLAG *flag = (NETOBJ_FLAG *)snap_new_item(NETOBJTYPE_FLAG, team, sizeof(NETOBJ_FLAG));
flag->x = (int)pos.x;
flag->y = (int)pos.y;
flag->team = team;

View file

@ -107,7 +107,7 @@ void event_handler::snap(int snapping_client)
{
if(cmask_is_set(client_masks[i], snapping_client))
{
ev_common *ev = (ev_common *)&data[offsets[i]];
NETEVENT_COMMON *ev = (NETEVENT_COMMON *)&data[offsets[i]];
if(distance(players[snapping_client].pos, vec2(ev->x, ev->y)) < 1500.0f)
{
void *d = snap_new_item(types[i], i, sizes[i]);
@ -297,6 +297,7 @@ void game_world::tick()
if(!paused)
{
/*
static PERFORMACE_INFO scopes[OBJTYPE_FLAG+1] =
{
{"null", 0},
@ -320,31 +321,32 @@ void game_world::tick()
};
static PERFORMACE_INFO tick_scope = {"tick", 0};
perf_start(&tick_scope);
perf_start(&tick_scope);*/
// update all objects
for(entity *ent = first_entity; ent; ent = ent->next_entity)
{
if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_start(&scopes[ent->objtype]);
/*if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_start(&scopes[ent->objtype]);*/
ent->tick();
if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_end();
/*if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_end();*/
}
/*
perf_end();
static PERFORMACE_INFO deftick_scope = {"tick_defered", 0};
perf_start(&deftick_scope);
perf_start(&deftick_scope);*/
for(entity *ent = first_entity; ent; ent = ent->next_entity)
{
if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_start(&scopes_def[ent->objtype]);
/*if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_start(&scopes_def[ent->objtype]);*/
ent->tick_defered();
if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_end();
/*if(ent->objtype >= 0 && ent->objtype < OBJTYPE_FLAG)
perf_end();*/
}
perf_end();
/*perf_end();*/
}
remove_entities();
@ -380,7 +382,7 @@ static input_count count_input(int prev, int cur)
//////////////////////////////////////////////////
projectile::projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner,
int damage, int flags, float force, int sound_impact, int weapon)
: entity(OBJTYPE_PROJECTILE)
: entity(NETOBJTYPE_PROJECTILE)
{
this->type = type;
this->pos = pos;
@ -437,7 +439,7 @@ void projectile::tick()
}
}
void projectile::fill_info(obj_projectile *proj)
void projectile::fill_info(NETOBJ_PROJECTILE *proj)
{
proj->x = (int)pos.x;
proj->y = (int)pos.y;
@ -455,7 +457,7 @@ void projectile::snap(int snapping_client)
if(distance(players[snapping_client].pos, curpos) > 1000.0f)
return;
obj_projectile *proj = (obj_projectile *)snap_new_item(OBJTYPE_PROJECTILE, id, sizeof(obj_projectile));
NETOBJ_PROJECTILE *proj = (NETOBJ_PROJECTILE *)snap_new_item(NETOBJTYPE_PROJECTILE, id, sizeof(NETOBJ_PROJECTILE));
fill_info(proj);
}
@ -464,7 +466,7 @@ void projectile::snap(int snapping_client)
// laser
//////////////////////////////////////////////////
laser::laser(vec2 pos, vec2 direction, float start_energy, player *owner)
: entity(OBJTYPE_LASER)
: entity(NETOBJTYPE_LASER)
{
this->pos = pos;
this->owner = owner;
@ -554,7 +556,7 @@ void laser::snap(int snapping_client)
if(distance(players[snapping_client].pos, pos) > 1000.0f)
return;
obj_laser *obj = (obj_laser *)snap_new_item(OBJTYPE_LASER, id, sizeof(obj_laser));
NETOBJ_LASER *obj = (NETOBJ_LASER *)snap_new_item(NETOBJTYPE_LASER, id, sizeof(NETOBJ_LASER));
obj->x = (int)pos.x;
obj->y = (int)pos.y;
obj->from_x = (int)from.x;
@ -568,7 +570,7 @@ void laser::snap(int snapping_client)
//////////////////////////////////////////////////
// TODO: move to separate file
player::player()
: entity(OBJTYPE_PLAYER_CHARACTER)
: entity(NETOBJTYPE_PLAYER_CHARACTER)
{
init();
}
@ -788,7 +790,7 @@ void player::try_respawn()
// check if the position is occupado
entity *ents[2] = {0};
int types[] = {OBJTYPE_PLAYER_CHARACTER};
int types[] = {NETOBJTYPE_PLAYER_CHARACTER};
int num_ents = world->find_entities(spawnpos, 64, ents, 2, types, 1);
for(int i = 0; i < num_ents; i++)
{
@ -901,12 +903,12 @@ int player::handle_ninja()
core.vel = vec2(0.0f,0.0f);
if ((ninja.currentmovetime % 2) == 0)
{
create_smoke(pos);
//create_smoke(pos);
}
// check if we hit anything along the way
{
int type = OBJTYPE_PLAYER_CHARACTER;
int type = NETOBJTYPE_PLAYER_CHARACTER;
entity *ents[64];
vec2 dir = pos - oldpos;
float radius = phys_size * 2.0f; //length(dir * 0.5f);
@ -990,12 +992,12 @@ void player::fire_weapon()
1, 0, 0, -1, WEAPON_GUN);
// pack the projectile and send it to the client directly
obj_projectile p;
NETOBJ_PROJECTILE p;
proj->fill_info(&p);
msg_pack_start(MSG_EXTRA_PROJECTILE, 0);
msg_pack_int(1);
for(unsigned i = 0; i < sizeof(obj_projectile)/sizeof(int); i++)
for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
msg_pack_int(((int *)&p)[i]);
msg_pack_end();
server_send_msg(client_id);
@ -1014,12 +1016,12 @@ void player::fire_weapon()
1, projectile::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
// pack the projectile and send it to the client directly
obj_projectile p;
NETOBJ_PROJECTILE p;
proj->fill_info(&p);
msg_pack_start(MSG_EXTRA_PROJECTILE, 0);
msg_pack_int(1);
for(unsigned i = 0; i < sizeof(obj_projectile)/sizeof(int); i++)
for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
msg_pack_int(((int *)&p)[i]);
msg_pack_end();
server_send_msg(client_id);
@ -1050,10 +1052,10 @@ void player::fire_weapon()
1, 0, 0, -1, WEAPON_SHOTGUN);
// pack the projectile and send it to the client directly
obj_projectile p;
NETOBJ_PROJECTILE p;
proj->fill_info(&p);
for(unsigned i = 0; i < sizeof(obj_projectile)/sizeof(int); i++)
for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
msg_pack_int(((int *)&p)[i]);
}
@ -1245,7 +1247,7 @@ int player::handle_weapons()
// only one that needs update (for now)
// do selection for the weapon and bash anything in it
// check if we hit anything along the way
int type = OBJTYPE_PLAYER_CHARACTER;
int type = NETOBJTYPE_PLAYER_CHARACTER;
entity *ents[64];
vec2 lookdir(direction.x > 0.0f ? 1.0f : -1.0f, 0.0f);
vec2 dir = lookdir * data->weapons[active_weapon].meleereach;
@ -1278,7 +1280,7 @@ int player::handle_weapons()
vec2 fdir = normalize(ents[i]->pos- pos);
// set his velocity to fast upward (for now)
create_smoke(ents[i]->pos);
//create_smoke(ents[i]->pos);
create_sound(pos, SOUND_HAMMER_HIT);
if(numobjectshit < 10)
hitobjects[numobjectshit++] = ents[i];
@ -1318,7 +1320,7 @@ int player::handle_weapons()
return 0;
}
void player::on_direct_input(player_input *new_input)
void player::on_direct_input(NETOBJ_PLAYER_INPUT *new_input)
{
mem_copy(&latest_previnput, &latest_input, sizeof(latest_input));
mem_copy(&latest_input, new_input, sizeof(latest_input));
@ -1444,7 +1446,7 @@ void player::tick_defered()
if(events&COREEVENT_AIR_JUMP)
{
create_sound(pos, SOUND_PLAYER_AIRJUMP, mask);
ev_common *c = (ev_common *)::events.create(EVENT_AIR_JUMP, sizeof(ev_common), mask);
NETEVENT_COMMON *c = (NETEVENT_COMMON *)::events.create(NETEVENTTYPE_AIR_JUMP, sizeof(NETEVENT_COMMON), mask);
if(c)
{
c->x = (int)pos.x;
@ -1580,12 +1582,12 @@ void player::snap(int snaping_client)
{
if(1)
{
obj_player_info *info = (obj_player_info *)snap_new_item(OBJTYPE_PLAYER_INFO, client_id, sizeof(obj_player_info));
NETOBJ_PLAYER_INFO *info = (NETOBJ_PLAYER_INFO *)snap_new_item(NETOBJTYPE_PLAYER_INFO, client_id, sizeof(NETOBJ_PLAYER_INFO));
info->latency = latency_min;
info->latency_flux = latency_max-latency_min;
info->local = 0;
info->clientid = client_id;
info->cid = client_id;
info->score = score;
info->team = team;
@ -1595,7 +1597,7 @@ void player::snap(int snaping_client)
if(health > 0 && team >= 0 && distance(players[snaping_client].pos, pos) < 1000.0f)
{
obj_player_character *character = (obj_player_character *)snap_new_item(OBJTYPE_PLAYER_CHARACTER, client_id, sizeof(obj_player_character));
NETOBJ_PLAYER_CHARACTER *character = (NETOBJ_PLAYER_CHARACTER *)snap_new_item(NETOBJTYPE_PLAYER_CHARACTER, client_id, sizeof(NETOBJ_PLAYER_CHARACTER));
core.write(character);
@ -1651,7 +1653,7 @@ player *players;
// powerup
//////////////////////////////////////////////////
powerup::powerup(int _type, int _subtype)
: entity(OBJTYPE_POWERUP)
: entity(NETOBJTYPE_POWERUP)
{
type = _type;
subtype = _subtype;
@ -1747,7 +1749,7 @@ void powerup::tick()
// loop through all players, setting their emotes
entity *ents[64];
const int types[] = {OBJTYPE_PLAYER_CHARACTER};
const int types[] = {NETOBJTYPE_PLAYER_CHARACTER};
int num = world->find_entities(vec2(0, 0), 1000000, ents, 64, types, 1);
for (int i = 0; i < num; i++)
{
@ -1782,7 +1784,7 @@ void powerup::snap(int snapping_client)
if(spawntick != -1)
return;
obj_powerup *up = (obj_powerup *)snap_new_item(OBJTYPE_POWERUP, id, sizeof(obj_powerup));
NETOBJ_POWERUP *up = (NETOBJ_POWERUP *)snap_new_item(NETOBJTYPE_POWERUP, id, sizeof(NETOBJ_POWERUP));
up->x = (int)pos.x;
up->y = (int)pos.y;
up->type = type; // TODO: two diffrent types? what gives?
@ -1805,7 +1807,7 @@ void create_damageind(vec2 p, float angle, int amount)
for(int i = 0; i < amount; i++)
{
float f = mix(s, e, float(i+1)/float(amount+2));
ev_damageind *ev = (ev_damageind *)events.create(EVENT_DAMAGEINDICATION, sizeof(ev_damageind));
NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)events.create(NETEVENTTYPE_DAMAGEIND, sizeof(NETEVENT_DAMAGEIND));
if(ev)
{
ev->x = (int)p.x;
@ -1818,7 +1820,7 @@ void create_damageind(vec2 p, float angle, int amount)
void create_explosion(vec2 p, int owner, int weapon, bool bnodamage)
{
// create the event
ev_explosion *ev = (ev_explosion *)events.create(EVENT_EXPLOSION, sizeof(ev_explosion));
NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)events.create(NETEVENTTYPE_EXPLOSION, sizeof(NETEVENT_EXPLOSION));
if(ev)
{
ev->x = (int)p.x;
@ -1848,21 +1850,22 @@ void create_explosion(vec2 p, int owner, int weapon, bool bnodamage)
}
}
/*
void create_smoke(vec2 p)
{
// create the event
ev_explosion *ev = (ev_explosion *)events.create(EVENT_SMOKE, sizeof(ev_explosion));
EV_EXPLOSION *ev = (EV_EXPLOSION *)events.create(EVENT_SMOKE, sizeof(EV_EXPLOSION));
if(ev)
{
ev->x = (int)p.x;
ev->y = (int)p.y;
}
}
}*/
void create_playerspawn(vec2 p)
{
// create the event
ev_spawn *ev = (ev_spawn *)events.create(EVENT_PLAYERSPAWN, sizeof(ev_spawn));
NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)events.create(NETEVENTTYPE_SPAWN, sizeof(NETEVENT_SPAWN));
if(ev)
{
ev->x = (int)p.x;
@ -1873,7 +1876,7 @@ void create_playerspawn(vec2 p)
void create_death(vec2 p)
{
// create the event
ev_death *ev = (ev_death *)events.create(EVENT_DEATH, sizeof(ev_death));
NETEVENT_DEATH *ev = (NETEVENT_DEATH *)events.create(NETEVENTTYPE_DEATH, sizeof(NETEVENT_DEATH));
if(ev)
{
ev->x = (int)p.x;
@ -1887,12 +1890,12 @@ void create_sound(vec2 pos, int sound, int mask)
return;
// create a sound
ev_sound *ev = (ev_sound *)events.create(EVENT_SOUND_WORLD, sizeof(ev_sound), mask);
NETEVENT_SOUND_WORLD *ev = (NETEVENT_SOUND_WORLD *)events.create(NETEVENTTYPE_SOUND_WORLD, sizeof(NETEVENT_SOUND_WORLD), mask);
if(ev)
{
ev->x = (int)pos.x;
ev->y = (int)pos.y;
ev->sound = sound;
ev->soundid = sound;
}
}
@ -2043,7 +2046,7 @@ void mods_snap(int client_id)
void mods_client_direct_input(int client_id, void *input)
{
if(!world->paused)
players[client_id].on_direct_input((player_input *)input);
players[client_id].on_direct_input((NETOBJ_PLAYER_INPUT *)input);
/*
if(i->fire)
@ -2058,11 +2061,11 @@ void mods_client_predicted_input(int client_id, void *input)
{
if(!world->paused)
{
if (memcmp(&players[client_id].input, input, sizeof(player_input)) != 0)
if (memcmp(&players[client_id].input, input, sizeof(NETOBJ_PLAYER_INPUT)) != 0)
players[client_id].last_action = server_tick();
//players[client_id].previnput = players[client_id].input;
players[client_id].input = *(player_input*)input;
players[client_id].input = *(NETOBJ_PLAYER_INPUT*)input;
players[client_id].num_inputs++;
if(players[client_id].input.target_x == 0 && players[client_id].input.target_y == 0)

36
src/tools/packetgen.c Normal file
View file

@ -0,0 +1,36 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <engine/e_system.h>
enum { NUM_SOCKETS = 64 };
int run(NETADDR4 dest)
{
NETSOCKET sockets[NUM_SOCKETS];
int i;
for(i = 0; i < NUM_SOCKETS; i++)
{
NETADDR4 bindaddr = {{0,0,0,0}, 0};
sockets[i] = net_udp4_create(bindaddr);
}
while(1)
{
unsigned char data[1024];
int size = 0;
int socket_to_use = 0;
io_read(io_stdin(), &size, 2);
io_read(io_stdin(), &socket_to_use, 1);
size %= 256;
socket_to_use %= NUM_SOCKETS;
io_read(io_stdin(), data, size);
net_udp4_send(sockets[socket_to_use], &dest, data, size);
}
}
int main(int argc, char **argv)
{
NETADDR4 dest = {{127,0,0,1},8303};
run(dest);
return 0;
}