Skip to content

Commit

Permalink
Add sections to script contexts and make global effects section-local
Browse files Browse the repository at this point in the history
  • Loading branch information
Fulgen301 committed Nov 15, 2023
1 parent e5cbc84 commit 926016d
Show file tree
Hide file tree
Showing 48 changed files with 528 additions and 409 deletions.
8 changes: 5 additions & 3 deletions src/C4Aul.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,11 @@ struct C4AulContext
{
C4Object *Obj;
C4Def *Def;
C4Section *Section;
struct C4AulScriptContext *Caller;

bool CalledWithStrictNil() const noexcept;
C4Section &GetSection() const noexcept;
};

// execution context
Expand Down Expand Up @@ -304,7 +306,7 @@ class C4AulFunc
virtual const C4V_Type *GetParType() { return nullptr; }
virtual C4V_Type GetRetType() { return C4V_Any; }
virtual C4Value Exec(C4AulContext *pCallerCtx, const C4Value pPars[], bool fPassErrors = false) { return C4Value(); } // execute func (script call)
virtual C4Value Exec(C4Object *pObj = nullptr, const C4AulParSet &pPars = C4AulParSet{}, bool fPassErrors = false, bool nonStrict3WarnConversionOnly = false, bool convertNilToIntBool = true); // execute func (engine call)
virtual C4Value Exec(C4Section &section, C4Object *pObj = nullptr, const C4AulParSet &pPars = C4AulParSet{}, bool fPassErrors = false, bool nonStrict3WarnConversionOnly = false, bool convertNilToIntBool = true); // execute func (engine call)
virtual void UnLink() { OverloadedBy = NextSNFunc = nullptr; }

C4AulFunc *GetLocalSFunc(const char *szIdtf); // find script function in own scope
Expand Down Expand Up @@ -356,7 +358,7 @@ class C4AulScriptFunc : public C4AulFunc
virtual const C4V_Type *GetParType() override { return ParType; }
virtual C4V_Type GetRetType() override { return bReturnRef ? C4V_pC4Value : C4V_Any; }
virtual C4Value Exec(C4AulContext *pCallerCtx, const C4Value pPars[], bool fPassErrors = false) override; // execute func (script call, should not happen)
virtual C4Value Exec(C4Object *pObj = nullptr, const C4AulParSet &pPars = C4AulParSet{}, bool fPassErrors = false, bool nonStrict3WarnConversionOnly = false, bool convertNilToIntBool = true) override; // execute func (engine call)
virtual C4Value Exec(C4Section &section, C4Object *pObj = nullptr, const C4AulParSet &pPars = C4AulParSet{}, bool fPassErrors = false, bool nonStrict3WarnConversionOnly = false, bool convertNilToIntBool = true) override; // execute func (engine call)

void CopyBody(C4AulScriptFunc &FromFunc); // copy script/code, etc from given func

Expand Down Expand Up @@ -505,7 +507,7 @@ class C4AulScript
C4AulAccess GetAllowedAccess(C4AulFunc *func, C4AulScript *caller);

public:
C4Value DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors = false, C4AulScriptStrict Strict = C4AulScriptStrict::MAXSTRICT); // directly parse uncompiled script (WARG! CYCLES!)
C4Value DirectExec(C4Section &section, C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors = false, C4AulScriptStrict Strict = C4AulScriptStrict::MAXSTRICT); // directly parse uncompiled script (WARG! CYCLES!)
void ResetProfilerTimes(); // zero all profiler times of owned functions
void CollectProfilerTimes(class C4AulProfiler &rProfiler);

Expand Down
29 changes: 19 additions & 10 deletions src/C4AulExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,21 @@ void C4AulExecError::show() const
// debug mode object message
if (Game.DebugMode)
if (cObj)
Game.Messages.New(C4GM_Target, sMessage, cObj, NO_OWNER);
Game.Messages.New(C4GM_Target, sMessage, cObj->Section, cObj, NO_OWNER);
else
Game.Messages.New(C4GM_Global, sMessage, nullptr, ANY_OWNER);
Game.Messages.New(C4GM_Global, sMessage, nullptr, nullptr, ANY_OWNER);
}

bool C4AulContext::CalledWithStrictNil() const noexcept
{
return Caller && Caller->Func->HasStrictNil();
}

C4Section &C4AulContext::GetSection() const noexcept
{
return Obj ? *Obj->Section : *Section;
}

const int MAX_CONTEXT_STACK = 512;
const int MAX_VALUE_STACK = 1024;

Expand Down Expand Up @@ -116,7 +121,7 @@ class C4AulExec
C4AulScript *pProfiledScript;

public:
C4Value Exec(C4AulScriptFunc *pSFunc, C4Object *pObj, const C4Value pPars[], bool fPassErrors, bool fTemporaryScript = false);
C4Value Exec(C4AulScriptFunc *pSFunc, C4Section &section, C4Object *pObj, const C4Value pPars[], bool fPassErrors, bool fTemporaryScript = false);
C4Value Exec(C4AulBCC *pCPos, bool fPassErrors);

void StartTrace();
Expand Down Expand Up @@ -315,7 +320,7 @@ class C4AulExec

C4AulExec AulExec;

C4Value C4AulExec::Exec(C4AulScriptFunc *pSFunc, C4Object *pObj, const C4Value *pnPars, bool fPassErrors, bool fTemporaryScript)
C4Value C4AulExec::Exec(C4AulScriptFunc *pSFunc, C4Section &section, C4Object *pObj, const C4Value *pnPars, bool fPassErrors, bool fTemporaryScript)
{
// Push parameters
C4Value *pPars = pCurVal + 1;
Expand All @@ -338,6 +343,7 @@ C4Value C4AulExec::Exec(C4AulScriptFunc *pSFunc, C4Object *pObj, const C4Value *
C4AulScriptContext ctx;
ctx.Obj = pObj;
ctx.Def = pDef;
ctx.Section = &section;
ctx.Return = nullptr;
ctx.Pars = pPars;
ctx.Vars = pVars;
Expand Down Expand Up @@ -1439,6 +1445,7 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
C4AulScriptContext ctx;
ctx.Obj = pObj;
ctx.Def = pDef;
ctx.Section = pCurCtx->Section;
ctx.Caller = pCurCtx;
ctx.Return = pReturn;
ctx.Pars = pPars;
Expand All @@ -1457,6 +1464,7 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
C4AulContext CallCtx;
CallCtx.Obj = pObj;
CallCtx.Def = pDef;
CallCtx.Section = pCurCtx->Section;
CallCtx.Caller = pCurCtx;

#ifdef DEBUGREC_SCRIPT
Expand Down Expand Up @@ -1592,12 +1600,13 @@ void C4AulProfiler::Show()
// done!
}

C4Value C4AulFunc::Exec(C4Object *pObj, const C4AulParSet &pPars, bool fPassErrors, bool nonStrict3WarnConversionOnly, bool convertNilToIntBool)
C4Value C4AulFunc::Exec(C4Section &section, C4Object *pObj, const C4AulParSet &pPars, bool fPassErrors, bool nonStrict3WarnConversionOnly, bool convertNilToIntBool)
{
// construct a dummy caller context
C4AulContext ctx;
ctx.Obj = pObj;
ctx.Def = pObj ? pObj->Def : nullptr;
ctx.Section = &section; // FIXME: pobj->Section?
ctx.Caller = nullptr;

const auto sFunc = SFunc();
Expand All @@ -1617,10 +1626,10 @@ C4Value C4AulScriptFunc::Exec(C4AulContext *pCtx, const C4Value pPars[], bool fP
if (Owner->State != ASS_PARSED) return C4VNull;

// execute
return AulExec.Exec(this, pCtx->Obj, pPars, fPassErrors);
return AulExec.Exec(this, *pCtx->Section, pCtx->Obj, pPars, fPassErrors);
}

C4Value C4AulScriptFunc::Exec(C4Object *pObj, const C4AulParSet &pPars, bool fPassErrors, bool nonStrict3WarnConversionOnly, bool convertNilToIntBool)
C4Value C4AulScriptFunc::Exec(C4Section &section, C4Object *pObj, const C4AulParSet &pPars, bool fPassErrors, bool nonStrict3WarnConversionOnly, bool convertNilToIntBool)
{
// handle easiest case first
if (Owner->State != ASS_PARSED) return C4VNull;
Expand All @@ -1630,7 +1639,7 @@ C4Value C4AulScriptFunc::Exec(C4Object *pObj, const C4AulParSet &pPars, bool fPa
if (TryCheckConvertFunctionParameters(pObj, this, pars.Par, !isAtLeastStrict3, isAtLeastStrict3 && convertNilToIntBool, fPassErrors, nonStrict3WarnConversionOnly && !isAtLeastStrict3))
{
// execute
return AulExec.Exec(this, pObj, pars.Par, fPassErrors);
return AulExec.Exec(this, section, pObj, pars.Par, fPassErrors);
}
return C4VNull;
}
Expand All @@ -1640,7 +1649,7 @@ bool C4AulScriptFunc::HasStrictNil() const noexcept
return pOrgScript->Strict >= C4AulScriptStrict::STRICT3;
}

C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors, C4AulScriptStrict Strict)
C4Value C4AulScript::DirectExec(C4Section &section, C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors, C4AulScriptStrict Strict)
{
#ifdef DEBUGREC_SCRIPT
AddDbgRec(RCT_DirectExec, szScript, strlen(szScript) + 1);
Expand Down Expand Up @@ -1685,7 +1694,7 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char
pFunc->Code = pScript->Code;
pScript->State = ASS_PARSED;
// Execute. The TemporaryScript-parameter makes sure the script will be deleted later on.
C4Value vRetVal(AulExec.Exec(pFunc, pObj, nullptr, fPassErrors, true));
C4Value vRetVal(AulExec.Exec(pFunc, section, pObj, nullptr, fPassErrors, true));
// profiler
AulExec.StopDirectExec();
return vRetVal;
Expand Down
6 changes: 3 additions & 3 deletions src/C4Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,7 @@ void C4Command::Transfer()
{
C4AulScriptFunc *f;
bool fHandled = (f = Target->Def->Script.SFn_ControlTransfer) != nullptr;
if (fHandled) fHandled = f->Exec(Target, {C4VObj(cObj), Tx, C4VInt(Ty)}).getBool();
if (fHandled) fHandled = f->Exec(*Target->Section, Target, {C4VObj(cObj), Tx, C4VInt(Ty)}).getBool();

if (!fHandled)
// Transfer not handled by target: done
Expand Down Expand Up @@ -2023,7 +2023,7 @@ void C4Command::Buy()
return;
}
// Base owner has not enough funds: fail
if (Game.Players.Get(Target->Base)->Wealth < pDef->GetValue(Target, cObj->Owner))
if (Game.Players.Get(Target->Base)->Wealth < pDef->GetValue(*Target->Section, Target, cObj->Owner))
{
Finish(false, LoadResStr("IDS_PLR_NOWEALTH")); return;
}
Expand Down Expand Up @@ -2237,7 +2237,7 @@ void C4Command::Fail(const char *szFailMessage)
// Message (if not empty)
if (!failMessage.empty())
{
Game.Messages.Append(C4GM_Target, failMessage.c_str(), l_Obj, NO_OWNER, 0, 0, FWhite, true);
Game.Messages.Append(C4GM_Target, failMessage.c_str(), l_Obj->Section, l_Obj, NO_OWNER, 0, 0, FWhite, true);
}
// Fail sound
StartSoundEffect("CommandFailure*", false, 100, l_Obj);
Expand Down
4 changes: 2 additions & 2 deletions src/C4Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ INT_PTR CALLBACK ConsoleDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lPara
// Remove player
if (Inside((int)LOWORD(wParam), IDM_PLAYER_QUIT1, IDM_PLAYER_QUIT2))
{
Game.Control.Input.Add(CID_EliminatePlayer, new C4ControlEliminatePlayer(LOWORD(wParam) - IDM_PLAYER_QUIT1));
Game.Control.Input.Add(CID_EliminatePlayer, new C4ControlEliminatePlayer(0, LOWORD(wParam) - IDM_PLAYER_QUIT1));
return TRUE;
}
// Remove client
Expand Down Expand Up @@ -608,7 +608,7 @@ bool C4Console::In(const char *szText)
// editing enabled?
if (!EditCursor.EditingOK()) return false;
// pass through network queue
Game.Control.DoInput(CID_Script, new C4ControlScript(szText, C4ControlScript::SCOPE_Console, Config.Developer.ConsoleScriptStrictness), CDT_Decide);
Game.Control.DoInput(CID_Script, new C4ControlScript(0, szText, C4ControlScript::SCOPE_Console, Config.Developer.ConsoleScriptStrictness), CDT_Decide);
return true;
}

Expand Down
32 changes: 26 additions & 6 deletions src/C4Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ void C4ControlScript::Execute() const
}
}

C4Section *const section{Game.GetSectionByIndex(sectionIndex)};
if (!section)
{
return;
}

const char *szScript = Script.getData();
// execute
C4Object *pObj = nullptr;
Expand All @@ -287,7 +293,7 @@ void C4ControlScript::Execute() const
else
// default: Fallback to global context
pScript = &Game.ScriptEngine;
C4Value rVal(pScript->DirectExec(pObj, szScript, "console script", false, Strict));
C4Value rVal(pScript->DirectExec(*section, pObj, szScript, "console script", false, Strict));
// show messages
// print script
if (pObj)
Expand All @@ -311,6 +317,7 @@ void C4ControlScript::Execute() const

void C4ControlScript::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkNamingAdapt(mkIntPackAdapt(sectionIndex) , "Section", 0));
pComp->Value(mkNamingAdapt(iTargetObj, "TargetObj", -1));
pComp->Value(mkNamingAdapt(Strict, "Strict", C4AulScriptStrict::MAXSTRICT));

Expand Down Expand Up @@ -864,9 +871,9 @@ void C4ControlJoinPlayer::CompileFunc(StdCompiler *pComp)

// *** C4ControlEMMoveObject

C4ControlEMMoveObject::C4ControlEMMoveObject(C4ControlEMObjectAction eAction, int32_t tx, int32_t ty, C4Object *pTargetObj,
C4ControlEMMoveObject::C4ControlEMMoveObject(C4ControlEMObjectAction eAction, int32_t tx, int32_t ty, const std::int32_t sectionIndex, C4Object *pTargetObj,
int32_t iObjectNum, int32_t *pObjects, const char *szScript, const C4AulScriptStrict strict)
: eAction(eAction), tx(tx), ty(ty), iTargetObj(Game.ObjectNumber(pTargetObj)),
: eAction(eAction), tx(tx), ty(ty), sectionIndex{sectionIndex}, iTargetObj(Game.ObjectNumber(pTargetObj)),
iObjectNum(iObjectNum), Strict{strict}, pObjects(pObjects), Script(szScript, true) {}

C4ControlEMMoveObject::~C4ControlEMMoveObject()
Expand Down Expand Up @@ -918,7 +925,7 @@ void C4ControlEMMoveObject::Execute() const
for (int i = 0; i < iObjectNum; ++i)
if (pObj = Game.SafeObjectPointer(pObjects[i]))
{
pObj = C4Object::GetSection(pObj).CreateObject(pObj->id, pObj, pObj->Owner, pObj->x, pObj->y);
pObj = pObj->Section->CreateObject(pObj->id, pObj, pObj->Owner, pObj->x, pObj->y);
if (pObj && fLocalCall) Console.EditCursor.GetSelection().Add(pObj, C4ObjectList::stNone);
}
// update status
Expand All @@ -933,7 +940,7 @@ void C4ControlEMMoveObject::Execute() const
{
if (!pObjects) return;
// execute script ...
C4ControlScript ScriptCtrl(Script.getData(), C4ControlScript::SCOPE_Global, Strict);
C4ControlScript ScriptCtrl(sectionIndex, Script.getData(), C4ControlScript::SCOPE_Global, Strict);
ScriptCtrl.SetByClient(iByClient);
// ... for each object in selection
for (int i = 0; i < iObjectNum; ++i)
Expand Down Expand Up @@ -974,6 +981,7 @@ void C4ControlEMMoveObject::CompileFunc(StdCompiler *pComp)
pComp->Value(mkNamingAdapt(mkIntAdaptT<uint8_t>(eAction), "Action"));
pComp->Value(mkNamingAdapt(tx, "tx", 0));
pComp->Value(mkNamingAdapt(ty, "ty", 0));
pComp->Value(mkNamingAdapt(mkIntPackAdapt(sectionIndex), "Section", 0));
pComp->Value(mkNamingAdapt(iTargetObj, "TargetObj", -1));
pComp->Value(mkNamingAdapt(mkIntPackAdapt(iObjectNum), "ObjectNum", 0));
pComp->Value(mkNamingAdapt(Strict, "Strict", C4AulScriptStrict::MAXSTRICT));
Expand Down Expand Up @@ -1539,6 +1547,12 @@ void C4ControlInternalScriptBase::Execute() const
{
if (!Allowed()) return;

C4Section *const section{Game.GetSectionByIndex(sectionIndex)};
if (!section)
{
return;
}

const auto scope = Scope();
// execute
C4Object *pObj = nullptr;
Expand All @@ -1552,7 +1566,13 @@ void C4ControlInternalScriptBase::Execute() const
else
// default: Fallback to global context
pScript = &Game.ScriptEngine;
pScript->DirectExec(pObj, FormatScript().getData(), "internal script");
pScript->DirectExec(*section, pObj, FormatScript().getData(), "internal script");
}

void C4ControlInternalScriptBase::CompileFunc(StdCompiler *const comp)
{
comp->Value(mkNamingAdapt(mkIntPackAdapt(sectionIndex), "Section", -1));
C4ControlPacket::CompileFunc(comp);
}

void C4ControlInternalPlayerScriptBase::CompileFunc(StdCompiler *pComp)
Expand Down
Loading

0 comments on commit 926016d

Please sign in to comment.