From 171211c4e2c8db036d5d33cf8d8f190a1748debd Mon Sep 17 00:00:00 2001 From: JeffR Date: Sat, 21 Feb 2026 11:03:07 -0600 Subject: [PATCH] Caches the processed line in CodeBlock for better assert reporting Adds additional context on eval and evaluate calls to better isolate script executions that are throwing errors, such as via command fields or eval() calls. --- Engine/source/T3D/trigger.cpp | 16 +++++++++++++--- Engine/source/console/consoleFunctions.cpp | 3 +-- Engine/source/console/torquescript/astNodes.cpp | 3 ++- Engine/source/console/torquescript/codeBlock.cpp | 2 ++ Engine/source/console/torquescript/codeBlock.h | 1 + Engine/source/console/torquescript/compiler.cpp | 9 ++++++--- .../source/gui/controls/guiGameListMenuCtrl.cpp | 4 +++- .../source/gui/controls/guiGameSettingsCtrl.cpp | 4 +++- Engine/source/gui/controls/guiListBoxCtrl.cpp | 4 +++- Engine/source/gui/controls/guiMLTextEditCtrl.cpp | 4 +++- Engine/source/gui/core/guiControl.cpp | 4 +++- Engine/source/sim/actionMap.cpp | 8 ++++++-- 12 files changed, 46 insertions(+), 16 deletions(-) diff --git a/Engine/source/T3D/trigger.cpp b/Engine/source/T3D/trigger.cpp index 9df293ba5..5df83f681 100644 --- a/Engine/source/T3D/trigger.cpp +++ b/Engine/source/T3D/trigger.cpp @@ -742,7 +742,10 @@ void Trigger::potentialEnterObject(GameBase* enter) { String command = String("%obj = ") + enter->getIdString() + ";"; command = command + String("%this = ") + getIdString() + ";" + mEnterCommand; - Con::evaluate(command.c_str()); + + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getIdString(); + String context = String::ToString("%s, %s", getGroup(), objectName); + Con::evaluate(command.c_str(), false, context); } if( mDataBlock && testTrippable() && testCondition()) @@ -791,7 +794,10 @@ void Trigger::processTick(const Move* move) { String command = String("%obj = ") + remove->getIdString() + ";"; command = command + String("%this = ") + getIdString() + ";" + mLeaveCommand; - Con::evaluate(command.c_str()); + + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getIdString(); + String context = String::ToString("%s, %s", getGroup(), objectName); + Con::evaluate(command.c_str(), false, context); } if (testTrippable() && testCondition()) mDataBlock->onLeaveTrigger_callback( this, remove ); @@ -800,7 +806,11 @@ void Trigger::processTick(const Move* move) } if (evalCmD(&mTickCommand)) - Con::evaluate(mTickCommand.c_str()); + { + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getIdString(); + String context = String::ToString("%s, %s", getGroup(), objectName); + Con::evaluate(mTickCommand.c_str(), false, context); + } if (mObjects.size() != 0 && testTrippable() && testCondition()) mDataBlock->onTickTrigger_callback( this ); diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 77f1e78c2..5da712e5d 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -2367,8 +2367,7 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou DefineEngineFunction( eval, const char*, ( const char* consoleString, bool echo ), (false), "eval(consoleString)") { - Con::EvalResult returnValue = Con::evaluate(consoleString, echo, NULL); - + Con::EvalResult returnValue = Con::evaluate(consoleString, echo, Platform::makeRelativePathName(Con::getCurrentScriptModulePath(), NULL)); return Con::getReturnBuffer(returnValue.value.getString()); } diff --git a/Engine/source/console/torquescript/astNodes.cpp b/Engine/source/console/torquescript/astNodes.cpp index 6fd28bc58..e1f3f6224 100644 --- a/Engine/source/console/torquescript/astNodes.cpp +++ b/Engine/source/console/torquescript/astNodes.cpp @@ -59,7 +59,8 @@ inline FuncVars* getFuncVars(S32 lineNumber) { if (gFuncVars == &gGlobalScopeFuncVars) { - const char* str = avar("Attemping to use local variable in global scope. File: %s Line: %d", CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineTxt = CodeBlock::smCurrentLineText; + const char* str = avar("Attemping to use local variable in global scope. File: %s Line Num: %d \nLine: %s", CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); scriptErrorHandler(str); } return gFuncVars; diff --git a/Engine/source/console/torquescript/codeBlock.cpp b/Engine/source/console/torquescript/codeBlock.cpp index 5a4bdb30a..cd324767d 100644 --- a/Engine/source/console/torquescript/codeBlock.cpp +++ b/Engine/source/console/torquescript/codeBlock.cpp @@ -35,6 +35,7 @@ using namespace Compiler; bool CodeBlock::smInFunction = false; CodeBlock * CodeBlock::smCodeBlockList = NULL; +StringTableEntry CodeBlock::smCurrentLineText = StringTable->EmptyString(); TorqueScriptParser *CodeBlock::smCurrentParser = NULL; extern FuncVars gEvalFuncVars; @@ -578,6 +579,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in consoleAllocReset(); name = fileName; + smCurrentLineText = inString; if (fileName) { diff --git a/Engine/source/console/torquescript/codeBlock.h b/Engine/source/console/torquescript/codeBlock.h index b9d7dd207..cef6d2683 100644 --- a/Engine/source/console/torquescript/codeBlock.h +++ b/Engine/source/console/torquescript/codeBlock.h @@ -61,6 +61,7 @@ private: public: static bool smInFunction; static TorqueScriptParser * smCurrentParser; + static StringTableEntry smCurrentLineText; static CodeBlock *getCodeBlockList() { diff --git a/Engine/source/console/torquescript/compiler.cpp b/Engine/source/console/torquescript/compiler.cpp index 51bf7c0c5..24e9135cc 100644 --- a/Engine/source/console/torquescript/compiler.cpp +++ b/Engine/source/console/torquescript/compiler.cpp @@ -160,7 +160,8 @@ S32 FuncVars::assign(StringTableEntry var, TypeReq currentType, S32 lineNumber, if (found->second.isConstant) { - const char* str = avar("Script Warning: Reassigning variable %s when it is a constant. File: %s Line : %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineTxt = CodeBlock::smCurrentLineText; + const char* str = avar("Script Warning: Reassigning variable %s when it is a constant. File: %s Line Num: %d \nLine: %s", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); scriptErrorHandler(str); } return found->second.reg; @@ -179,7 +180,8 @@ S32 FuncVars::lookup(StringTableEntry var, S32 lineNumber) if (found == vars.end()) { - const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineTxt = CodeBlock::smCurrentLineText; + const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line Num: %d \nLine: %s", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); scriptErrorHandler(str); return assign(var, TypeReqString, lineNumber, false); @@ -194,7 +196,8 @@ TypeReq FuncVars::lookupType(StringTableEntry var, S32 lineNumber) if (found == vars.end()) { - const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineText = CodeBlock::smCurrentLineText; + const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line Num: %d \nLine: %s", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); assign(var, TypeReqString, lineNumber, false); diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index fb69fbc71..a81551d0e 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -974,7 +974,9 @@ void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command) if (command && command[0]) { setThisControl(); - Con::evaluate(command, false, __FILE__); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate(command, false, context); } } diff --git a/Engine/source/gui/controls/guiGameSettingsCtrl.cpp b/Engine/source/gui/controls/guiGameSettingsCtrl.cpp index 0b1e7ebea..ea3fd2ece 100644 --- a/Engine/source/gui/controls/guiGameSettingsCtrl.cpp +++ b/Engine/source/gui/controls/guiGameSettingsCtrl.cpp @@ -494,7 +494,9 @@ void GuiGameSettingsCtrl::doScriptCommand(StringTableEntry command) if (command && command[0]) { setThisControl(); - Con::evaluate(command, false, __FILE__); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate(command, false, context); } } diff --git a/Engine/source/gui/controls/guiListBoxCtrl.cpp b/Engine/source/gui/controls/guiListBoxCtrl.cpp index 66328b2b3..5a5a81e6a 100644 --- a/Engine/source/gui/controls/guiListBoxCtrl.cpp +++ b/Engine/source/gui/controls/guiListBoxCtrl.cpp @@ -1539,7 +1539,9 @@ StringTableEntry GuiListBoxCtrl::_makeMirrorItemName( SimObject *inObj ) Con::setIntVariable( "$ThisControl", getId() ); Con::setIntVariable( "$ThisObject", inObj->getId() ); - outName = StringTable->insert( Con::evaluate( mMakeNameCallback ).value, true ); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + outName = StringTable->insert( Con::evaluate( mMakeNameCallback, false, context).value, true ); } else if ( inObj->getName() ) outName = StringTable->insert( inObj->getName() ); diff --git a/Engine/source/gui/controls/guiMLTextEditCtrl.cpp b/Engine/source/gui/controls/guiMLTextEditCtrl.cpp index 75cebfd41..d22300f37 100644 --- a/Engine/source/gui/controls/guiMLTextEditCtrl.cpp +++ b/Engine/source/gui/controls/guiMLTextEditCtrl.cpp @@ -211,7 +211,9 @@ bool GuiMLTextEditCtrl::onKeyDown(const GuiEvent& event) case KEY_ESCAPE: if ( mEscapeCommand[0] ) { - Con::evaluate( mEscapeCommand ); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate( mEscapeCommand, false, context ); return( true ); } return( Parent::onKeyDown( event ) ); diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index bc175e9fb..406a803d4 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -2495,7 +2495,9 @@ void GuiControl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent const char* GuiControl::evaluate( const char* str ) { smThisControl = this; - const char* result = Con::evaluate(str, false).value; + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + const char* result = Con::evaluate(str, false, context).value; smThisControl = NULL; return result; diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 2e9c3b0e7..d392ab3d2 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -1482,8 +1482,12 @@ bool ActionMap::processAction(const InputEventInfo* pEvent) if(pNode->flags & Node::BindCmd) { // it's a bind command - if(pNode->makeConsoleCommand) - Con::evaluate(pNode->makeConsoleCommand); + if (pNode->makeConsoleCommand) + { + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate(pNode->makeConsoleCommand, false, context); + } } else if (pNode->flags & Node::Held) {