From fa5cdd5a808598d3d054ddc771a0c9a3c72dd231 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Fri, 22 Oct 2021 20:51:51 +0200 Subject: [PATCH] Initial commit of the Save/Restore system, this is the first reference implementation of QuakeC controlled save-files and SV_PerformLoad() and SV_PerformSave that Spoike added into FTEQW for Nuclide. --- src/gs-entbase/shared/NSEntity.h | 2 + src/gs-entbase/shared/NSEntity.qc | 49 +++++++++++ src/gs-entbase/shared/NSIO.h | 6 +- src/gs-entbase/shared/NSIO.qc | 50 ++++++++++- src/gs-entbase/shared/NSMonster.h | 3 + src/gs-entbase/shared/NSMonster.qc | 28 ++++++ src/gs-entbase/shared/NSRenderableEntity.h | 2 + src/gs-entbase/shared/NSRenderableEntity.qc | 62 +++++++++++++ src/gs-entbase/shared/NSTalkMonster.h | 2 + src/gs-entbase/shared/NSTalkMonster.qc | 96 +++++++++++++++++++++ src/gs-entbase/shared/NSTrigger.h | 4 + src/gs-entbase/shared/NSTrigger.qc | 34 ++++++++ src/server/entry.qc | 27 +++--- 13 files changed, 347 insertions(+), 18 deletions(-) diff --git a/src/gs-entbase/shared/NSEntity.h b/src/gs-entbase/shared/NSEntity.h index 2ed496bb..dcf04669 100644 --- a/src/gs-entbase/shared/NSEntity.h +++ b/src/gs-entbase/shared/NSEntity.h @@ -32,6 +32,8 @@ class NSEntity:NSTrigger #ifdef SERVER virtual void(void) Respawn; virtual void(entity, string, string) Input; + virtual void(float) Save; + virtual void(string,string) Restore; #endif #ifdef SERVER diff --git a/src/gs-entbase/shared/NSEntity.qc b/src/gs-entbase/shared/NSEntity.qc index ff91f50d..6d5947c6 100644 --- a/src/gs-entbase/shared/NSEntity.qc +++ b/src/gs-entbase/shared/NSEntity.qc @@ -348,6 +348,55 @@ NSEntity::Respawn(void) target = m_oldstrTarget; } +void +NSEntity::Save(float handle) +{ + SaveVector(handle, "origin", origin); + SaveString(handle, "model", model); + SaveVector(handle, "angles", angles); + SaveString(handle, "targetname", targetname); + SaveString(handle, "target", target); + SaveFloat(handle, "health", health); + SaveString(handle, "parentname", m_parent); + SaveFloat(handle, "ignorepvs", pvsflags); + super::Save(handle); +} +void +NSEntity::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "origin": + origin = stov(strValue); + break; + case "model": + model = strValue; + break; + case "angles": + angles = stov(strValue); + break; + case "solid": + solid = stof(strValue); + break; + case "targetname": + targetname = strValue; + break; + case "target": + target = strValue; + break; + case "health": + health = stof(strValue); + break; + case "parentname": + SetParent(strValue); + break; + case "ignorepvs": + pvsflags = PVSF_IGNOREPVS; + break; + default: + super::Restore(strKey, strValue); + } +} + void NSEntity::Input(entity eAct, string strInput, string strData) { diff --git a/src/gs-entbase/shared/NSIO.h b/src/gs-entbase/shared/NSIO.h index 77f01769..c4dcd43d 100644 --- a/src/gs-entbase/shared/NSIO.h +++ b/src/gs-entbase/shared/NSIO.h @@ -48,7 +48,11 @@ class NSIO virtual void(void) Respawn; virtual void(float) Save; - virtual void(float) Restore; + virtual void(string,string) Restore; + nonvirtual void(float, string, float) SaveFloat; + nonvirtual void(float, string, int) SaveInt; + nonvirtual void(float, string, string) SaveString; + nonvirtual void(float, string, vector) SaveVector; /* Handle incoming entities input messaging */ virtual void(entity, string, string) Input; diff --git a/src/gs-entbase/shared/NSIO.qc b/src/gs-entbase/shared/NSIO.qc index 5e90b0b3..4b6ec459 100644 --- a/src/gs-entbase/shared/NSIO.qc +++ b/src/gs-entbase/shared/NSIO.qc @@ -152,14 +152,56 @@ NSIO::Respawn(void) } void -NSIO::Save(float handle) +NSIO::SaveFloat(float handle, string key, float value) { - + fputs(handle, sprintf("%S \"%f\"\n", key, value)); } void -NSIO::Restore(float handle) +NSIO::SaveInt(float handle, string key, int value) { - + fputs(handle, sprintf("%S \"%i\"\n", key, value)); +} +void +NSIO::SaveString(float handle, string key, string value) +{ + fputs(handle, sprintf("%S %S\n", key, value)); +} +void +NSIO::SaveVector(float handle, string key, vector value) +{ + fputs(handle, sprintf("%S \"%v\"\n", key, value)); +} + + +void +NSIO::Save(float handle) +{ + SaveString(handle, "OnTrigger", m_strOnTrigger); + SaveString(handle, "OnUser1", m_strOnUser1); + SaveString(handle, "OnUser2", m_strOnUser2); + SaveString(handle, "OnUser3", m_strOnUser3); + SaveString(handle, "OnUser4", m_strOnUser4); +} +void +NSIO::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "OnTrigger": + m_strOnTrigger = strValue; + break; + case "OnUser1": + m_strOnUser1 = strValue; + break; + case "OnUser1": + m_strOnUser1 = strValue; + break; + case "OnUser1": + m_strOnUser1 = strValue; + break; + case "OnUser1": + m_strOnUser1 = strValue; + break; + } } #endif diff --git a/src/gs-entbase/shared/NSMonster.h b/src/gs-entbase/shared/NSMonster.h index 75ff3e37..e80b9fae 100644 --- a/src/gs-entbase/shared/NSMonster.h +++ b/src/gs-entbase/shared/NSMonster.h @@ -137,6 +137,9 @@ class NSMonster:NSSurfacePropEntity void(void) NSMonster; #ifdef SERVER + virtual void(float) Save; + virtual void(string,string) Restore; + virtual void(void) touch; virtual void(void) Hide; virtual void(void) Respawn; diff --git a/src/gs-entbase/shared/NSMonster.qc b/src/gs-entbase/shared/NSMonster.qc index e6f80eda..72dc5c34 100644 --- a/src/gs-entbase/shared/NSMonster.qc +++ b/src/gs-entbase/shared/NSMonster.qc @@ -15,6 +15,34 @@ */ #ifdef SERVER +void +NSMonster::Save(float handle) +{ + SaveInt(handle, "TriggerCondition", m_iTriggerCondition); + SaveString(handle, "TriggerTarget", m_strTriggerTarget); + SaveFloat(handle, "flPitch", m_flPitch); + SaveInt(handle, "iFlags", m_iFlags); + super::Save(handle); +} +void +NSMonster::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "TriggerCondition": + m_iTriggerCondition = stoi(strValue); + break; + case "TriggerTarget": + m_strTriggerTarget = strValue; + break; + case "flPitch": + m_flPitch = stof(strValue); + break; + case "iFlags": + m_iFlags = stoi(strValue); + break; + } +} + int NSMonster::AnimIdle(void) { diff --git a/src/gs-entbase/shared/NSRenderableEntity.h b/src/gs-entbase/shared/NSRenderableEntity.h index 391d74b2..1cb5fc84 100644 --- a/src/gs-entbase/shared/NSRenderableEntity.h +++ b/src/gs-entbase/shared/NSRenderableEntity.h @@ -31,6 +31,8 @@ class NSRenderableEntity:NSEntity virtual float(entity, float) SendEntity; virtual void(entity, string, string) Input; virtual void(void) Respawn; + virtual void(float) Save; + virtual void(string,string) Restore; #else virtual void(float flChanged) ReceiveEntity; virtual float(void) predraw; diff --git a/src/gs-entbase/shared/NSRenderableEntity.qc b/src/gs-entbase/shared/NSRenderableEntity.qc index 353a43d3..c1245969 100644 --- a/src/gs-entbase/shared/NSRenderableEntity.qc +++ b/src/gs-entbase/shared/NSRenderableEntity.qc @@ -572,6 +572,68 @@ NSRenderableEntity::SetRenderColor(vector newColor) #ifdef SERVER +void +NSRenderableEntity::Save(float handle) +{ + SaveInt(handle, "body", m_iBody); + SaveFloat(handle, "scale", scale); + SaveFloat(handle, "skin", skin); + SaveFloat(handle, "effects", effects); + +#ifndef GS_RENDERFX + SaveVector(handle, "color", colormod); + SaveFloat(handle, "alpha", alpha); +#else + SaveFloat(handle, "renderamt", m_flRenderAmt); + SaveVector(handle, "rendercolor", m_vecRenderColor); + SaveInt(handle, "rendermode", m_iRenderMode); + SaveInt(handle, "renderfx", m_iRenderFX); +#endif + + super::Save(handle); +} +void +NSRenderableEntity::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "body": + m_iBody = stoi(strValue); + break; + case "scale": + scale = stof(strValue); + break; + case "skin": + skin = stof(strValue); + break; + case "effects": + effects = stof(strValue); + break; +#ifndef GS_RENDERFX + case "color": + colormod = stov(strValue); + break; + case "alpha": + alpha = stof(strValue); + break; +#else + case "renderamt": + m_flRenderAmt = stof(strValue) / 255; + break; + case "rendercolor": + m_vecRenderColor = stov(strValue) / 255; + break; + case "rendermode": + m_iRenderMode = stoi(strValue); + break; + case "renderfx": + m_iRenderFX = stoi(strValue); + break; +#endif + default: + super::Restore(strKey, strValue); + } +} + void NSRenderableEntity::Input(entity eAct, string strInput, string strData) { diff --git a/src/gs-entbase/shared/NSTalkMonster.h b/src/gs-entbase/shared/NSTalkMonster.h index c0f83157..5020b84c 100644 --- a/src/gs-entbase/shared/NSTalkMonster.h +++ b/src/gs-entbase/shared/NSTalkMonster.h @@ -111,6 +111,8 @@ class NSTalkMonster:NSMonster virtual void(void) TalkStopFollow; virtual void(string, string) SpawnKey; virtual float(entity, float) SendEntity; + virtual void(float) Save; + virtual void(string,string) Restore; #else virtual float(void) predraw; diff --git a/src/gs-entbase/shared/NSTalkMonster.qc b/src/gs-entbase/shared/NSTalkMonster.qc index e22210ab..400540cb 100644 --- a/src/gs-entbase/shared/NSTalkMonster.qc +++ b/src/gs-entbase/shared/NSTalkMonster.qc @@ -15,6 +15,102 @@ */ #ifdef SERVER +void +NSTalkMonster::Save(float handle) +{ + SaveString(handle, "talkAnswer", m_talkAnswer); + SaveString(handle, "talkAsk", m_talkAsk); + SaveString(handle, "talkAllyShot", m_talkAllyShot); + SaveString(handle, "talkGreet", m_talkGreet); + SaveString(handle, "talkIdle", m_talkIdle); + SaveString(handle, "talkPanic", m_talkPanic); + SaveString(handle, "talkHearing", m_talkHearing); + SaveString(handle, "talkSmelling", m_talkSmelling); + SaveString(handle, "talkStare", m_talkStare); + SaveString(handle, "talkSurvived", m_talkSurvived); + SaveString(handle, "talkWounded", m_talkWounded); + SaveString(handle, "talkPlayerAsk", m_talkPlayerAsk); + SaveString(handle, "talkPlayerGreet", m_talkPlayerGreet); + SaveString(handle, "talkPlayerIdle", m_talkPlayerIdle); + SaveString(handle, "talkPlayerWounded1", m_talkPlayerWounded1); + SaveString(handle, "talkPlayerWounded2", m_talkPlayerWounded2); + SaveString(handle, "talkPlayerWounded3", m_talkPlayerWounded3); + SaveString(handle, "talkUnfollow", m_talkUnfollow); + SaveString(handle, "talkFollow", m_talkFollow); + SaveString(handle, "talkStopFollow", m_talkStopFollow); + + super::Save(handle); +} +void +NSTalkMonster::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "talkAnswer": + m_talkAnswer = strValue; + break; + case "talkAsk": + m_talkAsk = strValue; + break; + case "talkAllyShot": + m_talkAllyShot = strValue; + break; + case "talkGreet": + m_talkGreet = strValue; + break; + case "talkIdle": + m_talkIdle = strValue; + break; + case "talkPanic": + m_talkPanic = strValue; + break; + case "talkHearing": + m_talkHearing = strValue; + break; + case "talkSmelling": + m_talkSmelling = strValue; + break; + case "talkStare": + m_talkStare = strValue; + break; + case "talkSurvived": + m_talkSurvived = strValue; + break; + case "talkWounded": + m_talkWounded = strValue; + break; + + case "talkPlayerAsk": + m_talkPlayerAsk = strValue; + break; + case "talkPlayerGreet": + m_talkPlayerGreet = strValue; + break; + case "talkPlayerIdle": + m_talkPlayerIdle = strValue; + break; + case "talkPlayerWounded1": + m_talkPlayerWounded1 = strValue; + break; + case "talkPlayerWounded2": + m_talkPlayerWounded2 = strValue; + break; + case "talkPlayerWounded3": + m_talkPlayerWounded3 = strValue; + break; + case "talkUnfollow": + m_talkUnfollow = strValue; + break; + case "talkFollow": + m_talkFollow = strValue; + break; + case "talkStopFollow": + m_talkStopFollow = strValue; + break; + default: + super::Restore(strKey, strValue); + } +} + void NSTalkMonster::WarnAllies(void) { diff --git a/src/gs-entbase/shared/NSTrigger.h b/src/gs-entbase/shared/NSTrigger.h index 26a25751..d7003bd4 100644 --- a/src/gs-entbase/shared/NSTrigger.h +++ b/src/gs-entbase/shared/NSTrigger.h @@ -46,7 +46,11 @@ class NSTrigger:NSIO virtual int(void) GetValue; virtual int(void) GetMaster; + /* overrides */ virtual void(string, string) SpawnKey; + virtual void(float) Save; + virtual void(string,string) Restore; + #endif }; diff --git a/src/gs-entbase/shared/NSTrigger.qc b/src/gs-entbase/shared/NSTrigger.qc index fe697e79..c1ed0c2c 100644 --- a/src/gs-entbase/shared/NSTrigger.qc +++ b/src/gs-entbase/shared/NSTrigger.qc @@ -101,6 +101,40 @@ NSTrigger::GetMaster(void) return t.GetValue(); } +void +NSTrigger::Save(float handle) +{ + SaveString(handle, "killtarget", m_strKillTarget); + SaveString(handle, "message", m_strMessage); + SaveString(handle, "master", m_strMaster); + SaveInt(handle, "team_no", m_iTeam); + SaveFloat(handle, "delay", m_flDelay); + super::Save(handle); +} +void +NSTrigger::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "killtarget": + m_strKillTarget = strValue; + break; + case "message": + m_strMessage = strValue; + break; + case "master": + m_strMaster = strValue; + break; + case "team_no": + m_iTeam = stoi(strValue); + break; + case "delay": + m_flDelay = stof(strValue); + break; + default: + super::Restore(strKey, strValue); + } +} + void NSTrigger::SpawnKey(string strKey, string strValue) { diff --git a/src/server/entry.qc b/src/server/entry.qc index 1060d0ff..e8ec6e8a 100644 --- a/src/server/entry.qc +++ b/src/server/entry.qc @@ -661,9 +661,9 @@ SV_PerformLoad(float fh) string l; float n; e = world; + int braced; - int inentity; - int inworld; + NSEntity loadent; /* while ((e=nextent(e))) { @@ -675,7 +675,6 @@ SV_PerformLoad(float fh) #if 1 /* read line per line of our file handle */ while ((l=fgets(fh))) { - float braced = FALSE; float args = tokenize(l); if (!args) @@ -686,13 +685,13 @@ SV_PerformLoad(float fh) n = stof(argv(1)); cname = argv(2); e = edict_num(n); + loadent = __NULL__; __fullspawndata = fgets(fh); print(sprintf("Try spawning %s\n", cname)); /* call the constructor if one is present, init the default fields */ if (isfunction(strcat("spawnfunc_", cname))) { - NSEntity willload; e.classname = cname; print(sprintf("I'm actually spawning %s\n", cname)); @@ -700,22 +699,24 @@ SV_PerformLoad(float fh) self = e; callfunction(strcat("spawnfunc_", cname)); e.classname = cname; + loadent = (NSEntity)e; self = eold; - inentity = TRUE; } else { print(sprintf("Could not spawn %s\n", cname)); remove(e); continue; } - } else if (argv(1) == "GLOBAL") { - // TODO } else if (argv(0) == "{") { - if (inentity) - - willload = (NSEntity)e; - willload.Restore(fh); + braced++; } else if (argv(0) == "}") { - + braced--; + } else if (braced == 1) { + if (loadent) { + int c = tokenize(l); + + if (c == 2) + loadent.Restore(argv(0), argv(1)); + } } } #endif @@ -742,7 +743,7 @@ SV_PerformSave(float fh, float numents) willsave = (NSEntity)e; fputs(fh, sprintf("ENTITY \"%d\" %S\n", i, willsave.classname)); - fputs(fh, "{ "); + fputs(fh, "{\n"); willsave.Save(fh); fputs(fh, "}\n"); }