Index: src/Cube.mm ================================================================== --- src/Cube.mm +++ src/Cube.mm @@ -88,12 +88,11 @@ if (enet_initialize() < 0) fatal(@"Unable to initialise network module"); initclient(); // never returns if dedicated - initserver(dedicated, uprate, sdesc.UTF8String, ip.UTF8String, - master.UTF8String, passwd, maxcl); + initserver(dedicated, uprate, sdesc, ip, master, passwd, maxcl); log(@"world"); empty_world(7, true); log(@"video: sdl"); Index: src/client.mm ================================================================== --- src/client.mm +++ src/client.mm @@ -291,11 +291,11 @@ if (toservermap.length > 0) // suggest server to change map { // do this exclusively as map change may invalidate rest of // update packet->flags = ENET_PACKET_FLAG_RELIABLE; putint(p, SV_MAPCHANGE); - sendstring(toservermap.UTF8String, p); + sendstring(toservermap, p); toservermap = @""; putint(p, nextmode); } else { putint(p, SV_POS); putint(p, clientnum); @@ -332,20 +332,20 @@ if (ctext[0]) // player chat, not flood protected for // now { packet->flags = ENET_PACKET_FLAG_RELIABLE; putint(p, SV_TEXT); - sendstring(ctext, p); + sendstring(@(ctext), p); ctext[0] = 0; } if (!c2sinit) // tell other clients who I am { packet->flags = ENET_PACKET_FLAG_RELIABLE; c2sinit = true; putint(p, SV_INITC2S); - sendstring(player1->name, p); - sendstring(player1->team, p); + sendstring(@(player1->name), p); + sendstring(@(player1->team), p); putint(p, player1->lifesequence); } for (OFData *msg in messages) { // send messages collected during the previous // frames Index: src/clientextras.mm ================================================================== --- src/clientextras.mm +++ src/clientextras.mm @@ -189,11 +189,11 @@ ENetPacket *packet = enet_packet_create( NULL, MAXTRANS + mapdata.count, ENET_PACKET_FLAG_RELIABLE); uchar *start = packet->data; uchar *p = start + 2; putint(p, SV_SENDMAP); - sendstring(mapname.UTF8String, p); + sendstring(mapname, p); putint(p, mapdata.count); if (65535 - (p - start) < mapdata.count) { conoutf(@"map %@ is too large to send", mapname); enet_packet_destroy(packet); return; Index: src/clientgame.mm ================================================================== --- src/clientgame.mm +++ src/clientgame.mm @@ -508,9 +508,9 @@ setvar(@"fog", 180); setvar(@"fogcolour", 0x8099B3); showscores(false); intermission = false; Cube.sharedInstance.framesInMap = 0; - conoutf(@"game mode is %s", modestr(gamemode)); + conoutf(@"game mode is %@", modestr(gamemode)); } COMMANDN(map, changemap, ARG_1STR) Index: src/clients2c.mm ================================================================== --- src/clients2c.mm +++ src/clients2c.mm @@ -13,16 +13,14 @@ conoutf(@"illegal network message (%@)", s); disconnect(); } void -changemapserv(char *name, int mode) // forced map change from the server +changemapserv(OFString *name, int mode) // forced map change from the server { gamemode = mode; - @autoreleasepool { - load_world(@(name)); - } + load_world(name); } void changemap(OFString *name) // request map change, server may ignore { @@ -98,11 +96,11 @@ return; } if (getint(p) == 1) conoutf(@"server is FULL, disconnecting.."); break; - }; + } case SV_POS: // position of another client { cn = getint(p); d = getclient(cn); @@ -127,11 +125,11 @@ d->lastaction = lastmillis; d->state = state; if (!demoplayback) updatepos(d); break; - }; + } case SV_SOUND: playsound(getint(p), &d->o); break; @@ -140,20 +138,22 @@ conoutf(@"%s:\f %s", d->name, text); break; case SV_MAPCHANGE: sgetstr(); - changemapserv(text, getint(p)); + @autoreleasepool { + changemapserv(@(text), getint(p)); + } mapchanged = true; break; case SV_ITEMLIST: { int n; if (mapchanged) { senditemstoserver = false; resetspawns(); - }; + } while ((n = getint(p)) != -1) if (mapchanged) setspawn(n, true); break; } @@ -365,14 +365,15 @@ sgetstr(); conoutf(@"received map \"%s\" from server, reloading..", text); int mapsize = getint(p); @autoreleasepool { - writemap(@(text), mapsize, p); + OFString *string = @(text); + writemap(string, mapsize, p); + p += mapsize; + changemapserv(string, gamemode); } - p += mapsize; - changemapserv(text, gamemode); break; } case SV_SERVMSG: sgetstr(); Index: src/commands.mm ================================================================== --- src/commands.mm +++ src/commands.mm @@ -343,21 +343,16 @@ bool execfile(OFString *cfgfile) { @autoreleasepool { - OFMutableData *data; @try { - data = [OFMutableData dataWithContentsOfFile:cfgfile]; + execute([OFString stringWithContentsOfFile:cfgfile]); } @catch (id e) { return false; } - // Ensure \0 termination. - [data addItem:""]; - - execute(@((char *)data.mutableItems)); return true; } } void Index: src/menus.mm ================================================================== --- src/menus.mm +++ src/menus.mm @@ -154,11 +154,11 @@ } else { if (code == SDLK_RETURN || code == -2) { OFString *action = menus[vmenu].items[menusel].action; if (vmenu == 1) { @autoreleasepool { - connects(@(getservername(menusel))); + connects(getservername(menusel)); } } if (menuStack == nil) menuStack = [[OFMutableArray alloc] init]; Index: src/protos.h ================================================================== --- src/protos.h +++ src/protos.h @@ -35,11 +35,11 @@ extern bool menukey(int code, bool isdown); extern void newmenu(OFString *name); // serverbrowser extern void addserver(OFString *servername); -extern char *getservername(int n); +extern OFString *getservername(int n); extern void writeservercfg(); // rendergl extern void gl_init(int w, int h); extern void cleangl(); @@ -80,11 +80,11 @@ extern void c2sinfo(dynent *d); extern void neterr(OFString *s); extern void initclientnet(); extern bool netmapstart(); extern int getclientnum(); -extern void changemapserv(char *name, int mode); +extern void changemapserv(OFString *name, int mode); extern void writeclientinfo(OFStream *stream); // clientgame extern void mousemove(int dx, int dy); extern void updateworld(int millis); @@ -93,11 +93,11 @@ extern void initclient(); extern void spawnplayer(dynent *d); extern void selfdamage(int damage, int actor, dynent *act); extern dynent *newdynent(); extern OFString *getclientmap(); -extern const char *modestr(int n); +extern OFString *modestr(int n); extern void zapdynent(dynent *&d); extern dynent *getclient(int cn); extern void timeupdate(int timeremain); extern void resetmovement(dynent *d); extern void fixplayer1range(); @@ -213,28 +213,28 @@ float scale, float speed, int snap = 0, int basetime = 0); @class MapModelInfo; extern MapModelInfo *getmminfo(int i); // server -extern void initserver(bool dedicated, int uprate, const char *sdesc, - const char *ip, const char *master, OFString *passwd, int maxcl); +extern void initserver(bool dedicated, int uprate, OFString *sdesc, + OFString *ip, OFString *master, OFString *passwd, int maxcl); extern void cleanupserver(); extern void localconnect(); extern void localdisconnect(); extern void localclienttoserver(struct _ENetPacket *); extern void serverslice(int seconds, unsigned int timeout); extern void putint(uchar *&p, int n); extern int getint(uchar *&p); -extern void sendstring(const char *t, uchar *&p); +extern void sendstring(OFString *t, uchar *&p); extern void startintermission(); extern void restoreserverstate(vector &ents); extern uchar *retrieveservers(uchar *buf, int buflen); extern char msgsizelookup(int msg); -extern void serverms(int mode, int numplayers, int minremain, char *smapname, - int seconds, bool isfull); -extern void servermsinit(const char *master, const char *sdesc, bool listen); -extern void sendmaps(int n, string mapname, int mapsize, uchar *mapdata); +extern void serverms(int mode, int numplayers, int minremain, + OFString *smapname, int seconds, bool isfull); +extern void servermsinit(OFString *master, OFString *sdesc, bool listen); +extern void sendmaps(int n, OFString *mapname, int mapsize, uchar *mapdata); extern ENetPacket *recvmap(int n); // weapon extern void selectgun(int a = -1, int b = -1, int c = -1); extern void shoot(dynent *d, OFVector3D &to); @@ -241,11 +241,11 @@ extern void shootv(int gun, OFVector3D &from, OFVector3D &to, dynent *d = 0, bool local = false); extern void createrays(OFVector3D &from, OFVector3D &to); extern void moveprojectiles(float time); extern void projreset(); -extern char *playerincrosshair(); +extern OFString *playerincrosshair(); extern int reloadtime(int gun); // monster extern void monsterclear(); extern void restoremonsterstate(); Index: src/renderextras.mm ================================================================== --- src/renderextras.mm +++ src/renderextras.mm @@ -365,18 +365,18 @@ glEnable(GL_TEXTURE_2D); @autoreleasepool { OFString *command = getcurcommand(); - char *player = playerincrosshair(); + OFString *player = playerincrosshair(); if (command) draw_textf(@"> %@_", 20, 1570, 2, command); else if (closeent[0]) draw_text(@(closeent), 20, 1570, 2); - else if (player) - draw_text(@(player), 20, 1570, 2); + else if (player != nil) + draw_text(player, 20, 1570, 2); } renderscores(); if (!rendermenu()) { glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); Index: src/server.mm ================================================================== --- src/server.mm +++ src/server.mm @@ -16,11 +16,11 @@ }; vector clients; int maxclients = 8; -string smapname; +static OFString *smapname; struct server_entity // server side version of "entity" type { bool spawned; int spawnsecs; @@ -94,11 +94,11 @@ if (packet->referenceCount == 0) enet_packet_destroy(packet); }; void -sendservmsg(char *msg) +sendservmsg(OFString *msg) { ENetPacket *packet = enet_packet_create( NULL, _MAXDEFSTR + 10, ENET_PACKET_FLAG_RELIABLE); uchar *start = packet->data; uchar *p = start + 2; @@ -107,11 +107,11 @@ *(ushort *)start = ENET_HOST_TO_NET_16(p - start); enet_packet_resize(packet, p - start); multicast(packet, -1); if (packet->referenceCount == 0) enet_packet_destroy(packet); -}; +} void disconnect_client(int n, char *reason) { printf("disconnecting client (%s) [%s]\n", clients[n].hostname, reason); @@ -163,16 +163,20 @@ } else no++; }; if (yes == 1 && no == 0) return true; // single player - sprintf_sd(msg)("%s suggests %s on map %s (set map to vote)", - clients[sender].name, modestr(reqmode), map); - sendservmsg(msg); + @autoreleasepool { + OFString *msg = + [OFString stringWithFormat: + @"%s suggests %@ on map %s (set map to vote)", + clients[sender].name, modestr(reqmode), map]; + sendservmsg(msg); + } if (yes / (float)(yes + no) <= 0.5f) return false; - sendservmsg("vote passed"); + sendservmsg(@"vote passed"); resetvotes(); return true; }; // server side processing of updates: does very little and most state is tracked @@ -209,23 +213,25 @@ case SV_MAPCHANGE: { sgetstr(); int reqmode = getint(p); if (reqmode < 0) reqmode = 0; - if (smapname[0] && !mapreload && + if (smapname.length > 0 && !mapreload && !vote(text, reqmode, sender)) return; mapreload = false; mode = reqmode; minremain = mode & 1 ? 15 : 10; mapend = lastsec + minremain * 60; interm = 0; - strcpy_s(smapname, text); + @autoreleasepool { + smapname = @(text); + } resetitems(); sender = -1; break; - }; + } case SV_ITEMLIST: { int n; while ((n = getint(p)) != -1) if (notgotitems) { @@ -234,17 +240,17 @@ sents.add(se); sents[n].spawned = true; }; notgotitems = false; break; - }; + } case SV_ITEMPICKUP: { int n = getint(p); pickup(n, getint(p), sender); break; - }; + } case SV_PING: send2(false, cn, SV_PONG, getint(p)); break; @@ -257,16 +263,18 @@ }; int size = msgsizelookup(type); assert(size != -1); loopi(size - 2) getint(p); break; - }; + } case SV_SENDMAP: { sgetstr(); int mapsize = getint(p); - sendmaps(sender, text, mapsize, p); + @autoreleasepool { + sendmaps(sender, @(text), mapsize, p); + } return; } case SV_RECVMAP: send(sender, recvmap(sender)); @@ -305,25 +313,27 @@ uchar *start = packet->data; uchar *p = start + 2; putint(p, SV_INITS2C); putint(p, n); putint(p, PROTOCOL_VERSION); - putint(p, smapname[0]); - sendstring(serverpassword.UTF8String, p); + @autoreleasepool { + putint(p, *smapname.UTF8String); + } + sendstring(serverpassword, p); putint(p, clients.length() > maxclients); - if (smapname[0]) { + if (smapname.length > 0) { putint(p, SV_MAPCHANGE); sendstring(smapname, p); putint(p, mode); putint(p, SV_ITEMLIST); loopv(sents) if (sents[i].spawned) putint(p, i); putint(p, -1); - }; + } *(ushort *)start = ENET_HOST_TO_NET_16(p - start); enet_packet_resize(packet, p - start); send(n, packet); -}; +} void multicast(ENetPacket *packet, int sender) { loopv(clients) @@ -369,19 +379,19 @@ void resetserverifempty() { loopv(clients) if (clients[i].type != ST_EMPTY) return; clients.setsize(0); - smapname[0] = 0; + smapname = @""; resetvotes(); resetitems(); mode = 0; mapreload = false; minremain = 10; mapend = lastsec + minremain * 60; interm = 0; -}; +} int nonlocalclients = 0; int lastconnect = 0; void @@ -507,22 +517,25 @@ strcpy_s(c.hostname, "local"); send_welcome(&c - &clients[0]); }; void -initserver(bool dedicated, int uprate, const char *sdesc, const char *ip, - const char *master, OFString *passwd, int maxcl) +initserver(bool dedicated, int uprate, OFString *sdesc, OFString *ip, + OFString *master, OFString *passwd, int maxcl) { serverpassword = passwd; maxclients = maxcl; - servermsinit(master ? master : "wouter.fov120.com/cube/masterserver/", + servermsinit(master ? master : @"wouter.fov120.com/cube/masterserver/", sdesc, dedicated); if (isdedicated = dedicated) { ENetAddress address = {ENET_HOST_ANY, CUBE_SERVER_PORT}; - if (*ip && enet_address_set_host(&address, ip) < 0) - printf("WARNING: server ip not resolved"); + @autoreleasepool { + if (ip.length > 0 && + enet_address_set_host(&address, ip.UTF8String) < 0) + printf("WARNING: server ip not resolved"); + } serverhost = enet_host_create(&address, MAXCLIENTS, 0, uprate); if (!serverhost) fatal(@"could not create server host\n"); loopi(MAXCLIENTS) serverhost->peers[i].data = (void *)-1; } Index: src/serverbrowser.mm ================================================================== --- src/serverbrowser.mm +++ src/serverbrowser.mm @@ -143,14 +143,16 @@ vector servers; ENetSocket pingsock = ENET_SOCKET_NULL; int lastinfo = 0; -char * +OFString * getservername(int n) { - return servers[n].name; + @autoreleasepool { + return @(servers[n].name); + } } void addserver(OFString *servername_) { @@ -270,15 +272,20 @@ serverinfo &si = servers[i]; if (si.address.host != ENET_HOST_ANY && si.ping != 9999) { if (si.protocol != PROTOCOL_VERSION) sprintf_s(si.full)( "%s [different cube protocol]", si.name); - else - sprintf_s(si.full)("%d\t%d\t%s, %s: %s %s", - si.ping, si.numplayers, - si.map[0] ? si.map : "[unknown]", - modestr(si.mode), si.name, si.sdesc); + else { + @autoreleasepool { + sprintf_s(si.full)( + "%d\t%d\t%s, %s: %s %s", si.ping, + si.numplayers, + si.map[0] ? si.map : "[unknown]", + modestr(si.mode).UTF8String, + si.name, si.sdesc); + } + } } else { sprintf_s(si.full)( si.address.host != ENET_HOST_ANY ? "%s [waiting for server response]" : "%s [unknown host]\t", Index: src/serverms.mm ================================================================== --- src/serverms.mm +++ src/serverms.mm @@ -10,31 +10,31 @@ if (ad.host == ENET_HOST_ANY) { printf("looking up %s...\n", hostname); enet_address_set_host(&ad, hostname); if (ad.host == ENET_HOST_ANY) return; - }; + } if (mssock != ENET_SOCKET_NULL) enet_socket_destroy(mssock); mssock = enet_socket_create(ENET_SOCKET_TYPE_STREAM, NULL); if (mssock == ENET_SOCKET_NULL) { printf("could not open socket\n"); return; - }; + } if (enet_socket_connect(mssock, &ad) < 0) { printf("could not connect\n"); return; - }; + } ENetBuffer buf; sprintf_sd(httpget)( "GET %s HTTP/1.0\nHost: %s\nReferer: %s\nUser-Agent: %s\n\n", req, hostname, ref, agent); buf.data = httpget; buf.dataLength = strlen((char *)buf.data); printf("sending request to %s...\n", hostname); enet_socket_send(mssock, NULL, &buf, 1); -}; +} void httpgetrecieve(ENetBuffer &buf) { if (mssock == ENET_SOCKET_NULL) @@ -108,15 +108,15 @@ httpgetrecieve(eb); return stripheader(buf); }; ENetSocket pongsock = ENET_SOCKET_NULL; -string serverdesc; +static OFString *serverdesc; void -serverms(int mode, int numplayers, int minremain, char *smapname, int seconds, - bool isfull) +serverms(int mode, int numplayers, int minremain, OFString *smapname, + int seconds, bool isfull) { checkmasterreply(); updatemasterserver(seconds); // reply all server info requests @@ -134,33 +134,37 @@ p = &pong[len]; putint(p, PROTOCOL_VERSION); putint(p, mode); putint(p, numplayers); putint(p, minremain); - string mname; - strcpy_s(mname, isfull ? "[FULL] " : ""); - strcat_s(mname, smapname); + OFString *mname = + [OFString stringWithFormat:@"%@%@", + (isfull ? @"[FULL] " : @""), smapname]; sendstring(mname, p); sendstring(serverdesc, p); buf.dataLength = p - pong; enet_socket_send(pongsock, &addr, &buf, 1); } } void -servermsinit(const char *master, const char *sdesc, bool listen) -{ - const char *mid = strstr(master, "/"); - if (!mid) - mid = master; - strcpy_s(masterpath, mid); - strn0cpy(masterbase, master, mid - master + 1); - strcpy_s(serverdesc, sdesc); - - if (listen) { - ENetAddress address = {ENET_HOST_ANY, CUBE_SERVINFO_PORT}; - pongsock = - enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM, &address); - if (pongsock == ENET_SOCKET_NULL) - fatal(@"could not create server info socket\n"); +servermsinit(OFString *master_, OFString *sdesc, bool listen) +{ + @autoreleasepool { + const char *master = master_.UTF8String; + const char *mid = strstr(master, "/"); + if (!mid) + mid = master; + strcpy_s(masterpath, mid); + strn0cpy(masterbase, master, mid - master + 1); + serverdesc = sdesc; + + if (listen) { + ENetAddress address = { + ENET_HOST_ANY, CUBE_SERVINFO_PORT}; + pongsock = enet_socket_create( + ENET_SOCKET_TYPE_DATAGRAM, &address); + if (pongsock == ENET_SOCKET_NULL) + fatal(@"could not create server info socket\n"); + } } } Index: src/serverutil.mm ================================================================== --- src/serverutil.mm +++ src/serverutil.mm @@ -38,42 +38,45 @@ n |= *p++ << 8; n |= *p++ << 16; return n | (*p++ << 24); } else return c; -}; - -void -sendstring(const char *t, uchar *&p) -{ - while (*t) - putint(p, *t++); - putint(p, 0); -}; - -const char *modenames[] = { - "SP", - "DMSP", - "ffa/default", - "coopedit", - "ffa/duel", - "teamplay", - "instagib", - "instagib team", - "efficiency", - "efficiency team", - "insta arena", - "insta clan arena", - "tactics arena", - "tactics clan arena", -}; - -const char * -modestr(int n) -{ - return (n >= -2 && n < 12) ? modenames[n + 2] : "unknown"; -}; +} + +void +sendstring(OFString *t_, uchar *&p) +{ + @autoreleasepool { + const char *t = t_.UTF8String; + while (*t) + putint(p, *t++); + putint(p, 0); + } +} + +static const OFString *modenames[] = { + @"SP", + @"DMSP", + @"ffa/default", + @"coopedit", + @"ffa/duel", + @"teamplay", + @"instagib", + @"instagib team", + @"efficiency", + @"efficiency team", + @"insta arena", + @"insta clan arena", + @"tactics arena", + @"tactics clan arena", +}; + +OFString * +modestr(int n) +{ + return (n >= -2 && n < 12) ? modenames[n + 2] : @"unknown"; +} char msgsizesl[] = // size inclusive message token, 0 for variable or // not-checked sizes {SV_INITS2C, 4, SV_INITC2S, 0, SV_POS, 12, SV_TEXT, 0, SV_SOUND, 2, SV_CDIS, 2, SV_EDITH, 7, SV_EDITT, 7, SV_EDITS, 6, SV_EDITD, 6, SV_EDITE, 6, @@ -92,20 +95,20 @@ return -1; }; // sending of maps between clients -string copyname; +static OFString *copyname; int copysize; uchar *copydata = NULL; void -sendmaps(int n, string mapname, int mapsize, uchar *mapdata) +sendmaps(int n, OFString *mapname, int mapsize, uchar *mapdata) { if (mapsize <= 0 || mapsize > 256 * 256) return; - strcpy_s(copyname, mapname); + copyname = mapname; copysize = mapsize; if (copydata) free(copydata); copydata = (uchar *)alloc(mapsize); memcpy(copydata, mapdata, mapsize); @@ -187,9 +190,9 @@ }; }; if (enet_initialize() < 0) fatal(@"Unable to initialise network module"); - initserver(true, uprate, sdesc, ip, master, @(passwd), maxcl); + initserver(true, uprate, @(sdesc), @(ip), @(master), @(passwd), maxcl); return 0; } #endif Index: src/tools.h ================================================================== --- src/tools.h +++ src/tools.h @@ -46,18 +46,13 @@ #define loopi(m) loop(i, m) #define loopj(m) loop(j, m) #define loopk(m) loop(k, m) #define loopl(m) loop(l, m) -#ifdef WIN32 -# pragma warning(3 : 4189) -// #pragma comment(linker,"/OPT:NOWIN98") -# define PATHDIV '\\' -#else +#ifndef OF_WINDOWS # define __cdecl # define _vsnprintf vsnprintf -# define PATHDIV '/' #endif // easy safe strings #define _MAXDEFSTR 260 Index: src/weapon.mm ================================================================== --- src/weapon.mm +++ src/weapon.mm @@ -109,22 +109,25 @@ return (p->x <= d->o.x + d->radius && p->x >= d->o.x - d->radius && p->y <= d->o.y + d->radius && p->y >= d->o.y - d->radius && p->z <= d->o.z + d->aboveeye && p->z >= d->o.z - d->eyeheight); } -char * +OFString * playerincrosshair() { if (demoplayback) return NULL; loopv(players) { dynent *o = players[i]; if (!o) continue; - if (intersect(o, player1->o, worldpos)) - return o->name; + if (intersect(o, player1->o, worldpos)) { + @autoreleasepool { + return @(o->name); + } + } } return NULL; } const int MAXPROJ = 100;