Index: src/Cube.mm ================================================================== --- src/Cube.mm +++ src/Cube.mm @@ -19,266 +19,279 @@ return (Cube *)OFApplication.sharedApplication.delegate; } - (void)applicationDidFinishLaunching:(OFNotification *)notification { - bool dedicated, windowed; - int par = 0, uprate = 0, maxcl = 4; - OFString *__autoreleasing sdesc, *__autoreleasing ip; - OFString *__autoreleasing master, *__autoreleasing passwd; - - processInitQueue(); - -#define log(s) conoutf(@"init: %@", s) - log(@"sdl"); - - const OFOptionsParserOption options[] = { { 'd', @"dedicated", 0, - &dedicated, NULL }, - { 't', @"window", 0, &windowed, NULL }, - { 'w', @"width", 1, NULL, NULL }, - { 'h', @"height", 1, NULL, NULL }, - { 'u', @"upload-rate", 1, NULL, NULL }, - { 'n', @"server-desc", 1, NULL, &sdesc }, - { 'i', @"ip", 1, NULL, &ip }, - { 'm', @"master", 1, NULL, &master }, - { 'p', @"password", 1, NULL, &passwd }, - { 'c', @"max-clients", 1, NULL, NULL }, - { '\0', nil, 0, NULL, NULL } }; - OFOptionsParser *optionsParser = - [OFOptionsParser parserWithOptions:options]; - OFUnichar option; - while ((option = [optionsParser nextOption]) != '\0') { - switch (option) { - case 'w': - _width = optionsParser.argument.intValue; - break; - case 'h': - _height = optionsParser.argument.intValue; - break; - case 'u': - uprate = optionsParser.argument.intValue; - break; - case 'c': - maxcl = optionsParser.argument.intValue; - break; - case ':': - case '=': - case '?': - conoutf(@"unknown commandline option"); - [OFApplication terminateWithStatus:1]; - } - } - - if (sdesc == nil) - sdesc = @""; - if (ip == nil) - ip = @""; - if (passwd == nil) - passwd = @""; - - _gameDataIRI = [OFFileManager.defaultManager currentDirectoryIRI]; - _userDataIRI = [OFFileManager.defaultManager currentDirectoryIRI]; - - [OFFileManager.defaultManager - createDirectoryAtIRI:[_userDataIRI - IRIByAppendingPathComponent:@"demos"] - createParents:true]; - [OFFileManager.defaultManager - createDirectoryAtIRI:[_userDataIRI - IRIByAppendingPathComponent:@"savegames"] - createParents:true]; - - if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | par) < 0) - fatal(@"Unable to initialize SDL"); - - initPlayers(); - - log(@"net"); - if (enet_initialize() < 0) - fatal(@"Unable to initialise network module"); - - initclient(); - // never returns if dedicated - initserver(dedicated, uprate, sdesc, ip, master, passwd, maxcl); - - log(@"world"); - empty_world(7, true); - - log(@"video: sdl"); - if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) - fatal(@"Unable to initialize SDL Video"); - - if (_width == 0 || _height == 0) { - SDL_DisplayMode mode; - - if (SDL_GetDesktopDisplayMode(0, &mode) == 0) { - _width = mode.w; - _height = mode.h; - } else { - _width = 1920; - _height = 1080; - } - } - - log(@"video: mode"); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - if ((_window = SDL_CreateWindow("cube engine", SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, _width, _height, - SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | - (!windowed ? SDL_WINDOW_FULLSCREEN : 0))) == NULL || - SDL_GL_CreateContext(_window) == NULL) - fatal(@"Unable to create OpenGL screen"); - - log(@"video: misc"); - SDL_SetWindowGrab(_window, SDL_TRUE); - SDL_SetRelativeMouseMode(SDL_TRUE); - SDL_ShowCursor(0); - - log(@"gl"); - gl_init(_width, _height); - - log(@"basetex"); - int xs, ys; - if (!installtex(2, - [_gameDataIRI IRIByAppendingPathComponent:@"data/newchars.png"], - &xs, &ys, false) || - !installtex(3, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/martin/base.png"], - &xs, &ys, false) || - !installtex(6, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/martin/ball1.png"], - &xs, &ys, false) || - !installtex(7, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/martin/smoke.png"], - &xs, &ys, false) || - !installtex(8, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/martin/ball2.png"], - &xs, &ys, false) || - !installtex(9, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/martin/ball3.png"], - &xs, &ys, false) || - !installtex(4, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/explosion.jpg"], - &xs, &ys, false) || - !installtex(5, - [_gameDataIRI IRIByAppendingPathComponent:@"data/items.png"], - &xs, &ys, false) || - !installtex(1, - [_gameDataIRI - IRIByAppendingPathComponent:@"data/crosshair.png"], - &xs, &ys, false)) - fatal(@"could not find core textures (hint: run cube from the " - @"parent of the bin directory)"); - - log(@"sound"); - initsound(); - - log(@"cfg"); - newmenu(@"frags\tpj\tping\tteam\tname"); - newmenu(@"ping\tplr\tserver"); - exec(@"data/keymap.cfg"); - exec(@"data/menus.cfg"); - exec(@"data/prefabs.cfg"); - exec(@"data/sounds.cfg"); - exec(@"servers.cfg"); - if (!execfile([_userDataIRI IRIByAppendingPathComponent:@"config.cfg"])) - execfile([_gameDataIRI - IRIByAppendingPathComponent:@"data/defaults.cfg"]); - exec(@"autoexec.cfg"); - - log(@"localconnect"); - localconnect(); - // if this map is changed, also change depthcorrect() - changemap(@"metl3"); - - log(@"mainloop"); - int ignore = 5; - OFDate *past = [OFDate date]; - for (;;) { - [OFRunLoop.mainRunLoop runUntilDate:past]; - - int millis = SDL_GetTicks() * gamespeed / 100; - if (millis - lastmillis > 200) - lastmillis = millis - 200; - else if (millis - lastmillis < 1) - lastmillis = millis - 1; - if (millis - lastmillis < minmillis) - SDL_Delay(minmillis - (millis - lastmillis)); - - cleardlights(); - updateworld(millis); - - if (!demoplayback) - serverslice((int)time(NULL), 0); - - static float fps = 30.0f; - fps = (1000.0f / curtime + fps * 50) / 51; - - computeraytable(player1.o.x, player1.o.y); - readdepth(_width, _height); - SDL_GL_SwapWindow(_window); - extern void updatevol(); - updatevol(); - - // cheap hack to get rid of initial sparklies, even when triple - // buffering etc. - if (_framesInMap++ < 5) { - player1.yaw += 5; - gl_drawframe(_width, _height, fps); - player1.yaw -= 5; - } - - gl_drawframe(_width, _height, fps); - - SDL_Event event; - int lasttype = 0, lastbut = 0; - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - [self quit]; - break; - case SDL_KEYDOWN: - case SDL_KEYUP: - if (_repeatsKeys || event.key.repeat == 0) - keypress(event.key.keysym.sym, - event.key.state == SDL_PRESSED); - break; - case SDL_TEXTINPUT: - @autoreleasepool { - input(@(event.text.text)); - } - break; - case SDL_MOUSEMOTION: - if (ignore) { - ignore--; - break; - } - mousemove(event.motion.xrel, event.motion.yrel); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - if (lasttype == event.type && - lastbut == event.button.button) - // why?? get event twice without it - break; - - keypress(-event.button.button, - event.button.state != 0); - lasttype = event.type; - lastbut = event.button.button; - break; - } - } - } - - [self quit]; + @autoreleasepool { + bool dedicated, windowed; + int par = 0, uprate = 0, maxcl = 4; + OFString *__autoreleasing sdesc, *__autoreleasing ip; + OFString *__autoreleasing master, *__autoreleasing passwd; + + processInitQueue(); + +#define log(s) conoutf(@"init: %@", s) + log(@"sdl"); + + const OFOptionsParserOption options[] = { + { 'd', @"dedicated", 0, &dedicated, NULL }, + { 't', @"window", 0, &windowed, NULL }, + { 'w', @"width", 1, NULL, NULL }, + { 'h', @"height", 1, NULL, NULL }, + { 'u', @"upload-rate", 1, NULL, NULL }, + { 'n', @"server-desc", 1, NULL, &sdesc }, + { 'i', @"ip", 1, NULL, &ip }, + { 'm', @"master", 1, NULL, &master }, + { 'p', @"password", 1, NULL, &passwd }, + { 'c', @"max-clients", 1, NULL, NULL }, + { '\0', nil, 0, NULL, NULL } + }; + OFOptionsParser *optionsParser = + [OFOptionsParser parserWithOptions:options]; + OFUnichar option; + while ((option = [optionsParser nextOption]) != '\0') { + switch (option) { + case 'w': + _width = optionsParser.argument.intValue; + break; + case 'h': + _height = optionsParser.argument.intValue; + break; + case 'u': + uprate = optionsParser.argument.intValue; + break; + case 'c': + maxcl = optionsParser.argument.intValue; + break; + case ':': + case '=': + case '?': + conoutf(@"unknown commandline option"); + [OFApplication terminateWithStatus:1]; + } + } + + if (sdesc == nil) + sdesc = @""; + if (ip == nil) + ip = @""; + if (passwd == nil) + passwd = @""; + + _gameDataIRI = + [OFFileManager.defaultManager currentDirectoryIRI]; + _userDataIRI = + [OFFileManager.defaultManager currentDirectoryIRI]; + + [OFFileManager.defaultManager + createDirectoryAtIRI: + [_userDataIRI IRIByAppendingPathComponent:@"demos"] + createParents:true]; + [OFFileManager.defaultManager + createDirectoryAtIRI: + [_userDataIRI IRIByAppendingPathComponent:@"savegames"] + createParents:true]; + + if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | par) < 0) + fatal(@"Unable to initialize SDL"); + + initPlayers(); + + log(@"net"); + if (enet_initialize() < 0) + fatal(@"Unable to initialise network module"); + + initclient(); + // never returns if dedicated + initserver(dedicated, uprate, sdesc, ip, master, passwd, maxcl); + + log(@"world"); + empty_world(7, true); + + log(@"video: sdl"); + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + fatal(@"Unable to initialize SDL Video"); + + if (_width == 0 || _height == 0) { + SDL_DisplayMode mode; + + if (SDL_GetDesktopDisplayMode(0, &mode) == 0) { + _width = mode.w; + _height = mode.h; + } else { + _width = 1920; + _height = 1080; + } + } + + log(@"video: mode"); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + if ((_window = SDL_CreateWindow("cube engine", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + _width, _height, + SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | + (!windowed ? SDL_WINDOW_FULLSCREEN : 0))) == + NULL || + SDL_GL_CreateContext(_window) == NULL) + fatal(@"Unable to create OpenGL screen"); + + log(@"video: misc"); + SDL_SetWindowGrab(_window, SDL_TRUE); + SDL_SetRelativeMouseMode(SDL_TRUE); + SDL_ShowCursor(0); + + log(@"gl"); + gl_init(_width, _height); + + log(@"basetex"); + int xs, ys; + if (!installtex(2, + [_gameDataIRI + IRIByAppendingPathComponent:@"data/newchars.png"], + &xs, &ys, false) || + !installtex(3, + [_gameDataIRI IRIByAppendingPathComponent: + @"data/martin/base.png"], + &xs, &ys, false) || + !installtex(6, + [_gameDataIRI IRIByAppendingPathComponent: + @"data/martin/ball1.png"], + &xs, &ys, false) || + !installtex(7, + [_gameDataIRI IRIByAppendingPathComponent: + @"data/martin/smoke.png"], + &xs, &ys, false) || + !installtex(8, + [_gameDataIRI IRIByAppendingPathComponent: + @"data/martin/ball2.png"], + &xs, &ys, false) || + !installtex(9, + [_gameDataIRI IRIByAppendingPathComponent: + @"data/martin/ball3.png"], + &xs, &ys, false) || + !installtex(4, + [_gameDataIRI + IRIByAppendingPathComponent:@"data/explosion.jpg"], + &xs, &ys, false) || + !installtex(5, + [_gameDataIRI + IRIByAppendingPathComponent:@"data/items.png"], + &xs, &ys, false) || + !installtex(1, + [_gameDataIRI + IRIByAppendingPathComponent:@"data/crosshair.png"], + &xs, &ys, false)) + fatal(@"could not find core textures (hint: run cube " + @"from the parent of the bin directory)"); + + log(@"sound"); + initsound(); + + log(@"cfg"); + newmenu(@"frags\tpj\tping\tteam\tname"); + newmenu(@"ping\tplr\tserver"); + exec(@"data/keymap.cfg"); + exec(@"data/menus.cfg"); + exec(@"data/prefabs.cfg"); + exec(@"data/sounds.cfg"); + exec(@"servers.cfg"); + if (!execfile([_userDataIRI + IRIByAppendingPathComponent:@"config.cfg"])) + execfile([_gameDataIRI + IRIByAppendingPathComponent:@"data/defaults.cfg"]); + exec(@"autoexec.cfg"); + + log(@"localconnect"); + localconnect(); + // if this map is changed, also change depthcorrect() + changemap(@"metl3"); + + log(@"mainloop"); + } + + OFDate *past = [OFDate date]; + int ignore = 5; + for (;;) { + @autoreleasepool { + [OFRunLoop.mainRunLoop runUntilDate:past]; + + int millis = SDL_GetTicks() * gamespeed / 100; + if (millis - lastmillis > 200) + lastmillis = millis - 200; + else if (millis - lastmillis < 1) + lastmillis = millis - 1; + if (millis - lastmillis < minmillis) + SDL_Delay(minmillis - (millis - lastmillis)); + + cleardlights(); + updateworld(millis); + + if (!demoplayback) + serverslice((int)time(NULL), 0); + + static float fps = 30.0f; + fps = (1000.0f / curtime + fps * 50) / 51; + + computeraytable(player1.o.x, player1.o.y); + readdepth(_width, _height); + SDL_GL_SwapWindow(_window); + extern void updatevol(); + updatevol(); + + // cheap hack to get rid of initial sparklies, even when + // triple buffering etc. + if (_framesInMap++ < 5) { + player1.yaw += 5; + gl_drawframe(_width, _height, fps); + player1.yaw -= 5; + } + + gl_drawframe(_width, _height, fps); + + SDL_Event event; + int lasttype = 0, lastbut = 0; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + [self quit]; + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + if (_repeatsKeys || + event.key.repeat == 0) + keypress(event.key.keysym.sym, + event.key.state == + SDL_PRESSED); + break; + case SDL_TEXTINPUT: + input(@(event.text.text)); + break; + case SDL_MOUSEMOTION: + if (ignore) { + ignore--; + break; + } + mousemove(event.motion.xrel, + event.motion.yrel); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if (lasttype == event.type && + lastbut == event.button.button) + // why?? get event twice without + // it + break; + + keypress(-event.button.button, + event.button.state != 0); + lasttype = event.type; + lastbut = event.button.button; + break; + } + } + } + } } - (void)applicationWillTerminate:(OFNotification *)notification { stop(); @@ -321,20 +334,16 @@ 3 * _width * (_height - 1 - idx), 3 * _width); endianswap(dest, 3, _width); } - @autoreleasepool { - OFString *path = [OFString - stringWithFormat: - @"screenshots/screenshot_%d.bmp", - lastmillis]; - SDL_SaveBMP(temp, - [_userDataIRI - IRIByAppendingPathComponent:path] - .fileSystemRepresentation.UTF8String); - } + OFString *path = [OFString + stringWithFormat:@"screenshots/screenshot_%d.bmp", + lastmillis]; + SDL_SaveBMP(temp, + [_userDataIRI IRIByAppendingPathComponent:path] + .fileSystemRepresentation.UTF8String); SDL_FreeSurface(temp); } SDL_FreeSurface(image); } Index: src/MD2.mm ================================================================== --- src/MD2.mm +++ src/MD2.mm @@ -52,64 +52,61 @@ delete[] _frames; } - (bool)loadWithIRI:(OFIRI *)IRI { - @autoreleasepool { - OFSeekableStream *stream; - @try { - stream = (OFSeekableStream *)[[OFIRIHandler - handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"]; - } @catch (id e) { - return false; - } - - if (![stream isKindOfClass:OFSeekableStream.class]) - return false; - - md2_header header; - [stream readIntoBuffer:&header exactLength:sizeof(md2_header)]; - endianswap( - &header, sizeof(int), sizeof(md2_header) / sizeof(int)); - - if (header.magic != 844121161 || header.version != 8) - return false; - - _frames = new char[header.frameSize * header.numFrames]; - if (_frames == NULL) - return false; - - [stream seekToOffset:header.offsetFrames whence:OFSeekSet]; - [stream readIntoBuffer:_frames - exactLength:header.frameSize * header.numFrames]; - - for (int i = 0; i < header.numFrames; ++i) - endianswap( - _frames + i * header.frameSize, sizeof(float), 6); - - _glCommands = new int[header.numGlCommands]; - if (_glCommands == NULL) - return false; - - [stream seekToOffset:header.offsetGlCommands whence:OFSeekSet]; - [stream readIntoBuffer:_glCommands - exactLength:header.numGlCommands * sizeof(int)]; - endianswap(_glCommands, sizeof(int), header.numGlCommands); - - _numFrames = header.numFrames; - _numGlCommands = header.numGlCommands; - _frameSize = header.frameSize; - _numTriangles = header.numTriangles; - _numVerts = header.numVertices; - - [stream close]; - - _mverts = new OFVector3D *[_numFrames]; - loopj(_numFrames) _mverts[j] = NULL; - - return true; - } + OFSeekableStream *stream; + @try { + stream = (OFSeekableStream *)[[OFIRIHandler handlerForIRI:IRI] + openItemAtIRI:IRI + mode:@"r"]; + } @catch (id e) { + return false; + } + + if (![stream isKindOfClass:OFSeekableStream.class]) + return false; + + md2_header header; + [stream readIntoBuffer:&header exactLength:sizeof(md2_header)]; + endianswap(&header, sizeof(int), sizeof(md2_header) / sizeof(int)); + + if (header.magic != 844121161 || header.version != 8) + return false; + + _frames = new char[header.frameSize * header.numFrames]; + if (_frames == NULL) + return false; + + [stream seekToOffset:header.offsetFrames whence:OFSeekSet]; + [stream readIntoBuffer:_frames + exactLength:header.frameSize * header.numFrames]; + + for (int i = 0; i < header.numFrames; ++i) + endianswap(_frames + i * header.frameSize, sizeof(float), 6); + + _glCommands = new int[header.numGlCommands]; + if (_glCommands == NULL) + return false; + + [stream seekToOffset:header.offsetGlCommands whence:OFSeekSet]; + [stream readIntoBuffer:_glCommands + exactLength:header.numGlCommands * sizeof(int)]; + endianswap(_glCommands, sizeof(int), header.numGlCommands); + + _numFrames = header.numFrames; + _numGlCommands = header.numGlCommands; + _frameSize = header.frameSize; + _numTriangles = header.numTriangles; + _numVerts = header.numVertices; + + [stream close]; + + _mverts = new OFVector3D *[_numFrames]; + loopj(_numFrames) _mverts[j] = NULL; + + return true; } - (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)sn { _mverts[frame] = new OFVector3D[_numVerts]; Index: src/client.mm ================================================================== --- src/client.mm +++ src/client.mm @@ -61,32 +61,28 @@ } void newname(OFString *name) { - @autoreleasepool { - c2sinit = false; - - if (name.length > 16) - name = [name substringToIndex:16]; - - player1.name = name; - } + c2sinit = false; + + if (name.length > 16) + name = [name substringToIndex:16]; + + player1.name = name; } COMMANDN(name, newname, ARG_1STR) void newteam(OFString *name) { - @autoreleasepool { - c2sinit = false; - - if (name.length > 5) - name = [name substringToIndex:5]; - - player1.team = name; - } + c2sinit = false; + + if (name.length > 5) + name = [name substringToIndex:5]; + + player1.team = name; } COMMANDN(team, newteam, ARG_1STR) void writeclientinfo(OFStream *stream) @@ -101,16 +97,13 @@ disconnect(1); // reset state addserver(servername); conoutf(@"attempting to connect to %@", servername); ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT }; - @autoreleasepool { - if (enet_address_set_host(&address, servername.UTF8String) < - 0) { - conoutf(@"could not resolve server %@", servername); - return; - } + if (enet_address_set_host(&address, servername.UTF8String) < 0) { + conoutf(@"could not resolve server %@", servername); + return; } clienthost = enet_host_create(NULL, 1, rate, rate); if (clienthost) { @@ -285,103 +278,98 @@ // send update to the server void c2sinfo(DynamicEntity *d) { - @autoreleasepool { - if (clientnum < 0) - return; // we haven't had a welcome message from the - // server yet - if (lastmillis - lastupdate < 40) - return; // don't update faster than 25fps - ENetPacket *packet = enet_packet_create(NULL, MAXTRANS, 0); - uchar *start = packet->data; - uchar *p = start + 2; - bool serveriteminitdone = false; - 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, p); - toservermap = @""; - putint(p, nextmode); - } else { - putint(p, SV_POS); - putint(p, clientnum); - // quantize coordinates to 1/16th of a cube, between 1 - // and 3 bytes - putint(p, (int)(d.o.x * DMF)); - putint(p, (int)(d.o.y * DMF)); - putint(p, (int)(d.o.z * DMF)); - putint(p, (int)(d.yaw * DAF)); - putint(p, (int)(d.pitch * DAF)); - putint(p, (int)(d.roll * DAF)); - // quantize to 1/100, almost always 1 byte - putint(p, (int)(d.vel.x * DVF)); - putint(p, (int)(d.vel.y * DVF)); - putint(p, (int)(d.vel.z * DVF)); - // pack rest in 1 byte: strafe:2, move:2, onfloor:1, - // state:3 - putint(p, - (d.strafe & 3) | ((d.move & 3) << 2) | - (((int)d.onfloor) << 4) | - ((editmode ? CS_EDITING : d.state) << 5)); - - if (senditemstoserver) { - packet->flags = ENET_PACKET_FLAG_RELIABLE; - putint(p, SV_ITEMLIST); - if (!m_noitems) - putitems(p); - putint(p, -1); - senditemstoserver = false; - serveriteminitdone = true; - } - // player chat, not flood protected for now - if (ctext.length > 0) { - packet->flags = ENET_PACKET_FLAG_RELIABLE; - putint(p, SV_TEXT); - sendstring(ctext, p); - ctext = @""; - } - // tell other clients who I am - if (!c2sinit) { - packet->flags = ENET_PACKET_FLAG_RELIABLE; - c2sinit = true; - putint(p, SV_INITC2S); - sendstring(player1.name, p); - sendstring(player1.team, p); - putint(p, player1.lifesequence); - } - for (OFData *msg in messages) { - // send messages collected during the previous - // frames - if (*(int *)[msg itemAtIndex:1]) - packet->flags = - ENET_PACKET_FLAG_RELIABLE; - loopi(*(int *)[msg itemAtIndex:0]) - putint(p, *(int *)[msg itemAtIndex:i + 2]); - } - [messages removeAllObjects]; - if (lastmillis - lastping > 250) { - putint(p, SV_PING); - putint(p, lastmillis); - lastping = lastmillis; - } - } - *(ushort *)start = ENET_HOST_TO_NET_16(p - start); - enet_packet_resize(packet, p - start); - incomingdemodata(start, p - start, true); - if (clienthost) { - enet_host_broadcast(clienthost, 0, packet); - enet_host_flush(clienthost); - } else - localclienttoserver(packet); - lastupdate = lastmillis; - if (serveriteminitdone) - loadgamerest(); // hack - } + if (clientnum < 0) + return; // we haven't had a welcome message from the server yet + if (lastmillis - lastupdate < 40) + return; // don't update faster than 25fps + ENetPacket *packet = enet_packet_create(NULL, MAXTRANS, 0); + uchar *start = packet->data; + uchar *p = start + 2; + bool serveriteminitdone = false; + // suggest server to change map + if (toservermap.length > 0) { + // do this exclusively as map change may invalidate rest of + // update + packet->flags = ENET_PACKET_FLAG_RELIABLE; + putint(p, SV_MAPCHANGE); + sendstring(toservermap, p); + toservermap = @""; + putint(p, nextmode); + } else { + putint(p, SV_POS); + putint(p, clientnum); + // quantize coordinates to 1/16th of a cube, between 1 and 3 + // bytes + putint(p, (int)(d.o.x * DMF)); + putint(p, (int)(d.o.y * DMF)); + putint(p, (int)(d.o.z * DMF)); + putint(p, (int)(d.yaw * DAF)); + putint(p, (int)(d.pitch * DAF)); + putint(p, (int)(d.roll * DAF)); + // quantize to 1/100, almost always 1 byte + putint(p, (int)(d.vel.x * DVF)); + putint(p, (int)(d.vel.y * DVF)); + putint(p, (int)(d.vel.z * DVF)); + // pack rest in 1 byte: strafe:2, move:2, onfloor:1, state:3 + putint(p, + (d.strafe & 3) | ((d.move & 3) << 2) | + (((int)d.onfloor) << 4) | + ((editmode ? CS_EDITING : d.state) << 5)); + + if (senditemstoserver) { + packet->flags = ENET_PACKET_FLAG_RELIABLE; + putint(p, SV_ITEMLIST); + if (!m_noitems) + putitems(p); + putint(p, -1); + senditemstoserver = false; + serveriteminitdone = true; + } + // player chat, not flood protected for now + if (ctext.length > 0) { + packet->flags = ENET_PACKET_FLAG_RELIABLE; + putint(p, SV_TEXT); + sendstring(ctext, p); + ctext = @""; + } + // tell other clients who I am + if (!c2sinit) { + packet->flags = ENET_PACKET_FLAG_RELIABLE; + c2sinit = true; + putint(p, SV_INITC2S); + sendstring(player1.name, p); + sendstring(player1.team, p); + putint(p, player1.lifesequence); + } + for (OFData *msg in messages) { + // send messages collected during the previous frames + if (*(int *)[msg itemAtIndex:1]) + packet->flags = ENET_PACKET_FLAG_RELIABLE; + loopi(*(int *)[msg itemAtIndex:0]) + putint(p, *(int *)[msg itemAtIndex:i + 2]); + } + [messages removeAllObjects]; + if (lastmillis - lastping > 250) { + putint(p, SV_PING); + putint(p, lastmillis); + lastping = lastmillis; + } + } + *(ushort *)start = ENET_HOST_TO_NET_16(p - start); + enet_packet_resize(packet, p - start); + incomingdemodata(start, p - start, true); + if (clienthost) { + enet_host_broadcast(clienthost, 0, packet); + enet_host_flush(clienthost); + } else + localclienttoserver(packet); + lastupdate = lastmillis; + if (serveriteminitdone) + loadgamerest(); // hack } void gets2c() // get updates from the server { Index: src/clientextras.mm ================================================================== --- src/clientextras.mm +++ src/clientextras.mm @@ -105,25 +105,23 @@ static OFMutableArray *scoreLines; void renderscore(DynamicEntity *d) { - @autoreleasepool { - OFString *lag = [OFString stringWithFormat:@"%d", d.plag]; - OFString *name = [OFString stringWithFormat:@"(%@)", d.name]; - OFString *line = - [OFString stringWithFormat:@"%d\t%@\t%d\t%@\t%@", d.frags, - (d.state == CS_LAGGED ? @"LAG" : lag), d.ping, - d.team, (d.state == CS_DEAD ? name : d.name)]; - - if (scoreLines == nil) - scoreLines = [[OFMutableArray alloc] init]; - - [scoreLines addObject:line]; - - menumanual(0, scoreLines.count - 1, line); - } + OFString *lag = [OFString stringWithFormat:@"%d", d.plag]; + OFString *name = [OFString stringWithFormat:@"(%@)", d.name]; + OFString *line = + [OFString stringWithFormat:@"%d\t%@\t%d\t%@\t%@", d.frags, + (d.state == CS_LAGGED ? @"LAG" : lag), d.ping, d.team, + (d.state == CS_DEAD ? name : d.name)]; + + if (scoreLines == nil) + scoreLines = [[OFMutableArray alloc] init]; + + [scoreLines addObject:line]; + + menumanual(0, scoreLines.count - 1, line); } static const int maxTeams = 4; static OFString *teamName[maxTeams]; static int teamScore[maxTeams]; @@ -130,24 +128,22 @@ static size_t teamsUsed; void addteamscore(DynamicEntity *d) { - @autoreleasepool { - for (size_t i = 0; i < teamsUsed; i++) { - if ([teamName[i] isEqual:d.team]) { - teamScore[i] += d.frags; - return; - } - } - - if (teamsUsed == maxTeams) - return; - - teamName[teamsUsed] = d.team; - teamScore[teamsUsed++] = d.frags; - } + for (size_t i = 0; i < teamsUsed; i++) { + if ([teamName[i] isEqual:d.team]) { + teamScore[i] += d.frags; + return; + } + } + + if (teamsUsed == maxTeams) + return; + + teamName[teamsUsed] = d.team; + teamScore[teamsUsed++] = d.frags; } void renderscores() { @@ -170,53 +166,49 @@ OFMutableString *teamScores = [[OFMutableString alloc] init]; for (size_t j = 0; j < teamsUsed; j++) [teamScores appendFormat:@"[ %@: %d ]", teamName[j], teamScore[j]]; menumanual(0, scoreLines.count, @""); - @autoreleasepool { - menumanual(0, scoreLines.count + 1, teamScores); - } + menumanual(0, scoreLines.count + 1, teamScores); } } // sendmap/getmap commands, should be replaced by more intuitive map downloading void sendmap(OFString *mapname) { - @autoreleasepool { - if (mapname.length > 0) - save_world(mapname); - changemap(mapname); - mapname = getclientmap(); - OFData *mapdata = readmap(mapname); - if (mapdata == nil) - return; - 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, p); - putint(p, mapdata.count); - if (65535 - (p - start) < mapdata.count) { - conoutf(@"map %@ is too large to send", mapname); - enet_packet_destroy(packet); - return; - } - memcpy(p, mapdata.items, mapdata.count); - p += mapdata.count; - *(ushort *)start = ENET_HOST_TO_NET_16(p - start); - enet_packet_resize(packet, p - start); - sendpackettoserv(packet); - conoutf(@"sending map %@ to server...", mapname); - OFString *msg = - [OFString stringWithFormat:@"[map %@ uploaded to server, " - @"\"getmap\" to receive it]", - mapname]; - toserver(msg); - } + if (mapname.length > 0) + save_world(mapname); + changemap(mapname); + mapname = getclientmap(); + OFData *mapdata = readmap(mapname); + if (mapdata == nil) + return; + 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, p); + putint(p, mapdata.count); + if (65535 - (p - start) < mapdata.count) { + conoutf(@"map %@ is too large to send", mapname); + enet_packet_destroy(packet); + return; + } + memcpy(p, mapdata.items, mapdata.count); + p += mapdata.count; + *(ushort *)start = ENET_HOST_TO_NET_16(p - start); + enet_packet_resize(packet, p - start); + sendpackettoserv(packet); + conoutf(@"sending map %@ to server...", mapname); + OFString *msg = + [OFString stringWithFormat:@"[map %@ uploaded to server, " + @"\"getmap\" to receive it]", + mapname]; + toserver(msg); } void getmap() { Index: src/clients2c.mm ================================================================== --- src/clients2c.mm +++ src/clients2c.mm @@ -93,19 +93,16 @@ if (!getint(p)) // we are the first client on this server, set // map toservermap = getclientmap(); sgetstr(); - @autoreleasepool { - if (text[0] && - strcmp(text, clientpassword.UTF8String)) { - conoutf(@"you need to set the correct " - @"password " - @"to join this server!"); - disconnect(); - return; - } + if (text[0] && + strcmp(text, clientpassword.UTF8String)) { + conoutf(@"you need to set the correct password " + @"to join this server!"); + disconnect(); + return; } if (getint(p) == 1) conoutf(@"server is FULL, disconnecting.."); break; } @@ -148,13 +145,11 @@ conoutf(@"%@:\f %s", d.name, text); break; case SV_MAPCHANGE: sgetstr(); - @autoreleasepool { - changemapserv(@(text), getint(p)); - } + changemapserv(@(text), getint(p)); mapchanged = true; break; case SV_ITEMLIST: { int n; @@ -376,16 +371,14 @@ case SV_RECVMAP: { sgetstr(); conoutf(@"received map \"%s\" from server, reloading..", text); int mapsize = getint(p); - @autoreleasepool { - OFString *string = @(text); - writemap(string, mapsize, p); - p += mapsize; - changemapserv(string, gamemode); - } + OFString *string = @(text); + writemap(string, mapsize, p); + p += mapsize; + changemapserv(string, gamemode); break; } case SV_SERVMSG: sgetstr(); Index: src/commands.mm ================================================================== --- src/commands.mm +++ src/commands.mm @@ -121,20 +121,17 @@ return NULL; } } char *s = strndup(word, p - word - 1); if (left == '(') { - @autoreleasepool { - OFString *t; - @try { - t = [OFString - stringWithFormat:@"%d", execute(@(s))]; - } @finally { - free(s); - } - s = strdup(t.UTF8String); - } + OFString *t; + @try { + t = [OFString stringWithFormat:@"%d", execute(@(s))]; + } @finally { + free(s); + } + s = strdup(t.UTF8String); } return s; } // parse single argument, including expressions @@ -162,23 +159,20 @@ if (p - word == 0) return NULL; return strndup(word, p - word); } +// find value of ident referenced with $ in exp OFString * -lookup(OFString *n) // find value of ident referenced with $ in exp -{ - @autoreleasepool { - __kindof Identifier *identifier = - identifiers[[n substringFromIndex:1]]; - - if ([identifier isKindOfClass:Variable.class]) { - return [OFString - stringWithFormat:@"%d", *[identifier storage]]; - } else if ([identifier isKindOfClass:Alias.class]) - return [identifier action]; - } +lookup(OFString *n) +{ + __kindof Identifier *identifier = identifiers[[n substringFromIndex:1]]; + + if ([identifier isKindOfClass:Variable.class]) { + return [OFString stringWithFormat:@"%d", *[identifier storage]]; + } else if ([identifier isKindOfClass:Alias.class]) + return [identifier action]; conoutf(@"unknown alias lookup: %@", [n substringFromIndex:1]); return n; } @@ -232,61 +226,59 @@ // all evaluation happens here, recursively int execute(OFString *string, bool isDown) { - @autoreleasepool { - std::unique_ptr copy(strdup(string.UTF8String)); - char *p = copy.get(); - const int MAXWORDS = 25; // limit, remove - OFString *w[MAXWORDS]; - int val = 0; - for (bool cont = true; cont;) { - // for each ; seperated statement - int numargs = MAXWORDS; - loopi(MAXWORDS) - { - // collect all argument values - w[i] = @""; - if (i > numargs) - continue; - // parse and evaluate exps - char *s = parseword(p); - if (!s) { - numargs = i; - s = strdup(""); - } - @try { - if (*s == '$') - // substitute variables - w[i] = lookup(@(s)); - else - w[i] = @(s); - } @finally { - free(s); - } - } - - p += strcspn(p, ";\n\0"); - // more statements if this isn't the end of the string - cont = *p++ != 0; - OFString *c = w[0]; - // strip irc-style command prefix - if ([c hasPrefix:@"/"]) { - c = [c substringFromIndex:1]; - w[0] = c; - } - // empty statement - if (c.length == 0) - continue; - - val = executeIdentifier(identifiers[c], - [OFArray arrayWithObjects:w count:numargs], isDown); - } - - return val; - } + std::unique_ptr copy(strdup(string.UTF8String)); + char *p = copy.get(); + const int MAXWORDS = 25; // limit, remove + OFString *w[MAXWORDS]; + int val = 0; + for (bool cont = true; cont;) { + // for each ; seperated statement + int numargs = MAXWORDS; + loopi(MAXWORDS) + { + // collect all argument values + w[i] = @""; + if (i > numargs) + continue; + // parse and evaluate exps + char *s = parseword(p); + if (!s) { + numargs = i; + s = strdup(""); + } + @try { + if (*s == '$') + // substitute variables + w[i] = lookup(@(s)); + else + w[i] = @(s); + } @finally { + free(s); + } + } + + p += strcspn(p, ";\n\0"); + // more statements if this isn't the end of the string + cont = *p++ != 0; + OFString *c = w[0]; + // strip irc-style command prefix + if ([c hasPrefix:@"/"]) { + c = [c substringFromIndex:1]; + w[0] = c; + } + // empty statement + if (c.length == 0) + continue; + + val = executeIdentifier(identifiers[c], + [OFArray arrayWithObjects:w count:numargs], isDown); + } + + return val; } // tab-completion of all identifiers int completesize = 0, completeidx = 0; @@ -298,68 +290,61 @@ } void complete(OFMutableString *s) { - @autoreleasepool { - if (![s hasPrefix:@"/"]) - [s insertString:@"/" atIndex:0]; - - if (s.length == 1) - return; - - if (!completesize) { - completesize = s.length - 1; - completeidx = 0; - } - - __block int idx = 0; - [identifiers enumerateKeysAndObjectsUsingBlock:^( - OFString *name, Identifier *identifier, bool *stop) { - if (strncmp(identifier.name.UTF8String, - s.UTF8String + 1, completesize) == 0 && - idx++ == completeidx) - [s replaceCharactersInRange:OFMakeRange( - 1, s.length - 1) - withString:identifier.name]; - }]; - - completeidx++; - - if (completeidx >= idx) - completeidx = 0; - } + if (![s hasPrefix:@"/"]) + [s insertString:@"/" atIndex:0]; + + if (s.length == 1) + return; + + if (!completesize) { + completesize = s.length - 1; + completeidx = 0; + } + + __block int idx = 0; + [identifiers enumerateKeysAndObjectsUsingBlock:^( + OFString *name, Identifier *identifier, bool *stop) { + if (strncmp(identifier.name.UTF8String, s.UTF8String + 1, + completesize) == 0 && + idx++ == completeidx) + [s replaceCharactersInRange:OFMakeRange(1, s.length - 1) + withString:identifier.name]; + }]; + + completeidx++; + + if (completeidx >= idx) + completeidx = 0; } bool execfile(OFIRI *cfgfile) { - @autoreleasepool { - OFString *command; - @try { - command = [OFString stringWithContentsOfIRI:cfgfile]; - } @catch (OFOpenItemFailedException *e) { - return false; - } @catch (OFReadFailedException *e) { - return false; - } - - execute(command); - return true; - } + OFString *command; + @try { + command = [OFString stringWithContentsOfIRI:cfgfile]; + } @catch (OFOpenItemFailedException *e) { + return false; + } @catch (OFReadFailedException *e) { + return false; + } + + execute(command); + return true; } void exec(OFString *cfgfile) { - @autoreleasepool { - if (!execfile([Cube.sharedInstance.userDataIRI - IRIByAppendingPathComponent:cfgfile]) && - !execfile([Cube.sharedInstance.gameDataIRI - IRIByAppendingPathComponent:cfgfile])) - conoutf(@"could not read \"%@\"", cfgfile); - } + if (!execfile([Cube.sharedInstance.userDataIRI + IRIByAppendingPathComponent:cfgfile]) && + !execfile([Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:cfgfile])) + conoutf(@"could not read \"%@\"", cfgfile); } void writecfg() { @@ -416,13 +401,11 @@ // trivially. void intset(OFString *name, int v) { - @autoreleasepool { - alias(name, [OFString stringWithFormat:@"%d", v]); - } + alias(name, [OFString stringWithFormat:@"%d", v]); } void ifthen(OFString *cond, OFString *thenp, OFString *elsep) { @@ -430,18 +413,16 @@ } void loopa(OFString *times, OFString *body) { - @autoreleasepool { - int t = times.cube_intValue; - - loopi(t) - { - intset(@"i", i); - execute(body); - } + int t = times.cube_intValue; + + loopi(t) + { + intset(@"i", i); + execute(body); } } void whilea(OFString *cond, OFString *body) @@ -470,36 +451,32 @@ } int listlen(OFString *a_) { - @autoreleasepool { - const char *a = a_.UTF8String; - - if (!*a) - return 0; - - int n = 0; - while (*a) - if (*a++ == ' ') - n++; - - return n + 1; - } + const char *a = a_.UTF8String; + + if (!*a) + return 0; + + int n = 0; + while (*a) + if (*a++ == ' ') + n++; + + return n + 1; } void at(OFString *s_, OFString *pos) { - @autoreleasepool { - int n = pos.cube_intValue; - std::unique_ptr copy(strdup(s_.UTF8String)); - char *s = copy.get(); - loopi(n) s += strspn(s += strcspn(s, " \0"), " "); - s[strcspn(s, " \0")] = 0; - concat(@(s)); - } + int n = pos.cube_intValue; + std::unique_ptr copy(strdup(s_.UTF8String)); + char *s = copy.get(); + loopi(n) s += strspn(s += strcspn(s, " \0"), " "); + s[strcspn(s, " \0")] = 0; + concat(@(s)); } COMMANDN(loop, loopa, ARG_2STR) COMMANDN(while, whilea, ARG_2STR) COMMANDN(if, ifthen, ARG_3STR) Index: src/console.mm ================================================================== --- src/console.mm +++ src/console.mm @@ -81,26 +81,24 @@ } void conoutf(OFConstantString *format, ...) { - @autoreleasepool { - va_list arguments; - va_start(arguments, format); - - OFString *string = [[OFString alloc] initWithFormat:format - arguments:arguments]; - - va_end(arguments); - - int n = 0; - while (string.length > WORDWRAP) { - conline([string substringToIndex:WORDWRAP], n++ != 0); - string = [string substringFromIndex:WORDWRAP]; - } - conline(string, n != 0); - } + va_list arguments; + va_start(arguments, format); + + OFString *string = [[OFString alloc] initWithFormat:format + arguments:arguments]; + + va_end(arguments); + + int n = 0; + while (string.length > WORDWRAP) { + conline([string substringToIndex:WORDWRAP], n++ != 0); + string = [string substringFromIndex:WORDWRAP]; + } + conline(string, n != 0); } // render buffer taking into account time & scrolling void renderconsole() @@ -179,23 +177,19 @@ COMMAND(saycommand, ARG_VARI) void mapmsg(OFString *s) { - @autoreleasepool { - memset(hdr.maptitle, '\0', sizeof(hdr.maptitle)); - strncpy(hdr.maptitle, s.UTF8String, 127); - } + memset(hdr.maptitle, '\0', sizeof(hdr.maptitle)); + strncpy(hdr.maptitle, s.UTF8String, 127); } COMMAND(mapmsg, ARG_1STR) void pasteconsole() { - @autoreleasepool { - [commandbuf appendString:@(SDL_GetClipboardText())]; - } + [commandbuf appendString:@(SDL_GetClipboardText())]; } static OFMutableArray *vhistory; static int histpos = 0; @@ -260,25 +254,21 @@ resetcomplete(); } } else { if (code == SDLK_RETURN) { if (commandbuf.length > 0) { - @autoreleasepool { - if (vhistory == nil) - vhistory = - [[OFMutableArray - alloc] init]; - - if (vhistory.count == 0 || - ![vhistory.lastObject - isEqual:commandbuf]) { - // cap this? - [vhistory - addObject: - [commandbuf - copy]]; - } + if (vhistory == nil) + vhistory = + [[OFMutableArray alloc] + init]; + + if (vhistory.count == 0 || + ![vhistory.lastObject + isEqual:commandbuf]) { + // cap this? + [vhistory addObject:[commandbuf + copy]]; } histpos = vhistory.count; if ([commandbuf hasPrefix:@"/"]) execute(commandbuf, true); else Index: src/editing.mm ================================================================== --- src/editing.mm +++ src/editing.mm @@ -602,15 +602,13 @@ void newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4) { EDITSEL; - @autoreleasepool { - newentity(sel.x, sel.y, (int)player1.o.z, what, - [a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0], - [a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]); - } + newentity(sel.x, sel.y, (int)player1.o.z, what, + [a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0], + [a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]); } COMMANDN(select, selectpos, ARG_4INT) COMMAND(edittag, ARG_1INT) COMMAND(replace, ARG_NONE) Index: src/entities.mm ================================================================== --- src/entities.mm +++ src/entities.mm @@ -40,19 +40,14 @@ entity &e = ents[i]; if (e.type == MAPMODEL) { MapModelInfo *mmi = getmminfo(e.attr2); if (mmi == nil) continue; - @autoreleasepool { - rendermodel(mmi.name, 0, 1, e.attr4, - (float)mmi.rad, e.x, - (float)S(e.x, e.y)->floor + mmi.zoff + - e.attr3, - e.y, - (float)((e.attr1 + 7) - (e.attr1 + 7) % 15), - 0, false, 1.0f, 10.0f, mmi.snap); - } + rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad, + e.x, (float)S(e.x, e.y)->floor + mmi.zoff + e.attr3, + e.y, (float)((e.attr1 + 7) - (e.attr1 + 7) % 15), 0, + false, 1.0f, 10.0f, mmi.snap); } else { if (OUTBORD(e.x, e.y)) continue; if (e.type != CARROT) { if (!e.spawned && e.type != TELEPORT) Index: src/menus.mm ================================================================== --- src/menus.mm +++ src/menus.mm @@ -41,57 +41,54 @@ void refreshservers(); bool rendermenu() { - @autoreleasepool { - if (vmenu < 0) { - [menuStack removeAllObjects]; - return false; - } - - if (vmenu == 1) - refreshservers(); - - Menu *m = menus[vmenu]; - OFString *title; - if (vmenu > 1) - title = - [OFString stringWithFormat:@"[ %@ menu ]", m.name]; - else - title = m.name; - int mdisp = m.items.count; - int w = 0; - loopi(mdisp) - { - int x = text_width(m.items[i].text); - if (x > w) - w = x; - } - int tw = text_width(title); - if (tw > w) - w = tw; - int step = FONTH / 4 * 5; - int h = (mdisp + 2) * step; - int y = (VIRTH - h) / 2; - int x = (VIRTW - w) / 2; - blendbox(x - FONTH / 2 * 3, y - FONTH, x + w + FONTH / 2 * 3, - y + h + FONTH, true); - draw_text(title, x, y, 2); - y += FONTH * 2; - if (vmenu) { - int bh = y + m.menusel * step; - blendbox(x - FONTH, bh - 10, x + w + FONTH, - bh + FONTH + 10, false); - } - loopj(mdisp) - { - draw_text(m.items[j].text, x, y, 2); - y += step; - } - return true; - } + if (vmenu < 0) { + [menuStack removeAllObjects]; + return false; + } + + if (vmenu == 1) + refreshservers(); + + Menu *m = menus[vmenu]; + OFString *title; + if (vmenu > 1) + title = [OFString stringWithFormat:@"[ %@ menu ]", m.name]; + else + title = m.name; + int mdisp = m.items.count; + int w = 0; + loopi(mdisp) + { + int x = text_width(m.items[i].text); + if (x > w) + w = x; + } + int tw = text_width(title); + if (tw > w) + w = tw; + int step = FONTH / 4 * 5; + int h = (mdisp + 2) * step; + int y = (VIRTH - h) / 2; + int x = (VIRTW - w) / 2; + blendbox(x - FONTH / 2 * 3, y - FONTH, x + w + FONTH / 2 * 3, + y + h + FONTH, true); + draw_text(title, x, y, 2); + y += FONTH * 2; + if (vmenu) { + int bh = y + m.menusel * step; + blendbox( + x - FONTH, bh - 10, x + w + FONTH, bh + FONTH + 10, false); + } + loopj(mdisp) + { + draw_text(m.items[j].text, x, y, 2); + y += step; + } + return true; } void newmenu(OFString *name) { @@ -152,15 +149,12 @@ menusel = 0; menus[vmenu].menusel = menusel; } else { if (code == SDLK_RETURN || code == -2) { OFString *action = menus[vmenu].items[menusel].action; - if (vmenu == 1) { - @autoreleasepool { - connects(getservername(menusel)); - } - } + if (vmenu == 1) + connects(getservername(menusel)); if (menuStack == nil) menuStack = [[OFMutableArray alloc] init]; [menuStack addObject:@(vmenu)]; Index: src/renderextras.mm ================================================================== --- src/renderextras.mm +++ src/renderextras.mm @@ -201,38 +201,35 @@ } void loadsky(OFString *basename) { - @autoreleasepool { - static OFString *lastsky = @""; - - basename = [basename stringByReplacingOccurrencesOfString:@"\\" - withString:@"/"]; - - if ([lastsky isEqual:basename]) - return; - - static const OFString *side[] = { @"ft", @"bk", @"lf", @"rt", - @"dn", @"up" }; - int texnum = 14; - loopi(6) - { - OFString *path = - [OFString stringWithFormat:@"packages/%@_%@.jpg", - basename, side[i]]; - - int xs, ys; - if (!installtex(texnum + i, - [Cube.sharedInstance.gameDataIRI - IRIByAppendingPathComponent:path], - &xs, &ys, true)) - conoutf(@"could not load sky textures"); - } - - lastsky = basename; - } + static OFString *lastsky = @""; + + basename = [basename stringByReplacingOccurrencesOfString:@"\\" + withString:@"/"]; + + if ([lastsky isEqual:basename]) + return; + + static const OFString *side[] = { @"ft", @"bk", @"lf", @"rt", @"dn", + @"up" }; + int texnum = 14; + loopi(6) + { + OFString *path = [OFString + stringWithFormat:@"packages/%@_%@.jpg", basename, side[i]]; + + int xs, ys; + if (!installtex(texnum + i, + [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path], + &xs, &ys, true)) + conoutf(@"could not load sky textures"); + } + + lastsky = basename; } COMMAND(loadsky, ARG_1STR) float cursordepth = 0.9f; GLint viewport[4]; @@ -365,21 +362,19 @@ dblend = 0; } glEnable(GL_TEXTURE_2D); - @autoreleasepool { - OFString *command = getcurcommand(); - OFString *player = playerincrosshair(); - - if (command) - draw_textf(@"> %@_", 20, 1570, 2, command); - else if (closeent.length > 0) - draw_text(closeent, 20, 1570, 2); - else if (player != nil) - draw_text(player, 20, 1570, 2); - } + OFString *command = getcurcommand(); + OFString *player = playerincrosshair(); + + if (command) + draw_textf(@"> %@_", 20, 1570, 2, command); + else if (closeent.length > 0) + draw_text(closeent, 20, 1570, 2); + else if (player != nil) + draw_text(player, 20, 1570, 2); renderscores(); if (!rendermenu()) { glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, 1); Index: src/rendergl.mm ================================================================== --- src/rendergl.mm +++ src/rendergl.mm @@ -76,92 +76,87 @@ } bool installtex(int tnum, OFIRI *IRI, int *xs, int *ys, bool clamp) { - @autoreleasepool { - SDL_Surface *s = - IMG_Load(IRI.fileSystemRepresentation.UTF8String); - if (s == NULL) { - conoutf(@"couldn't load texture %@", IRI.string); - return false; - } - - if (s->format->BitsPerPixel != 24) { - SDL_PixelFormat *format = - SDL_AllocFormat(SDL_PIXELFORMAT_RGB24); - if (format == NULL) { - conoutf( - @"texture cannot be converted to 24bpp: %@", - IRI.string); - return false; - } - - @try { - SDL_Surface *converted = - SDL_ConvertSurface(s, format, 0); - if (converted == NULL) { - conoutf(@"texture cannot be converted " - @"to 24bpp: %@", - IRI.string); - return false; - } - - SDL_FreeSurface(s); - s = converted; - } @finally { - SDL_FreeFormat(format); - } - } + SDL_Surface *s = IMG_Load(IRI.fileSystemRepresentation.UTF8String); + if (s == NULL) { + conoutf(@"couldn't load texture %@", IRI.string); + return false; + } + + if (s->format->BitsPerPixel != 24) { + SDL_PixelFormat *format = + SDL_AllocFormat(SDL_PIXELFORMAT_RGB24); + if (format == NULL) { + conoutf(@"texture cannot be converted to 24bpp: %@", + IRI.string); + return false; + } + + @try { + SDL_Surface *converted = + SDL_ConvertSurface(s, format, 0); + if (converted == NULL) { + conoutf(@"texture cannot be converted " + @"to 24bpp: %@", + IRI.string); + return false; + } + + SDL_FreeSurface(s); + s = converted; + } @finally { + SDL_FreeFormat(format); + } + } #if 0 loopi(s->w * s->h * 3) { uchar *p = (uchar *)s->pixels + i; *p = 255 - *p; } #endif - glBindTexture(GL_TEXTURE_2D, tnum); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_LINEAR_MIPMAP_LINEAR); // NEAREST); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - *xs = s->w; - *ys = s->h; - while (*xs > glmaxtexsize || *ys > glmaxtexsize) { - *xs /= 2; - *ys /= 2; - } - - void *scaledimg = s->pixels; - - if (*xs != s->w) { - conoutf(@"warning: quality loss: scaling %@", - IRI.string); // for voodoo cards under linux - scaledimg = OFAllocMemory(1, *xs * *ys * 3); - gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, - s->pixels, *xs, *ys, GL_UNSIGNED_BYTE, scaledimg); - } - - if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, *xs, *ys, GL_RGB, - GL_UNSIGNED_BYTE, scaledimg)) - fatal(@"could not build mipmaps"); - - if (*xs != s->w) - free(scaledimg); - - SDL_FreeSurface(s); - - return true; - } + glBindTexture(GL_TEXTURE_2D, tnum); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); // NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + *xs = s->w; + *ys = s->h; + while (*xs > glmaxtexsize || *ys > glmaxtexsize) { + *xs /= 2; + *ys /= 2; + } + + void *scaledimg = s->pixels; + + if (*xs != s->w) { + conoutf(@"warning: quality loss: scaling %@", + IRI.string); // for voodoo cards under linux + scaledimg = OFAllocMemory(1, *xs * *ys * 3); + gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, s->pixels, + *xs, *ys, GL_UNSIGNED_BYTE, scaledimg); + } + + if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, *xs, *ys, GL_RGB, + GL_UNSIGNED_BYTE, scaledimg)) + fatal(@"could not build mipmaps"); + + if (*xs != s->w) + free(scaledimg); + + SDL_FreeSurface(s); + + return true; } // management of texture slots // each texture slot can have multople texture frames, of which currently only // the first is used additional frames can be used for various shaders @@ -195,21 +190,18 @@ COMMAND(texturereset, ARG_NONE) void texture(OFString *aframe, OFString *name) { - @autoreleasepool { - int num = curtexnum++, frame = aframe.cube_intValue; - - if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES) - return; - - mapping[num][frame] = 1; - mapname[num][frame] = - [name stringByReplacingOccurrencesOfString:@"\\" - withString:@"/"]; - } + int num = curtexnum++, frame = aframe.cube_intValue; + + if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES) + return; + + mapping[num][frame] = 1; + mapname[num][frame] = [name stringByReplacingOccurrencesOfString:@"\\" + withString:@"/"]; } COMMAND(texture, ARG_2STR) int lookuptexture(int tex, int *xs, int *ys) @@ -241,26 +233,24 @@ fatal(@"loaded too many textures"); int tnum = curtex + FIRSTTEX; texname[curtex] = mapname[tex][frame]; - @autoreleasepool { - OFString *path = - [OFString stringWithFormat:@"packages/%@", texname[curtex]]; - - if (installtex(tnum, - [Cube.sharedInstance.gameDataIRI - IRIByAppendingPathComponent:path], - xs, ys, false)) { - mapping[tex][frame] = tnum; - texx[curtex] = *xs; - texy[curtex] = *ys; - curtex++; - return tnum; - } else { - return mapping[tex][frame] = FIRSTTEX; // temp fix - } + OFString *path = + [OFString stringWithFormat:@"packages/%@", texname[curtex]]; + + if (installtex(tnum, + [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path], + xs, ys, false)) { + mapping[tex][frame] = tnum; + texx[curtex] = *xs; + texy[curtex] = *ys; + curtex++; + return tnum; + } else { + return mapping[tex][frame] = FIRSTTEX; // temp fix } } void setupworld() Index: src/rendermd2.mm ================================================================== --- src/rendermd2.mm +++ src/rendermd2.mm @@ -14,56 +14,46 @@ void delayedload(MD2 *m) { if (!m.loaded) { - @autoreleasepool { - OFString *path = [OFString - stringWithFormat:@"packages/models/%@", m.loadname]; - OFIRI *baseIRI = [Cube.sharedInstance.gameDataIRI - IRIByAppendingPathComponent:path]; - - OFIRI *IRI1 = - [baseIRI IRIByAppendingPathComponent:@"tris.md2"]; - if (![m loadWithIRI:IRI1]) - fatal(@"loadmodel: ", IRI1.string); - - OFIRI *IRI2 = - [baseIRI IRIByAppendingPathComponent:@"skin.jpg"]; - int xs, ys; - installtex(FIRSTMDL + m.mdlnum, IRI2, &xs, &ys, false); - m.loaded = true; - } + OFString *path = [OFString + stringWithFormat:@"packages/models/%@", m.loadname]; + OFIRI *baseIRI = [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path]; + + OFIRI *IRI1 = [baseIRI IRIByAppendingPathComponent:@"tris.md2"]; + if (![m loadWithIRI:IRI1]) + fatal(@"loadmodel: ", IRI1.string); + + OFIRI *IRI2 = [baseIRI IRIByAppendingPathComponent:@"skin.jpg"]; + int xs, ys; + installtex(FIRSTMDL + m.mdlnum, IRI2, &xs, &ys, false); + m.loaded = true; } } MD2 * loadmodel(OFString *name) { - @autoreleasepool { - static int modelnum = 0; - - MD2 *m = mdllookup[name]; - if (m != nil) - return m; - - m = [[MD2 alloc] init]; - m.mdlnum = modelnum++; - m.mmi = [[MapModelInfo alloc] initWithRad:2 - h:2 - zoff:0 - snap:0 - name:@""]; - m.loadname = name; - - if (mdllookup == nil) - mdllookup = [[OFMutableDictionary alloc] init]; - - mdllookup[name] = m; - - return m; - } + static int modelnum = 0; + + MD2 *m = mdllookup[name]; + if (m != nil) + return m; + + m = [[MD2 alloc] init]; + m.mdlnum = modelnum++; + m.mmi = [[MapModelInfo alloc] initWithRad:2 h:2 zoff:0 snap:0 name:@""]; + m.loadname = name; + + if (mdllookup == nil) + mdllookup = [[OFMutableDictionary alloc] init]; + + mdllookup[name] = m; + + return m; } void mapmodel( OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name) Index: src/rendertext.mm ================================================================== --- src/rendertext.mm +++ src/rendertext.mm @@ -100,118 +100,110 @@ }; int text_width(OFString *string) { - @autoreleasepool { - const char *str = string.UTF8String; - size_t len = string.UTF8StringLength; - - int x = 0; - for (int i = 0; i < len; i++) { - int c = str[i]; - if (c == '\t') { - x = (x + PIXELTAB) / PIXELTAB * PIXELTAB; - continue; - } - - if (c == '\f') - continue; - - if (c == ' ') { - x += FONTH / 2; - continue; - } - - c -= 33; - if (c < 0 || c >= 95) - continue; - - int in_width = char_coords[c][2] - char_coords[c][0]; - x += in_width + 1; - } - - return x; - } + const char *str = string.UTF8String; + size_t len = string.UTF8StringLength; + + int x = 0; + for (int i = 0; i < len; i++) { + int c = str[i]; + if (c == '\t') { + x = (x + PIXELTAB) / PIXELTAB * PIXELTAB; + continue; + } + + if (c == '\f') + continue; + + if (c == ' ') { + x += FONTH / 2; + continue; + } + + c -= 33; + if (c < 0 || c >= 95) + continue; + + int in_width = char_coords[c][2] - char_coords[c][0]; + x += in_width + 1; + } + + return x; } void draw_textf(OFConstantString *format, int left, int top, int gl_num, ...) { - @autoreleasepool { - va_list arguments; - va_start(arguments, gl_num); - OFString *str = [[OFString alloc] initWithFormat:format - arguments:arguments]; - va_end(arguments); - draw_text(str, left, top, gl_num); - } + va_list arguments; + va_start(arguments, gl_num); + OFString *str = [[OFString alloc] initWithFormat:format + arguments:arguments]; + va_end(arguments); + draw_text(str, left, top, gl_num); } void draw_text(OFString *string, int left, int top, int gl_num) { - @autoreleasepool { - glBlendFunc(GL_ONE, GL_ONE); - glBindTexture(GL_TEXTURE_2D, gl_num); - glColor3ub(255, 255, 255); - - int x = left; - int y = top; - - int i; - float in_left, in_top, in_right, in_bottom; - int in_width, in_height; - - const char *str = string.UTF8String; - size_t len = string.UTF8StringLength; - for (i = 0; i < len; i++) { - int c = str[i]; - - if (c == '\t') { - x = (x - left + PIXELTAB) / PIXELTAB * - PIXELTAB + - left; - continue; - } - - if (c == '\f') { - glColor3ub(64, 255, 128); - continue; - } - - if (c == ' ') { - x += FONTH / 2; - continue; - } - - c -= 33; - if (c < 0 || c >= 95) - continue; - - in_left = ((float)char_coords[c][0]) / 512.0f; - in_top = ((float)char_coords[c][1] + 2) / 512.0f; - in_right = ((float)char_coords[c][2]) / 512.0f; - in_bottom = ((float)char_coords[c][3] - 2) / 512.0f; - - in_width = char_coords[c][2] - char_coords[c][0]; - in_height = char_coords[c][3] - char_coords[c][1]; - - glBegin(GL_QUADS); - glTexCoord2f(in_left, in_top); - glVertex2i(x, y); - glTexCoord2f(in_right, in_top); - glVertex2i(x + in_width, y); - glTexCoord2f(in_right, in_bottom); - glVertex2i(x + in_width, y + in_height); - glTexCoord2f(in_left, in_bottom); - glVertex2i(x, y + in_height); - glEnd(); - - xtraverts += 4; - x += in_width + 1; - } + glBlendFunc(GL_ONE, GL_ONE); + glBindTexture(GL_TEXTURE_2D, gl_num); + glColor3ub(255, 255, 255); + + int x = left; + int y = top; + + int i; + float in_left, in_top, in_right, in_bottom; + int in_width, in_height; + + const char *str = string.UTF8String; + size_t len = string.UTF8StringLength; + for (i = 0; i < len; i++) { + int c = str[i]; + + if (c == '\t') { + x = (x - left + PIXELTAB) / PIXELTAB * PIXELTAB + left; + continue; + } + + if (c == '\f') { + glColor3ub(64, 255, 128); + continue; + } + + if (c == ' ') { + x += FONTH / 2; + continue; + } + + c -= 33; + if (c < 0 || c >= 95) + continue; + + in_left = ((float)char_coords[c][0]) / 512.0f; + in_top = ((float)char_coords[c][1] + 2) / 512.0f; + in_right = ((float)char_coords[c][2]) / 512.0f; + in_bottom = ((float)char_coords[c][3] - 2) / 512.0f; + + in_width = char_coords[c][2] - char_coords[c][0]; + in_height = char_coords[c][3] - char_coords[c][1]; + + glBegin(GL_QUADS); + glTexCoord2f(in_left, in_top); + glVertex2i(x, y); + glTexCoord2f(in_right, in_top); + glVertex2i(x + in_width, y); + glTexCoord2f(in_right, in_bottom); + glVertex2i(x + in_width, y + in_height); + glTexCoord2f(in_left, in_bottom); + glVertex2i(x, y + in_height); + glEnd(); + + xtraverts += 4; + x += in_width + 1; } } // also Don's code, so goes in here too :) Index: src/savegamedemo.mm ================================================================== --- src/savegamedemo.mm +++ src/savegamedemo.mm @@ -89,44 +89,42 @@ } void savestate(OFIRI *IRI) { - @autoreleasepool { - stop(); - f = gzopen([IRI.fileSystemRepresentation - cStringWithEncoding:OFLocale.encoding], - "wb9"); - if (!f) { - conoutf(@"could not write %@", IRI.string); - return; - } - gzwrite(f, (void *)"CUBESAVE", 8); - gzputc(f, islittleendian); - gzputi(SAVEGAMEVERSION); - OFData *data = [player1 dataBySerializing]; - gzputi(data.count); - char map[_MAXDEFSTR] = { 0 }; - memcpy(map, getclientmap().UTF8String, - min(getclientmap().UTF8StringLength, _MAXDEFSTR - 1)); - gzwrite(f, map, _MAXDEFSTR); - gzputi(gamemode); - gzputi(ents.length()); - loopv(ents) gzputc(f, ents[i].spawned); - gzwrite(f, data.items, data.count); - OFArray *monsters = getmonsters(); - gzputi(monsters.count); - for (DynamicEntity *monster in monsters) { - data = [monster dataBySerializing]; - gzwrite(f, data.items, data.count); - } - gzputi(players.count); - for (id player in players) { - gzput(player == [OFNull null]); - data = [player dataBySerializing]; - gzwrite(f, data.items, data.count); - } + stop(); + f = gzopen([IRI.fileSystemRepresentation + cStringWithEncoding:OFLocale.encoding], + "wb9"); + if (!f) { + conoutf(@"could not write %@", IRI.string); + return; + } + gzwrite(f, (void *)"CUBESAVE", 8); + gzputc(f, islittleendian); + gzputi(SAVEGAMEVERSION); + OFData *data = [player1 dataBySerializing]; + gzputi(data.count); + char map[_MAXDEFSTR] = { 0 }; + memcpy(map, getclientmap().UTF8String, + min(getclientmap().UTF8StringLength, _MAXDEFSTR - 1)); + gzwrite(f, map, _MAXDEFSTR); + gzputi(gamemode); + gzputi(ents.length()); + loopv(ents) gzputc(f, ents[i].spawned); + gzwrite(f, data.items, data.count); + OFArray *monsters = getmonsters(); + gzputi(monsters.count); + for (DynamicEntity *monster in monsters) { + data = [monster dataBySerializing]; + gzwrite(f, data.items, data.count); + } + gzputi(players.count); + for (id player in players) { + gzput(player == [OFNull null]); + data = [player dataBySerializing]; + gzwrite(f, data.items, data.count); } } void savegame(OFString *name) @@ -134,74 +132,64 @@ if (!m_classicsp) { conoutf(@"can only save classic sp games"); return; } - @autoreleasepool { - OFString *path = - [OFString stringWithFormat:@"savegames/%@.csgz", name]; - OFIRI *IRI = [Cube.sharedInstance.userDataIRI - IRIByAppendingPathComponent:path]; - savestate(IRI); - stop(); - conoutf(@"wrote %@", IRI.string); - } + OFString *path = [OFString stringWithFormat:@"savegames/%@.csgz", name]; + OFIRI *IRI = + [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent:path]; + savestate(IRI); + stop(); + conoutf(@"wrote %@", IRI.string); } COMMAND(savegame, ARG_1STR) void loadstate(OFIRI *IRI) { - @autoreleasepool { - stop(); - if (multiplayer()) - return; - f = gzopen([IRI.fileSystemRepresentation - cStringWithEncoding:OFLocale.encoding], - "rb9"); - if (!f) { - conoutf(@"could not open %@", IRI.string); - return; - } - - char mapname[_MAXDEFSTR] = { 0 }; - char buf[8]; - gzread(f, buf, 8); - if (strncmp(buf, "CUBESAVE", 8)) - goto out; - if (gzgetc(f) != islittleendian) - goto out; // not supporting save->load accross - // incompatible architectures simpifies things - // a LOT - if (gzgeti() != SAVEGAMEVERSION || - gzgeti() != DynamicEntity.serializedSize) - goto out; - gzread(f, mapname, _MAXDEFSTR); - nextmode = gzgeti(); - @autoreleasepool { - // continue below once map has been loaded and client & - // server have updated - changemap(@(mapname)); - } - return; - out: - conoutf(@"aborting: savegame/demo from a different version of " - @"cube or cpu architecture"); - stop(); - } + stop(); + if (multiplayer()) + return; + f = gzopen([IRI.fileSystemRepresentation + cStringWithEncoding:OFLocale.encoding], + "rb9"); + if (!f) { + conoutf(@"could not open %@", IRI.string); + return; + } + + char mapname[_MAXDEFSTR] = { 0 }; + char buf[8]; + gzread(f, buf, 8); + if (strncmp(buf, "CUBESAVE", 8)) + goto out; + if (gzgetc(f) != islittleendian) + goto out; // not supporting save->load accross + // incompatible architectures simpifies things + // a LOT + if (gzgeti() != SAVEGAMEVERSION || + gzgeti() != DynamicEntity.serializedSize) + goto out; + gzread(f, mapname, _MAXDEFSTR); + nextmode = gzgeti(); + // continue below once map has been loaded and client & server + // have updated + changemap(@(mapname)); + return; +out: + conoutf(@"aborting: savegame/demo from a different version of " + @"cube or cpu architecture"); + stop(); } void loadgame(OFString *name) { - @autoreleasepool { - OFString *path = - [OFString stringWithFormat:@"savegames/%@.csgz", name]; - OFIRI *IRI = [Cube.sharedInstance.userDataIRI - IRIByAppendingPathComponent:path]; - loadstate(IRI); - } + OFString *path = [OFString stringWithFormat:@"savegames/%@.csgz", name]; + OFIRI *IRI = + [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent:path]; + loadstate(IRI); } COMMAND(loadgame, ARG_1STR) void loadgameout() @@ -284,22 +272,19 @@ int cn = getclientnum(); if (cn < 0) return; - @autoreleasepool { - OFString *path = - [OFString stringWithFormat:@"demos/%@.cdgz", name]; - OFIRI *IRI = [Cube.sharedInstance.userDataIRI - IRIByAppendingPathComponent:path]; - savestate(IRI); - gzputi(cn); - conoutf(@"started recording demo to %@", IRI.string); - demorecording = true; - starttime = lastmillis; - ddamage = bdamage = 0; - } + OFString *path = [OFString stringWithFormat:@"demos/%@.cdgz", name]; + OFIRI *IRI = + [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent:path]; + savestate(IRI); + gzputi(cn); + conoutf(@"started recording demo to %@", IRI.string); + demorecording = true; + starttime = lastmillis; + ddamage = bdamage = 0; } COMMAND(record, ARG_1STR) void demodamage(int damage, const OFVector3D &o) @@ -346,18 +331,15 @@ } void demo(OFString *name) { - @autoreleasepool { - OFString *path = - [OFString stringWithFormat:@"demos/%@.cdgz", name]; - OFIRI *IRI = [Cube.sharedInstance.userDataIRI - IRIByAppendingPathComponent:path]; - loadstate(IRI); - demoloading = true; - } + OFString *path = [OFString stringWithFormat:@"demos/%@.cdgz", name]; + OFIRI *IRI = + [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent:path]; + loadstate(IRI); + demoloading = true; } COMMAND(demo, ARG_1STR) void stopreset() Index: src/server.mm ================================================================== --- src/server.mm +++ src/server.mm @@ -171,17 +171,14 @@ } if (yes == 1 && no == 0) return true; // single player - @autoreleasepool { - OFString *msg = - [OFString stringWithFormat: - @"%@ suggests %@ on map %@ (set map to vote)", - clients[sender].name, modestr(reqmode), map]; - sendservmsg(msg); - } + OFString *msg = [OFString + stringWithFormat:@"%@ suggests %@ on map %@ (set map to vote)", + clients[sender].name, modestr(reqmode), map]; + sendservmsg(msg); if (yes / (float)(yes + no) <= 0.5f) return false; sendservmsg(@"vote passed"); @@ -213,35 +210,29 @@ sgetstr(); break; case SV_INITC2S: sgetstr(); - @autoreleasepool { - clients[cn].name = @(text); - } + clients[cn].name = @(text); sgetstr(); getint(p); break; case SV_MAPCHANGE: { sgetstr(); int reqmode = getint(p); if (reqmode < 0) reqmode = 0; - @autoreleasepool { - if (smapname.length > 0 && !mapreload && - !vote(@(text), reqmode, sender)) - return; - } + 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; - @autoreleasepool { - smapname = @(text); - } + smapname = @(text); resetitems(); sender = -1; break; } @@ -282,13 +273,11 @@ } case SV_SENDMAP: { sgetstr(); int mapsize = getint(p); - @autoreleasepool { - sendmaps(sender, @(text), mapsize, p); - } + sendmaps(sender, @(text), mapsize, p); return; } case SV_RECVMAP: send(sender, recvmap(sender)); @@ -327,13 +316,11 @@ uchar *start = packet->data; uchar *p = start + 2; putint(p, SV_INITS2C); putint(p, n); putint(p, PROTOCOL_VERSION); - @autoreleasepool { - putint(p, *smapname.UTF8String); - } + putint(p, *smapname.UTF8String); sendstring(serverpassword, p); putint(p, clients.count > maxclients); if (smapname.length > 0) { putint(p, SV_MAPCHANGE); sendstring(smapname, p); @@ -491,17 +478,14 @@ Client *c = addclient(); c.type = ST_TCPIP; c.peer = event.peer; c.peer->data = (void *)(clients.count - 1); char hn[1024]; - @autoreleasepool { - c.hostname = - (enet_address_get_host( - &c.peer->address, hn, sizeof(hn)) == 0 - ? @(hn) - : @"localhost"); - } + c.hostname = (enet_address_get_host( + &c.peer->address, hn, sizeof(hn)) == 0 + ? @(hn) + : @"localhost"); [OFStdOut writeFormat:@"client connected (%@)\n", c.hostname]; send_welcome(lastconnect = clients.count - 1); break; } @@ -564,15 +548,13 @@ servermsinit(master ? master : @"wouter.fov120.com/cube/masterserver/", sdesc, dedicated); if ((isdedicated = dedicated)) { ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT }; - @autoreleasepool { - if (ip.length > 0 && - enet_address_set_host(&address, ip.UTF8String) < 0) - printf("WARNING: server ip not resolved"); - } + 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; } @@ -587,8 +569,11 @@ printf("dedicated server started, waiting for " "clients...\nCtrl-C to exit\n\n"); atexit(cleanupserver); atexit(enet_deinitialize); for (;;) - serverslice(/*enet_time_get_sec()*/ time(NULL), 5); + @autoreleasepool { + serverslice( + /*enet_time_get_sec()*/ time(NULL), 5); + } } } Index: src/serverbrowser.mm ================================================================== --- src/serverbrowser.mm +++ src/serverbrowser.mm @@ -178,21 +178,18 @@ } void addserver(OFString *servername) { - @autoreleasepool { - for (ServerInfo *si in servers) - if ([si.name isEqual:servername]) - return; - - if (servers == nil) - servers = [[OFMutableArray alloc] init]; - - [servers - addObject:[[ServerInfo alloc] initWithName:servername]]; - } + for (ServerInfo *si in servers) + if ([si.name isEqual:servername]) + return; + + if (servers == nil) + servers = [[OFMutableArray alloc] init]; + + [servers addObject:[[ServerInfo alloc] initWithName:servername]]; } void pingservers() { @@ -258,17 +255,13 @@ si.ping = 9998; si.mode = getint(p); si.numplayers = getint(p); si.minremain = getint(p); sgetstr(); - @autoreleasepool { - si.map = @(text); - } + si.map = @(text); sgetstr(); - @autoreleasepool { - si.sdesc = @(text); - } + si.sdesc = @(text); break; } } } } @@ -304,14 +297,12 @@ ? @"%@ [waiting for server response]" : @"%@ [unknown host]\t"), si.name]; // cut off too long server descriptions - @autoreleasepool { - if (si.full.length > 50) - si.full = [si.full substringToIndex:50]; - } + if (si.full.length > 50) + si.full = [si.full substringToIndex:50]; menumanual(1, i, si.full); if (!--maxmenu) return; @@ -346,13 +337,11 @@ if (!*reply || strstr((char *)reply, "") || strstr((char *)reply, "")) conoutf(@"master server not replying"); else { [servers removeAllObjects]; - @autoreleasepool { - execute(@((char *)reply)); - } + execute(@((char *)reply)); } servermenu(); } COMMAND(addserver, ARG_1STR) @@ -364,11 +353,9 @@ { FILE *f = fopen("servers.cfg", "w"); if (!f) return; fprintf(f, "// servers connected to are added here automatically\n\n"); - @autoreleasepool { - for (ServerInfo *si in servers.reversedArray) - fprintf(f, "addserver %s\n", si.name.UTF8String); - } + for (ServerInfo *si in servers.reversedArray) + fprintf(f, "addserver %s\n", si.name.UTF8String); fclose(f); } Index: src/serverms.mm ================================================================== --- src/serverms.mm +++ src/serverms.mm @@ -8,13 +8,11 @@ httpgetsend(ENetAddress &ad, OFString *hostname, OFString *req, OFString *ref, OFString *agent) { if (ad.host == ENET_HOST_ANY) { [OFStdOut writeFormat:@"looking up %@...\n", hostname]; - @autoreleasepool { - enet_address_set_host(&ad, hostname.UTF8String); - } + enet_address_set_host(&ad, hostname.UTF8String); if (ad.host == ENET_HOST_ANY) return; } if (mssock != ENET_SOCKET_NULL) enet_socket_destroy(mssock); @@ -77,17 +75,14 @@ static void updatemasterserver(int seconds) { // send alive signal to masterserver every hour of uptime if (seconds > updmaster) { - @autoreleasepool { - OFString *path = [OFString - stringWithFormat:@"%@register.do?action=add", - masterpath]; - httpgetsend(masterserver, masterbase, path, - @"cubeserver", @"Cube Server"); - } + OFString *path = [OFString + stringWithFormat:@"%@register.do?action=add", masterpath]; + httpgetsend(masterserver, masterbase, path, @"cubeserver", + @"Cube Server"); masterrep[0] = 0; masterb.data = masterrep; masterb.dataLength = MAXTRANS - 1; updmaster = seconds + 60 * 60; } @@ -103,16 +98,14 @@ } uchar * retrieveservers(uchar *buf, int buflen) { - @autoreleasepool { - OFString *path = [OFString - stringWithFormat:@"%@retrieve.do?item=list", masterpath]; - httpgetsend(masterserver, masterbase, path, @"cubeserver", - @"Cube Server"); - } + OFString *path = + [OFString stringWithFormat:@"%@retrieve.do?item=list", masterpath]; + httpgetsend( + masterserver, masterbase, path, @"cubeserver", @"Cube Server"); ENetBuffer eb; buf[0] = 0; eb.data = buf; eb.dataLength = buflen - 1; while (mssock != ENET_SOCKET_NULL) @@ -158,25 +151,22 @@ } void servermsinit(OFString *master_, OFString *sdesc, bool listen) { - @autoreleasepool { - const char *master = master_.UTF8String; - const char *mid = strstr(master, "/"); - if (!mid) - mid = master; - masterpath = @(mid); - masterbase = [[OFString alloc] initWithUTF8String:master - length:mid - master]; - 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"); - } + const char *master = master_.UTF8String; + const char *mid = strstr(master, "/"); + if (!mid) + mid = master; + masterpath = @(mid); + masterbase = [[OFString alloc] initWithUTF8String:master + length:mid - master]; + 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 @@ -43,18 +43,16 @@ } void sendstring(OFString *t_, uchar *&p) { - @autoreleasepool { - const char *t = t_.UTF8String; - - for (size_t i = 0; i < _MAXDEFSTR && *t != '\0'; i++) - putint(p, *t++); - - putint(p, 0); - } + 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", Index: src/sound.mm ================================================================== --- src/sound.mm +++ src/sound.mm @@ -85,47 +85,41 @@ { if (nosound) return; stopsound(); if (soundvol && musicvol) { - @autoreleasepool { - name = [name stringByReplacingOccurrencesOfString:@"\\" - withString:@"/"]; - OFString *path = - [OFString stringWithFormat:@"packages/%@", name]; - OFIRI *IRI = [Cube.sharedInstance.gameDataIRI - IRIByAppendingPathComponent:path]; - -#ifdef USE_MIXER - if ((mod = Mix_LoadMUS( - IRI.fileSystemRepresentation.UTF8String)) != - NULL) { - Mix_PlayMusic(mod, -1); - Mix_VolumeMusic((musicvol * MAXVOL) / 255); - } -#else - if ((mod = FMUSIC_LoadSong( - IRI.fileSystemRepresentation.UTF8String)) != - NULL) { - FMUSIC_PlaySong(mod); - FMUSIC_SetMasterVolume(mod, musicvol); - } else if (stream = FSOUND_Stream_Open( - IRI.fileSystemRepresentation.UTF8String, - FSOUND_LOOP_NORMAL, 0, 0)) { - int chan = - FSOUND_Stream_Play(FSOUND_FREE, stream); - if (chan >= 0) { - FSOUND_SetVolume( - chan, (musicvol * MAXVOL) / 255); - FSOUND_SetPaused(chan, false); - } - } else { - conoutf( - @"could not play music: %@", IRI.string); - } -#endif - } + name = [name stringByReplacingOccurrencesOfString:@"\\" + withString:@"/"]; + OFString *path = + [OFString stringWithFormat:@"packages/%@", name]; + OFIRI *IRI = [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path]; + +#ifdef USE_MIXER + if ((mod = Mix_LoadMUS( + IRI.fileSystemRepresentation.UTF8String)) != NULL) { + Mix_PlayMusic(mod, -1); + Mix_VolumeMusic((musicvol * MAXVOL) / 255); + } +#else + if ((mod = FMUSIC_LoadSong( + IRI.fileSystemRepresentation.UTF8String)) != NULL) { + FMUSIC_PlaySong(mod); + FMUSIC_SetMasterVolume(mod, musicvol); + } else if (stream = FSOUND_Stream_Open( + IRI.fileSystemRepresentation.UTF8String, + FSOUND_LOOP_NORMAL, 0, 0)) { + int chan = FSOUND_Stream_Play(FSOUND_FREE, stream); + if (chan >= 0) { + FSOUND_SetVolume( + chan, (musicvol * MAXVOL) / 255); + FSOUND_SetPaused(chan, false); + } + } else { + conoutf(@"could not play music: %@", IRI.string); + } +#endif } } COMMAND(music, ARG_1STR) #ifdef USE_MIXER Index: src/world.mm ================================================================== --- src/world.mm +++ src/world.mm @@ -65,17 +65,15 @@ settag(tag, type); if (!savegame && type != 3) playsound(S_RUMBLE); - @autoreleasepool { - OFString *aliasname = - [OFString stringWithFormat:@"level_trigger_%d", tag]; + OFString *aliasname = + [OFString stringWithFormat:@"level_trigger_%d", tag]; - if (identexists(aliasname)) - execute(aliasname); - } + if (identexists(aliasname)) + execute(aliasname); if (type == 2) endsp(false); } COMMAND(trigger, ARG_2INT) @@ -304,27 +302,23 @@ if (e < 0) { conoutf(@"no more entities"); return; } int t = ents[e].type; - @autoreleasepool { - conoutf(@"%@ entity deleted", entnames[t]); - } + conoutf(@"%@ entity deleted", entnames[t]); ents[e].type = NOTUSED; addmsg(1, 10, SV_EDITENT, e, NOTUSED, 0, 0, 0, 0, 0, 0, 0); if (t == LIGHT) calclight(); } int findtype(OFString *what) { - @autoreleasepool { - loopi(MAXENTTYPES) if ([what isEqual:entnames[i]]) return i; - conoutf(@"unknown entity type \"%@\"", what); - return NOTUSED; - } + loopi(MAXENTTYPES) if ([what isEqual:entnames[i]]) return i; + conoutf(@"unknown entity type \"%@\"", what); + return NOTUSED; } entity * newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4) { Index: src/worldio.mm ================================================================== --- src/worldio.mm +++ src/worldio.mm @@ -12,34 +12,31 @@ static OFString *cgzname, *bakname, *pcfname, *mcfname; static void setnames(OFString *name) { - @autoreleasepool { - OFCharacterSet *cs = - [OFCharacterSet characterSetWithCharactersInString:@"/\\"]; - OFRange range = [name rangeOfCharacterFromSet:cs]; - OFString *pakname, *mapname; - - if (range.location != OFNotFound) { - pakname = [name substringToIndex:range.location]; - mapname = [name substringFromIndex:range.location + 1]; - } else { - pakname = @"base"; - mapname = name; - } - - cgzname = [[OFString alloc] - initWithFormat:@"packages/%@/%@.cgz", pakname, mapname]; - bakname = - [[OFString alloc] initWithFormat:@"packages/%@/%@_%d.BAK", - pakname, mapname, lastmillis]; - pcfname = [[OFString alloc] - initWithFormat:@"packages/%@/package.cfg", pakname]; - mcfname = [[OFString alloc] - initWithFormat:@"packages/%@/%@.cfg", pakname, mapname]; - } + OFCharacterSet *cs = + [OFCharacterSet characterSetWithCharactersInString:@"/\\"]; + OFRange range = [name rangeOfCharacterFromSet:cs]; + OFString *pakname, *mapname; + + if (range.location != OFNotFound) { + pakname = [name substringToIndex:range.location]; + mapname = [name substringFromIndex:range.location + 1]; + } else { + pakname = @"base"; + mapname = name; + } + + cgzname = [[OFString alloc] + initWithFormat:@"packages/%@/%@.cgz", pakname, mapname]; + bakname = [[OFString alloc] initWithFormat:@"packages/%@/%@_%d.BAK", + pakname, mapname, lastmillis]; + pcfname = [[OFString alloc] + initWithFormat:@"packages/%@/package.cfg", pakname]; + mcfname = [[OFString alloc] + initWithFormat:@"packages/%@/%@.cfg", pakname, mapname]; } // the optimize routines below are here to reduce the detrimental effects of // messy mapping by setting certain properties (vdeltas and textures) to // neighbouring values wherever there is no visible difference. This allows the @@ -158,42 +155,41 @@ // miniscule map sizes. void save_world(OFString *mname) { - @autoreleasepool { - resettagareas(); // wouldn't be able to reproduce tagged areas - // otherwise - voptimize(); - toptimize(); - if (mname.length == 0) - mname = getclientmap(); - setnames(mname); - backup(cgzname, bakname); - gzFile f = gzopen( - [cgzname cStringWithEncoding:OFLocale.encoding], "wb9"); - if (!f) { - conoutf(@"could not write map to %@", cgzname); - return; - } - hdr.version = MAPVERSION; - hdr.numents = 0; - loopv(ents) if (ents[i].type != NOTUSED) hdr.numents++; - header tmp = hdr; - endianswap(&tmp.version, sizeof(int), 4); - endianswap(&tmp.waterlevel, sizeof(int), 16); - gzwrite(f, &tmp, sizeof(header)); - loopv(ents) - { - if (ents[i].type != NOTUSED) { - entity tmp = ents[i]; - endianswap(&tmp, sizeof(short), 4); - gzwrite(f, &tmp, sizeof(persistent_entity)); - } - } - sqr *t = NULL; - int sc = 0; + resettagareas(); // wouldn't be able to reproduce tagged areas + // otherwise + voptimize(); + toptimize(); + if (mname.length == 0) + mname = getclientmap(); + setnames(mname); + backup(cgzname, bakname); + gzFile f = + gzopen([cgzname cStringWithEncoding:OFLocale.encoding], "wb9"); + if (!f) { + conoutf(@"could not write map to %@", cgzname); + return; + } + hdr.version = MAPVERSION; + hdr.numents = 0; + loopv(ents) if (ents[i].type != NOTUSED) hdr.numents++; + header tmp = hdr; + endianswap(&tmp.version, sizeof(int), 4); + endianswap(&tmp.waterlevel, sizeof(int), 16); + gzwrite(f, &tmp, sizeof(header)); + loopv(ents) + { + if (ents[i].type != NOTUSED) { + entity tmp = ents[i]; + endianswap(&tmp, sizeof(short), 4); + gzwrite(f, &tmp, sizeof(persistent_entity)); + } + } + sqr *t = NULL; + int sc = 0; #define spurge \ while (sc) { \ gzputc(f, 255); \ if (sc > 255) { \ gzputc(f, 255); \ @@ -201,195 +197,188 @@ } else { \ gzputc(f, sc); \ sc = 0; \ } \ } - loopk(cubicsize) - { - sqr *s = &world[k]; -#define c(f) (s->f == t->f) - // 4 types of blocks, to compress a bit: - // 255 (2): same as previous block + count - // 254 (3): same as previous, except light // deprecated - // SOLID (5) - // anything else (9) - - if (SOLID(s)) { - if (t && c(type) && c(wtex) && c(vdelta)) { - sc++; - } else { - spurge; - gzputc(f, s->type); - gzputc(f, s->wtex); - gzputc(f, s->vdelta); - } - } else { - if (t && c(type) && c(floor) && c(ceil) && - c(ctex) && c(ftex) && c(utex) && c(wtex) && - c(vdelta) && c(tag)) { - sc++; - } else { - spurge; - gzputc(f, s->type); - gzputc(f, s->floor); - gzputc(f, s->ceil); - gzputc(f, s->wtex); - gzputc(f, s->ftex); - gzputc(f, s->ctex); - gzputc(f, s->vdelta); - gzputc(f, s->utex); - gzputc(f, s->tag); - } - } - t = s; - } - spurge; - gzclose(f); - conoutf(@"wrote map file %@", cgzname); - settagareas(); - } + loopk(cubicsize) + { + sqr *s = &world[k]; +#define c(f) (s->f == t->f) + // 4 types of blocks, to compress a bit: + // 255 (2): same as previous block + count + // 254 (3): same as previous, except light // deprecated + // SOLID (5) + // anything else (9) + + if (SOLID(s)) { + if (t && c(type) && c(wtex) && c(vdelta)) { + sc++; + } else { + spurge; + gzputc(f, s->type); + gzputc(f, s->wtex); + gzputc(f, s->vdelta); + } + } else { + if (t && c(type) && c(floor) && c(ceil) && c(ctex) && + c(ftex) && c(utex) && c(wtex) && c(vdelta) && + c(tag)) { + sc++; + } else { + spurge; + gzputc(f, s->type); + gzputc(f, s->floor); + gzputc(f, s->ceil); + gzputc(f, s->wtex); + gzputc(f, s->ftex); + gzputc(f, s->ctex); + gzputc(f, s->vdelta); + gzputc(f, s->utex); + gzputc(f, s->tag); + } + } + t = s; + } + spurge; + gzclose(f); + conoutf(@"wrote map file %@", cgzname); + settagareas(); } COMMANDN(savemap, save_world, ARG_1STR) void load_world(OFString *mname) // still supports all map formats that have existed // since the earliest cube betas! { - @autoreleasepool { - stopifrecording(); - cleardlights(); - pruneundos(); - setnames(mname); - gzFile f = gzopen( - [cgzname cStringWithEncoding:OFLocale.encoding], "rb9"); - if (!f) { - conoutf(@"could not read map %@", cgzname); - return; - } - gzread(f, &hdr, sizeof(header) - sizeof(int) * 16); - endianswap(&hdr.version, sizeof(int), 4); - if (strncmp(hdr.head, "CUBE", 4) != 0) - fatal(@"while reading map: header malformatted"); - if (hdr.version > MAPVERSION) - fatal(@"this map requires a newer version of cube"); - if (sfactor < SMALLEST_FACTOR || sfactor > LARGEST_FACTOR) - fatal(@"illegal map size"); - if (hdr.version >= 4) { - gzread(f, &hdr.waterlevel, sizeof(int) * 16); - endianswap(&hdr.waterlevel, sizeof(int), 16); - } else { - hdr.waterlevel = -100000; - } - ents.setsize(0); - loopi(hdr.numents) - { - entity &e = ents.add(); - gzread(f, &e, sizeof(persistent_entity)); - endianswap(&e, sizeof(short), 4); - e.spawned = false; - if (e.type == LIGHT) { - if (!e.attr2) - e.attr2 = - 255; // needed for MAPVERSION<=2 - if (e.attr1 > 32) - e.attr1 = 32; // 12_03 and below - } - } - free(world); - setupworld(hdr.sfactor); - char texuse[256]; - loopi(256) texuse[i] = 0; - sqr *t = NULL; - loopk(cubicsize) - { - sqr *s = &world[k]; - int type = gzgetc(f); - switch (type) { - case 255: { - int n = gzgetc(f); - for (int i = 0; i < n; i++, k++) - memcpy(&world[k], t, sizeof(sqr)); - k--; - break; - } - case 254: // only in MAPVERSION<=2 - { - memcpy(s, t, sizeof(sqr)); - s->r = s->g = s->b = gzgetc(f); - gzgetc(f); - break; - } - case SOLID: { - s->type = SOLID; - s->wtex = gzgetc(f); - s->vdelta = gzgetc(f); - if (hdr.version <= 2) { - gzgetc(f); - gzgetc(f); - } - s->ftex = DEFAULT_FLOOR; - s->ctex = DEFAULT_CEIL; - s->utex = s->wtex; - s->tag = 0; - s->floor = 0; - s->ceil = 16; - break; - } - default: { - if (type < 0 || type >= MAXTYPE) { - OFString *t = [OFString - stringWithFormat:@"%d @ %d", type, - k]; - fatal(@"while reading map: type out of " - @"range: ", - t); - } - s->type = type; - s->floor = gzgetc(f); - s->ceil = gzgetc(f); - if (s->floor >= s->ceil) - s->floor = s->ceil - 1; // for pre 12_13 - s->wtex = gzgetc(f); - s->ftex = gzgetc(f); - s->ctex = gzgetc(f); - if (hdr.version <= 2) { - gzgetc(f); - gzgetc(f); - } - s->vdelta = gzgetc(f); - s->utex = - (hdr.version >= 2) ? gzgetc(f) : s->wtex; - s->tag = (hdr.version >= 5) ? gzgetc(f) : 0; - s->type = type; - } - } - s->defer = 0; - t = s; - texuse[s->wtex] = 1; - if (!SOLID(s)) - texuse[s->utex] = texuse[s->ftex] = - texuse[s->ctex] = 1; - } - gzclose(f); - calclight(); - settagareas(); - int xs, ys; - loopi(256) if (texuse) lookuptexture(i, &xs, &ys); - conoutf(@"read map %@ (%d milliseconds)", cgzname, - SDL_GetTicks() - lastmillis); - conoutf(@"%s", hdr.maptitle); - startmap(mname); - loopl(256) - { - // can this be done smarter? - OFString *aliasname = - [OFString stringWithFormat:@"level_trigger_%d", l]; - if (identexists(aliasname)) - alias(aliasname, @""); - } - OFIRI *gameDataIRI = Cube.sharedInstance.gameDataIRI; - execfile([gameDataIRI IRIByAppendingPathComponent: - @"data/default_map_settings.cfg"]); - execfile([gameDataIRI IRIByAppendingPathComponent:pcfname]); - execfile([gameDataIRI IRIByAppendingPathComponent:mcfname]); - } + stopifrecording(); + cleardlights(); + pruneundos(); + setnames(mname); + gzFile f = + gzopen([cgzname cStringWithEncoding:OFLocale.encoding], "rb9"); + if (!f) { + conoutf(@"could not read map %@", cgzname); + return; + } + gzread(f, &hdr, sizeof(header) - sizeof(int) * 16); + endianswap(&hdr.version, sizeof(int), 4); + if (strncmp(hdr.head, "CUBE", 4) != 0) + fatal(@"while reading map: header malformatted"); + if (hdr.version > MAPVERSION) + fatal(@"this map requires a newer version of cube"); + if (sfactor < SMALLEST_FACTOR || sfactor > LARGEST_FACTOR) + fatal(@"illegal map size"); + if (hdr.version >= 4) { + gzread(f, &hdr.waterlevel, sizeof(int) * 16); + endianswap(&hdr.waterlevel, sizeof(int), 16); + } else { + hdr.waterlevel = -100000; + } + ents.setsize(0); + loopi(hdr.numents) + { + entity &e = ents.add(); + gzread(f, &e, sizeof(persistent_entity)); + endianswap(&e, sizeof(short), 4); + e.spawned = false; + if (e.type == LIGHT) { + if (!e.attr2) + e.attr2 = 255; // needed for MAPVERSION<=2 + if (e.attr1 > 32) + e.attr1 = 32; // 12_03 and below + } + } + free(world); + setupworld(hdr.sfactor); + char texuse[256]; + loopi(256) texuse[i] = 0; + sqr *t = NULL; + loopk(cubicsize) + { + sqr *s = &world[k]; + int type = gzgetc(f); + switch (type) { + case 255: { + int n = gzgetc(f); + for (int i = 0; i < n; i++, k++) + memcpy(&world[k], t, sizeof(sqr)); + k--; + break; + } + case 254: // only in MAPVERSION<=2 + { + memcpy(s, t, sizeof(sqr)); + s->r = s->g = s->b = gzgetc(f); + gzgetc(f); + break; + } + case SOLID: { + s->type = SOLID; + s->wtex = gzgetc(f); + s->vdelta = gzgetc(f); + if (hdr.version <= 2) { + gzgetc(f); + gzgetc(f); + } + s->ftex = DEFAULT_FLOOR; + s->ctex = DEFAULT_CEIL; + s->utex = s->wtex; + s->tag = 0; + s->floor = 0; + s->ceil = 16; + break; + } + default: { + if (type < 0 || type >= MAXTYPE) { + OFString *t = [OFString + stringWithFormat:@"%d @ %d", type, k]; + fatal(@"while reading map: type out of " + @"range: ", + t); + } + s->type = type; + s->floor = gzgetc(f); + s->ceil = gzgetc(f); + if (s->floor >= s->ceil) + s->floor = s->ceil - 1; // for pre 12_13 + s->wtex = gzgetc(f); + s->ftex = gzgetc(f); + s->ctex = gzgetc(f); + if (hdr.version <= 2) { + gzgetc(f); + gzgetc(f); + } + s->vdelta = gzgetc(f); + s->utex = (hdr.version >= 2) ? gzgetc(f) : s->wtex; + s->tag = (hdr.version >= 5) ? gzgetc(f) : 0; + s->type = type; + } + } + s->defer = 0; + t = s; + texuse[s->wtex] = 1; + if (!SOLID(s)) + texuse[s->utex] = texuse[s->ftex] = texuse[s->ctex] = 1; + } + gzclose(f); + calclight(); + settagareas(); + int xs, ys; + loopi(256) if (texuse) lookuptexture(i, &xs, &ys); + conoutf(@"read map %@ (%d milliseconds)", cgzname, + SDL_GetTicks() - lastmillis); + conoutf(@"%s", hdr.maptitle); + startmap(mname); + loopl(256) + { + // can this be done smarter? + OFString *aliasname = + [OFString stringWithFormat:@"level_trigger_%d", l]; + if (identexists(aliasname)) + alias(aliasname, @""); + } + OFIRI *gameDataIRI = Cube.sharedInstance.gameDataIRI; + execfile([gameDataIRI + IRIByAppendingPathComponent:@"data/default_map_settings.cfg"]); + execfile([gameDataIRI IRIByAppendingPathComponent:pcfname]); + execfile([gameDataIRI IRIByAppendingPathComponent:mcfname]); }