Merge branch 'feature/vscript' of https://github.com/mapbase-source/source-sdk-2013 into feature/vscript

This commit is contained in:
Blixibon 2020-05-31 08:57:35 -05:00
commit 82b0460d8f
6 changed files with 198 additions and 33 deletions

View File

@ -13,9 +13,7 @@
#include "characterset.h"
#include "isaverestore.h"
#include "gamerules.h"
#ifdef _WIN32
//#include "vscript_client_nut.h"
#endif
#include "vscript_client.nut"
#ifdef MAPBASE_VSCRIPT
#include "c_world.h"
#include "proxyentity.h"
@ -405,13 +403,13 @@ bool VScriptClientInit()
IGameSystem::RegisterVScriptAllSystems();
RegisterSharedScriptFunctions();
#else
if ( scriptLanguage == SL_SQUIRREL )
{
//g_pScriptVM->Run( g_Script_vscript_client );
}
#endif
if (scriptLanguage == SL_SQUIRREL)
{
g_pScriptVM->Run( g_Script_vscript_client );
}
VScriptRunScript( "mapspawn", false );
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );

View File

@ -1,3 +1,4 @@
static char g_Script_vscript_client[] = R"vscript(
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
//
// Purpose:
@ -17,3 +18,5 @@ function IncludeScript( name, scope = null )
}
return ::DoIncludeScript( name, scope );
}
)vscript";

View File

@ -15,9 +15,7 @@
#include "sceneentity.h" // for exposing scene precache function
#include "isaverestore.h"
#include "gamerules.h"
#ifdef _WIN32
//#include "vscript_server_nut.h"
#endif
#include "vscript_server.nut"
#ifdef MAPBASE_VSCRIPT
#include "world.h"
#endif
@ -555,13 +553,13 @@ bool VScriptServerInit()
IGameSystem::RegisterVScriptAllSystems();
RegisterSharedScriptFunctions();
#else
if ( scriptLanguage == SL_SQUIRREL )
{
//g_pScriptVM->Run( g_Script_vscript_server );
}
#endif
if (scriptLanguage == SL_SQUIRREL)
{
g_pScriptVM->Run( g_Script_vscript_server );
}
VScriptRunScript( "mapspawn", false );
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );

View File

@ -1,3 +1,4 @@
static char g_Script_vscript_server[] = R"vscript(
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
//
// Purpose:
@ -38,7 +39,7 @@ function __ReplaceClosures( script, scope )
local tempParent = { getroottable = function() { return null; } };
local temp = { runscript = script };
delegate tempParent : temp;
temp.set_delegate(tempParent);
temp.runscript()
foreach( key,val in temp )
@ -125,3 +126,4 @@ function __DumpScope( depth, table )
}
}
)vscript";

View File

@ -343,7 +343,7 @@ public:
private:
} g_ScriptConvarLookup;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarLookup, "Convars", SCRIPT_SINGLETON "Provides an interface for getting and setting convars." )
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarLookup, "CConvars", SCRIPT_SINGLETON "Provides an interface for getting and setting convars." )
#ifndef CLIENT_DLL
DEFINE_SCRIPTFUNC( GetClientConvarValue, "Returns the convar value for the entindex as a string. Only works with client convars with the FCVAR_USERINFO flag." )
#endif

View File

@ -199,6 +199,7 @@ public:
HSQUIRRELVM vm_ = nullptr;
HSQOBJECT lastError_;
HSQOBJECT vectorClass_;
HSQOBJECT regexpClass_;
};
SQUserPointer TYPETAG_VECTOR = "VectorTypeTag";
@ -1112,6 +1113,66 @@ void errorfunc(HSQUIRRELVM SQ_UNUSED_ARG(v), const SQChar* format, ...)
va_end(args);
}
const char * ScriptDataTypeToName(ScriptDataType_t datatype)
{
switch (datatype)
{
case FIELD_VOID: return "void";
case FIELD_FLOAT: return "float";
case FIELD_CSTRING: return "string";
case FIELD_VECTOR: return "Vector";
case FIELD_INTEGER: return "int";
case FIELD_BOOLEAN: return "bool";
case FIELD_CHARACTER: return "char";
case FIELD_HSCRIPT: return "handle";
default: return "<unknown>";
}
}
void RegisterDocumentation(HSQUIRRELVM vm, const ScriptFuncDescriptor_t& pFuncDesc, ScriptClassDesc_t* pClassDesc = nullptr)
{
SquirrelSafeCheck safeCheck(vm);
if (pFuncDesc.m_pszDescription && pFuncDesc.m_pszDescription[0] == SCRIPT_HIDE[0])
return;
char name[256] = "";
if (pClassDesc)
{
V_strcat_safe(name, pClassDesc->m_pszScriptName);
V_strcat_safe(name, "::");
}
V_strcat_safe(name, pFuncDesc.m_pszScriptName);
char signature[256] = "";
V_snprintf(signature, sizeof(signature), "%s %s(", ScriptDataTypeToName(pFuncDesc.m_ReturnType), name);
for (int i = 0; i < pFuncDesc.m_Parameters.Count(); ++i)
{
if (i != 0)
V_strcat_safe(signature, ", ");
V_strcat_safe(signature, ScriptDataTypeToName(pFuncDesc.m_Parameters[i]));
}
V_strcat_safe(signature, ")");
// RegisterHelp(name, signature, description)
sq_pushroottable(vm);
sq_pushstring(vm, "RegisterHelp", -1);
sq_get(vm, -2);
sq_remove(vm, -2);
sq_pushroottable(vm);
sq_pushstring(vm, name, -1);
sq_pushstring(vm, signature, -1);
sq_pushstring(vm, pFuncDesc.m_pszDescription ? pFuncDesc.m_pszDescription : "", -1);
sq_call(vm, 4, SQFalse, SQFalse);
sq_pop(vm, 1);
}
bool SquirrelVM::Init()
{
@ -1149,6 +1210,33 @@ bool SquirrelVM::Init()
sqstd_seterrorhandlers(vm_);
{
// Unfortunately we can not get the pattern from a regexp instance
// so we need to wrap it with our own to get it.
if (Run(R"script(
class regexp extends regexp
{
constructor(pattern)
{
base.constructor(pattern);
pattern_ = pattern;
}
pattern_="";
}
)script") == SCRIPT_ERROR)
{
this->Shutdown();
return false;
}
sq_resetobject(&regexpClass_);
sq_pushstring(vm_, "regexp", -1);
sq_rawget(vm_, -2);
sq_getstackobj(vm_, -1, &regexpClass_);
sq_addref(vm_, &regexpClass_);
sq_pop(vm_, 1);
}
sq_pop(vm_, 1);
}
@ -1194,13 +1282,67 @@ bool SquirrelVM::Init()
chain = [];
}
DocumentedFuncs <- {}
function RegisterHelp(name, signature, description)
{
if (description.len() && description[0] == '#')
{
// This is an alias function, could use split() if we could guarantee
// that ':' would not occur elsewhere in the description and Squirrel had
// a convience join() function -- It has split()
local colon = description.find(":");
if (colon == null)
colon = description.len();
local alias = description.slice(1, colon);
description = description.slice(colon + 1);
name = alias;
signature = null;
}
DocumentedFuncs[name] <- [signature, description];
}
function PrintHelp(pattern = "*")
{
local foundMatches = false;
foreach(name, doc in DocumentedFuncs)
{
if (pattern == "*" || name.tolower().find(pattern.tolower()) != null)
{
foundMatches = true;
printl("Function: " + name);
if (doc[0] == null)
{
// Is an aliased function
print("Signature: function " + name + "(");
foreach(k,v in this[name].getinfos()["parameters"])
{
if (k == 0 && v == "this") continue;
if (k > 1) print(", ");
print(v);
}
printl(")");
}
else
{
printl("Signature: " + doc[0]);
}
if (doc[1].len())
printl("Description: " + doc[1]);
print("\n");
}
}
if (!foundMatches)
printl("Pattern " + pattern + " not found");
}
)script") != SCRIPT_DONE)
{
this->Shutdown();
return false;
}
return true;
}
@ -1208,6 +1350,9 @@ void SquirrelVM::Shutdown()
{
if (vm_)
{
sq_release(vm_, &vectorClass_);
sq_release(vm_, &regexpClass_);
sq_close(vm_);
vm_ = nullptr;
}
@ -1516,6 +1661,8 @@ void SquirrelVM::RegisterFunction(ScriptFunctionBinding_t* pScriptFunction)
sq_newslot(vm_, -3, isStatic);
sq_pop(vm_, 1);
RegisterDocumentation(vm_, pScriptFunction->m_desc);
}
bool SquirrelVM::RegisterClass(ScriptClassDesc_t* pClassDesc)
@ -1587,6 +1734,8 @@ bool SquirrelVM::RegisterClass(ScriptClassDesc_t* pClassDesc)
sq_setparamscheck(vm_, scriptFunction.m_desc.m_Parameters.Count() + 1, typemask);
bool isStatic = false;
sq_newslot(vm_, -3, isStatic);
RegisterDocumentation(vm_, scriptFunction.m_desc, pClassDesc);
}
sq_pushstring(vm_, pClassDesc->m_pszScriptName, -1);
@ -2164,18 +2313,9 @@ void SquirrelVM::WriteObject(CUtlBuffer* pBuffer, WriteStateMap& writeState, SQI
// so we just check against the only class we need to deal with at the moment
// which is "regexp"
const char* builtinName = nullptr;
if (_class(obj) == _class(regexpClass_))
{
HSQOBJECT builtin;
sq_resetobject(&builtin);
sq_pushroottable(vm_);
sq_pushstring(vm_, "regexp", -1);
sq_rawget(vm_, -2);
sq_getstackobj(vm_, -1, &builtin);
sq_pop(vm_, 2);
if (_class(obj) == _class(builtin))
{
builtinName = "regexp";
}
builtinName = "regexp";
}
if (builtinName)
@ -2240,6 +2380,16 @@ void SquirrelVM::WriteObject(CUtlBuffer* pBuffer, WriteStateMap& writeState, SQI
WriteObject(pBuffer, writeState, -1);
sq_pop(vm_, 1);
if (_instance(obj)->_class == _class(regexpClass_))
{
sq_push(vm_, idx);
sq_pushstring(vm_, "pattern_", -1);
sq_rawget(vm_, -2);
WriteObject(pBuffer, writeState, -1);
sq_pop(vm_, 2);
break;
}
{
// HACK: No way to get the default values part from accessing the class directly
SQUnsignedInteger nvalues = _instance(obj)->_class->_defaultvalues.size();
@ -2613,15 +2763,29 @@ void SquirrelVM::ReadObject(CUtlBuffer* pBuffer, ReadStateMap& readState)
ReadObject(pBuffer, readState);
HSQOBJECT klass;
sq_resetobject(&klass);
sq_getstackobj(vm_, -1, &klass);
if (_class(klass) == _class(regexpClass_))
{
sq_pushnull(vm_);
ReadObject(pBuffer, readState);
sq_call(vm_, 2, SQTrue, SQFalse);
sq_getstackobj(vm_, -1, obj);
sq_addref(vm_, obj);
sq_remove(vm_, -2);
break;
}
SQUserPointer typetag;
sq_gettypetag(vm_, -1, &typetag);
if (typetag && typetag != TYPETAG_VECTOR &&
((ScriptClassDesc_t*)typetag)->m_pszDescription[0] == SCRIPT_SINGLETON[0])
{
HSQOBJECT klass;
sq_resetobject(&klass);
sq_getstackobj(vm_, -1, &klass);
sq_poptop(vm_);
Assert(sq_isclass(klass));