More file handling cleanups

FossilOrigin-Name: c09457f7ad6613411be70250bdc33917e92298e80706560a9a205c997b679297
This commit is contained in:
Jonathan Schleifer 2025-03-05 22:42:56 +00:00
parent a6a0247bb2
commit 3661ce9a40
3 changed files with 110 additions and 79 deletions

View file

@ -69,6 +69,18 @@ VARP(minmillis, 0, 5, 1000);
if (passwd == nil) if (passwd == nil)
passwd = @""; 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) if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | par) < 0)
fatal(@"Unable to initialize SDL"); fatal(@"Unable to initialize SDL");
@ -118,8 +130,6 @@ VARP(minmillis, 0, 5, 1000);
gl_init(_width, _height); gl_init(_width, _height);
log(@"basetex"); log(@"basetex");
_gameDataIRI = [OFFileManager.defaultManager currentDirectoryIRI];
_userDataIRI = [OFFileManager.defaultManager currentDirectoryIRI];
int xs, ys; int xs, ys;
if (!installtex(2, if (!installtex(2,
[_userDataIRI IRIByAppendingPathComponent:@"data/newchars.png"], [_userDataIRI IRIByAppendingPathComponent:@"data/newchars.png"],

View file

@ -88,94 +88,108 @@ stopifrecording()
} }
void void
savestate(char *fn) savestate(OFIRI *IRI)
{ {
stop();
f = gzopen(fn, "wb9");
if (!f) {
conoutf(@"could not write %s", fn);
return;
}
gzwrite(f, (void *)"CUBESAVE", 8);
gzputc(f, islittleendian);
gzputi(SAVEGAMEVERSION);
gzputi(sizeof(dynent));
@autoreleasepool { @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);
gzputi(sizeof(dynent));
gzwrite(f, getclientmap().UTF8String, _MAXDEFSTR); gzwrite(f, getclientmap().UTF8String, _MAXDEFSTR);
} gzputi(gamemode);
gzputi(gamemode); gzputi(ents.length());
gzputi(ents.length()); loopv(ents) gzputc(f, ents[i].spawned);
loopv(ents) gzputc(f, ents[i].spawned); gzwrite(f, player1, sizeof(dynent));
gzwrite(f, player1, sizeof(dynent)); dvector &monsters = getmonsters();
dvector &monsters = getmonsters(); gzputi(monsters.length());
gzputi(monsters.length()); loopv(monsters) gzwrite(f, monsters[i], sizeof(dynent));
loopv(monsters) gzwrite(f, monsters[i], sizeof(dynent)); gzputi(players.length());
gzputi(players.length()); loopv(players)
loopv(players) {
{ gzput(players[i] == NULL);
gzput(players[i] == NULL); gzwrite(f, players[i], sizeof(dynent));
gzwrite(f, players[i], sizeof(dynent)); }
} }
} }
void void
savegame(OFString *name) savegame(OFString *name)
{ {
if (!m_classicsp) {
conoutf(@"can only save classic sp games");
return;
}
@autoreleasepool { @autoreleasepool {
if (!m_classicsp) { OFString *path =
conoutf(@"can only save classic sp games"); [OFString stringWithFormat:@"savegames/%@.csgz", name];
return; OFIRI *IRI = [Cube.sharedInstance.userDataIRI
} IRIByAppendingPathComponent:path];
sprintf_sd(fn)("savegames/%s.csgz", name.UTF8String); savestate(IRI);
savestate(fn);
stop(); stop();
conoutf(@"wrote %s", fn); conoutf(@"wrote %@", IRI.string);
} }
} }
COMMAND(savegame, ARG_1STR) COMMAND(savegame, ARG_1STR)
void void
loadstate(char *fn) loadstate(OFIRI *IRI)
{ {
stop();
if (multiplayer())
return;
f = gzopen(fn, "rb9");
if (!f) {
conoutf(@"could not open %s", fn);
return;
}
string buf;
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() != sizeof(dynent))
goto out;
string mapname;
gzread(f, mapname, _MAXDEFSTR);
nextmode = gzgeti();
@autoreleasepool { @autoreleasepool {
// continue below once map has been loaded and client & server stop();
// have updated if (multiplayer())
changemap(@(mapname)); return;
f = gzopen([IRI.fileSystemRepresentation
cStringWithEncoding:OFLocale.encoding],
"rb9");
if (!f) {
conoutf(@"could not open %@", IRI.string);
return;
}
string buf;
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() != sizeof(dynent))
goto out;
string mapname;
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();
} }
return;
out:
conoutf(@"aborting: savegame/demo from a different version of cube or "
@"cpu architecture");
stop();
} }
void void
loadgame(OFString *name) loadgame(OFString *name)
{ {
@autoreleasepool { @autoreleasepool {
sprintf_sd(fn)("savegames/%s.csgz", name.UTF8String); OFString *path =
loadstate(fn); [OFString stringWithFormat:@"savegames/%@.csgz", name];
OFIRI *IRI = [Cube.sharedInstance.userDataIRI
IRIByAppendingPathComponent:path];
loadstate(IRI);
} }
} }
COMMAND(loadgame, ARG_1STR) COMMAND(loadgame, ARG_1STR)
@ -249,18 +263,23 @@ OFVector3D dorig;
void void
record(OFString *name) record(OFString *name)
{ {
if (m_sp) {
conoutf(@"cannot record singleplayer games");
return;
}
int cn = getclientnum();
if (cn < 0)
return;
@autoreleasepool { @autoreleasepool {
if (m_sp) { OFString *path =
conoutf(@"cannot record singleplayer games"); [OFString stringWithFormat:@"demos/%@.cdgz", name];
return; OFIRI *IRI = [Cube.sharedInstance.userDataIRI
} IRIByAppendingPathComponent:path];
int cn = getclientnum(); savestate(IRI);
if (cn < 0)
return;
sprintf_sd(fn)("demos/%s.cdgz", name.UTF8String);
savestate(fn);
gzputi(cn); gzputi(cn);
conoutf(@"started recording demo to %s", fn); conoutf(@"started recording demo to %@", IRI.string);
demorecording = true; demorecording = true;
starttime = lastmillis; starttime = lastmillis;
ddamage = bdamage = 0; ddamage = bdamage = 0;
@ -315,8 +334,11 @@ void
demo(OFString *name) demo(OFString *name)
{ {
@autoreleasepool { @autoreleasepool {
sprintf_sd(fn)("demos/%s.cdgz", name.UTF8String); OFString *path =
loadstate(fn); [OFString stringWithFormat:@"demos/%@.cdgz", name];
OFIRI *IRI = [Cube.sharedInstance.userDataIRI
IRIByAppendingPathComponent:path];
loadstate(IRI);
demoloading = true; demoloading = true;
} }
} }

View file

@ -254,8 +254,7 @@ playsound(int n, OFVector3D *loc)
#endif #endif
if (!samples[n]) { if (!samples[n]) {
conoutf(@"failed to load sample: %s", conoutf(@"failed to load sample: %@", IRI.string);
IRI.string.UTF8String);
return; return;
} }
} }