Index: src/renderextras.mm ================================================================== --- src/renderextras.mm +++ src/renderextras.mm @@ -144,11 +144,11 @@ glDisable(GL_BLEND); glDepthMask(GL_TRUE); } -string closeent; +static OFString *closeent; OFString *entnames[] = { @"none?", @"light", @"playerstart", @"shells", @@ -174,11 +174,11 @@ }; void renderents() // show sparkly thingies for map entities in edit mode { - closeent[0] = 0; + closeent = @""; if (!editmode) return; loopv(ents) { entity &e = ents[i]; @@ -188,18 +188,15 @@ particle_splash(2, 2, 40, v); } int e = closestent(); if (e >= 0) { entity &c = ents[e]; - @autoreleasepool { - sprintf_s(closeent)( - "closest entity = %s (%d, %d, %d, %d), " - "selection = (%d, %d)", - entnames[c.type].UTF8String, c.attr1, c.attr2, - c.attr3, c.attr4, getvar(@"selxs"), - getvar(@"selys")); - } + closeent = [[OFString alloc] + initWithFormat:@"closest entity = %@ (%d, %d, %d, %d), " + @"selection = (%d, %d)", + entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, + getvar(@"selxs"), getvar(@"selys")]; } } void loadsky(OFString *basename) @@ -369,12 +366,12 @@ OFString *command = getcurcommand(); OFString *player = playerincrosshair(); if (command) draw_textf(@"> %@_", 20, 1570, 2, command); - else if (closeent[0]) - draw_text(@(closeent), 20, 1570, 2); + else if (closeent.length > 0) + draw_text(closeent, 20, 1570, 2); else if (player != nil) draw_text(player, 20, 1570, 2); } renderscores(); Index: src/worldio.mm ================================================================== --- src/worldio.mm +++ src/worldio.mm @@ -1,35 +1,43 @@ // worldio.cpp: loading & saving of maps and savegames #include "cube.h" void -backup(char *name, char *backupname) +backup(OFString *name, OFString *backupname) { - remove(backupname); - rename(name, backupname); + [OFFileManager.defaultManager removeItemAtPath:backupname]; + [OFFileManager.defaultManager moveItemAtPath:name toPath:backupname]; } -string cgzname, bakname, pcfname, mcfname; +static OFString *cgzname, *bakname, *pcfname, *mcfname; static void -setnames(const char *name) -{ - string pakname, mapname; - const char *slash = strpbrk(name, "/\\"); - if (slash) { - strn0cpy(pakname, name, slash - name + 1); - strcpy_s(mapname, slash + 1); - } else { - strcpy_s(pakname, "base"); - strcpy_s(mapname, name); - } - sprintf_s(cgzname)("packages/%s/%s.cgz", pakname, mapname); - sprintf_s(bakname)( - "packages/%s/%s_%d.BAK", pakname, mapname, lastmillis); - sprintf_s(pcfname)("packages/%s/package.cfg", pakname); - sprintf_s(mcfname)("packages/%s/%s.cfg", pakname, mapname); +setnames(OFString *name_) +{ + @autoreleasepool { + const char *name = name_.UTF8String; + string pakname, mapname; + const char *slash = strpbrk(name, "/\\"); + if (slash) { + strn0cpy(pakname, name, slash - name + 1); + strcpy_s(mapname, slash + 1); + } else { + strcpy_s(pakname, "base"); + strcpy_s(mapname, name); + } + + cgzname = [[OFString alloc] + initWithFormat:@"packages/%s/%s.cgz", pakname, mapname]; + bakname = + [[OFString alloc] initWithFormat:@"packages/%s/%s_%d.BAK", + pakname, mapname, lastmillis]; + pcfname = [[OFString alloc] + initWithFormat:@"packages/%s/package.cfg", pakname]; + mcfname = [[OFString alloc] + initWithFormat:@"packages/%s/%s.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 @@ -120,16 +128,14 @@ // these two are used by getmap/sendmap.. transfers compressed maps directly void writemap(OFString *mname, int msize, uchar *mdata) { - @autoreleasepool { - setnames(mname.UTF8String); - } + setnames(mname); backup(cgzname, bakname); - FILE *f = fopen(cgzname, "wb"); + FILE *f = fopen([cgzname cStringWithEncoding:OFLocale.encoding], "wb"); if (!f) { conoutf(@"could not write map to %s", cgzname); return; } fwrite(mdata, 1, msize, f); @@ -138,13 +144,11 @@ } OFData * readmap(OFString *mname) { - @autoreleasepool { - setnames(mname.UTF8String); - } + setnames(mname); return [OFData dataWithContentsOfFile:mname]; } // save map as .cgz file. uses 2 layers of compression: first does simple // run-length encoding and leaves out data for certain kinds of cubes, then zlib @@ -159,13 +163,14 @@ // otherwise voptimize(); toptimize(); if (mname.length == 0) mname = getclientmap(); - setnames(mname.UTF8String); + setnames(mname); backup(cgzname, bakname); - gzFile f = gzopen(cgzname, "wb9"); + gzFile f = gzopen( + [cgzname cStringWithEncoding:OFLocale.encoding], "wb9"); if (!f) { conoutf(@"could not write map to %s", cgzname); return; } hdr.version = MAPVERSION; @@ -245,140 +250,142 @@ void load_world(OFString *mname) // still supports all map formats that have existed // since the earliest cube betas! { - stopifrecording(); - cleardlights(); - pruneundos(); - @autoreleasepool { - setnames(mname.UTF8String); - } - gzFile f = gzopen(cgzname, "rb9"); - if (!f) { - conoutf(@"could not read map %s", 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 %s (%d milliseconds)", cgzname, - SDL_GetTicks() - lastmillis); - conoutf(@"%s", hdr.maptitle); - startmap(mname); - loopl(256) - { - @autoreleasepool { + @autoreleasepool { + stopifrecording(); + cleardlights(); + pruneundos(); + setnames(mname); + gzFile f = gzopen( + [cgzname cStringWithEncoding:OFLocale.encoding], "rb9"); + if (!f) { + conoutf(@"could not read map %s", 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 %s (%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, @""); } - } - execfile(@"data/default_map_settings.cfg"); - @autoreleasepool { - execfile(@(pcfname)); - execfile(@(mcfname)); + execfile(@"data/default_map_settings.cfg"); + execfile(pcfname); + execfile(mcfname); } }