Artifact 0ddeef8a46f25c1ff6ac64be801516e30cbc748d89c1f11e07d953023d00357a:
- File
src/serverutil.mm
— part of check-in
[489124a92f]
at
2025-03-16 10:11:39
on branch trunk
— Use one autorelease pool per frame
This way, nowhere else autorelease pools need to be managed. (user: js, size: 3816) [annotate] [blame] [check-ins using]
// misc useful functions used by the server #include "cube.h" // all network traffic is in 32bit ints, which are then compressed using the // following simple scheme (assumes that most values are small). void putint(uchar *&p, int n) { if (n < 128 && n > -127) { *p++ = n; } else if (n < 0x8000 && n >= -0x8000) { *p++ = 0x80; *p++ = n; *p++ = n >> 8; } else { *p++ = 0x81; *p++ = n; *p++ = n >> 8; *p++ = n >> 16; *p++ = n >> 24; } } int getint(uchar *&p) { int c = *((char *)p); p++; if (c == -128) { int n = *p++; n |= *((char *)p) << 8; p++; return n; } else if (c == -127) { int n = *p++; n |= *p++ << 8; n |= *p++ << 16; return n | (*p++ << 24); } else return c; } void sendstring(OFString *t_, uchar *&p) { const char *t = t_.UTF8String; for (size_t i = 0; i < _MAXDEFSTR && *t != '\0'; i++) 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"; } // size inclusive message token, 0 for variable or not-checked sizes char msgsizesl[] = { 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, SV_DIED, 2, SV_DAMAGE, 4, SV_SHOT, 8, SV_FRAGS, 2, SV_MAPCHANGE, 0, SV_ITEMSPAWN, 2, SV_ITEMPICKUP, 3, SV_DENIED, 2, SV_PING, 2, SV_PONG, 2, SV_CLIENTPING, 2, SV_GAMEMODE, 2, SV_TIMEUP, 2, SV_EDITENT, 10, SV_MAPRELOAD, 2, SV_ITEMACC, 2, SV_SENDMAP, 0, SV_RECVMAP, 1, SV_SERVMSG, 0, SV_ITEMLIST, 0, SV_EXT, 0, -1 }; char msgsizelookup(int msg) { for (char *p = msgsizesl; *p >= 0; p += 2) if (*p == msg) return p[1]; return -1; } // sending of maps between clients static OFString *copyname; int copysize; uchar *copydata = NULL; void sendmaps(int n, OFString *mapname, int mapsize, uchar *mapdata) { if (mapsize <= 0 || mapsize > 256 * 256) return; copyname = mapname; copysize = mapsize; if (copydata) OFFreeMemory(copydata); copydata = (uchar *)OFAllocMemory(1, mapsize); memcpy(copydata, mapdata, mapsize); } ENetPacket * recvmap(int n) { if (!copydata) return NULL; ENetPacket *packet = enet_packet_create( NULL, MAXTRANS + copysize, ENET_PACKET_FLAG_RELIABLE); uchar *start = packet->data; uchar *p = start + 2; putint(p, SV_RECVMAP); sendstring(copyname, p); putint(p, copysize); memcpy(p, copydata, copysize); p += copysize; *(ushort *)start = ENET_HOST_TO_NET_16(p - start); enet_packet_resize(packet, p - start); return packet; } #ifdef STANDALONE void localservertoclient(uchar *buf, int len) { } void fatal(OFString *s, OFString *o) { cleanupserver(); [OFStdOut writeFormat:@"servererror: %@\n", s]; exit(1); } void * alloc(int s) { void *b = calloc(1, s); if (!b) fatal(@"no memory!"); return b; } int main(int argc, char *argv[]) { int uprate = 0, maxcl = 4; const char *sdesc = "", *ip = "", *master = NULL, *passwd = ""; for (int i = 1; i < argc; i++) { char *a = &argv[i][2]; if (argv[i][0] == '-') switch (argv[i][1]) { case 'u': uprate = atoi(a); break; case 'n': sdesc = a; break; case 'i': ip = a; break; case 'm': master = a; break; case 'p': passwd = a; break; case 'c': maxcl = atoi(a); break; default: printf("WARNING: unknown commandline option\n"); } } if (enet_initialize() < 0) fatal(@"Unable to initialise network module"); initserver(true, uprate, @(sdesc), @(ip), (master != NULL ? @(master) : nil), @(passwd), maxcl); return 0; } #endif