mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-09-15 16:57:19 +02:00
Compare commits
25 Commits
5a57bf2fbf
...
8d15f4b6
Author | SHA1 | Date | |
---|---|---|---|
|
8d15f4b6e9 | ||
|
c0d142ab34 | ||
|
f77ec9482f | ||
|
4fc1e892f7 | ||
|
015047a935 | ||
|
bc1fc1d245 | ||
|
2a069f3040 | ||
|
d295828545 | ||
|
483ac37bdb | ||
|
78dc76e6b4 | ||
|
e29070af49 | ||
|
1f25b3ea60 | ||
|
52cfa235be | ||
|
ec7f1183d8 | ||
|
a788e059a5 | ||
|
5f20ffc4de | ||
|
08106156c4 | ||
|
60119ff8fa | ||
|
f4720ae77a | ||
|
c9fb257f48 | ||
|
475a428366 | ||
|
42ac0e32b7 | ||
|
3e75e36cdf | ||
|
ac7d18f297 | ||
|
39473a68f4 |
@@ -3,7 +3,7 @@ project(SqMod)
|
|||||||
|
|
||||||
# This plug-in only works on 64-bit
|
# This plug-in only works on 64-bit
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
message(FATAL_ERROR "SqMod does not support 32-but platforms anymore.")
|
message(FATAL_ERROR "SqMod does not support 32-bit platforms anymore.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Tell CMake where to find our scripts
|
# Tell CMake where to find our scripts
|
||||||
@@ -18,7 +18,7 @@ option(ENABLE_BUILTIN_MYSQL_C "Enable built-in MySQL connector library" OFF)
|
|||||||
#option(FORCE_32BIT_BIN "Create a 32-bit executable binary if the compiler defaults to 64-bit." OFF)
|
#option(FORCE_32BIT_BIN "Create a 32-bit executable binary if the compiler defaults to 64-bit." OFF)
|
||||||
# This option should only be available in certain conditions
|
# This option should only be available in certain conditions
|
||||||
if(WIN32 AND MINGW)
|
if(WIN32 AND MINGW)
|
||||||
option(COPY_DEPENDENCIES "Copy deppendent DLLs into the deps folder." OFF)
|
option(COPY_DEPENDENCIES "Copy dependent DLLs into the deps folder." OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# C++14 is mandatory
|
# C++14 is mandatory
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
@@ -300,6 +301,21 @@ String AABB::ToString() const
|
|||||||
return fmt::format("{},{},{},{},{},{}", min.x, min.y, min.z, max.x, max.y, max.z);
|
return fmt::format("{},{},{},{},{},{}", min.x, min.y, min.z, max.x, max.y, max.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void AABB::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{min:{{x:{},y:{},z:{}}},max:{{x:{},y:{},z:{}}},",
|
||||||
|
min.x, min.y, min.z, max.x, max.y, max.z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{min:[{},{},{}],max:[{},{},{}]}},",
|
||||||
|
min.x, min.y, min.z, max.x, max.y, max.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void AABB::SetStr(SQChar delim, StackStrF & values)
|
void AABB::SetStr(SQChar delim, StackStrF & values)
|
||||||
{
|
{
|
||||||
@@ -793,6 +809,7 @@ void Register_AABB(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &AABB::ToString)
|
.Func(_SC("_tostring"), &AABB::ToString)
|
||||||
|
.Func(_SC("_tojson"), &AABB::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< AABB >, SQFloat, SQInteger, bool, std::nullptr_t, AABB >)
|
||||||
|
@@ -304,6 +304,11 @@ struct AABB
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set the values extracted from the specified string using the specified delimiter.
|
* Set the values extracted from the specified string using the specified delimiter.
|
||||||
*/
|
*/
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -360,6 +361,19 @@ String Circle::ToString() const
|
|||||||
return fmt::format("{},{},{}", pos.x, pos.y, rad);
|
return fmt::format("{},{},{}", pos.x, pos.y, rad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Circle::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},r:{}}},", pos.x, pos.y, rad);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{}],", pos.x, pos.y, rad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Circle::SetRadius(Value nr)
|
void Circle::SetRadius(Value nr)
|
||||||
{
|
{
|
||||||
@@ -552,6 +566,7 @@ void Register_Circle(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Circle::ToString)
|
.Func(_SC("_tostring"), &Circle::ToString)
|
||||||
|
.Func(_SC("_toJSON"), &Circle::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Circle >, SQFloat, SQInteger, bool, std::nullptr_t, Circle >)
|
||||||
|
@@ -341,6 +341,11 @@ struct Circle
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set the specified radius.
|
* Set the specified radius.
|
||||||
*/
|
*/
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -481,6 +482,19 @@ String Color3::ToString() const
|
|||||||
return fmt::format("{},{},{}", r, g, b);
|
return fmt::format("{},{},{}", r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Color3::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{r:{},g:{},b:{}}},", r, g, b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{}],", r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Color3::SetScalar(Value ns)
|
void Color3::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -741,6 +755,7 @@ void Register_Color3(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Color3::ToString)
|
.Func(_SC("_tostring"), &Color3::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Color3::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Color3 >, SQFloat, SQInteger, bool, std::nullptr_t, Color3 >)
|
||||||
|
@@ -405,6 +405,11 @@ struct Color3
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -506,6 +507,19 @@ String Color4::ToString() const
|
|||||||
return fmt::format("{},{},{},{}", r, g, b, a);
|
return fmt::format("{},{},{},{}", r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Color4::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{r:{},g:{},b:{},a:{}}},", r, g, b, a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Color4::SetScalar(Value ns)
|
void Color4::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -781,6 +795,7 @@ void Register_Color4(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Color4::ToString)
|
.Func(_SC("_tostring"), &Color4::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Color4::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Color4 >, SQFloat, SQInteger, bool, std::nullptr_t, Color4 >)
|
||||||
|
@@ -405,6 +405,11 @@ struct Color4
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -349,6 +350,19 @@ String Quaternion::ToString() const
|
|||||||
return fmt::format("{},{},{},{}", x, y, z, w);
|
return fmt::format("{},{},{},{}", x, y, z, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Quaternion::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{},w:{}}},", x, y, z, w);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", x, y, z, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Quaternion::SetScalar(Value ns)
|
void Quaternion::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -775,6 +789,7 @@ void Register_Quaternion(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Quaternion::ToString)
|
.Func(_SC("_tostring"), &Quaternion::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Quaternion::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Quaternion >, SQFloat, SQInteger, bool, std::nullptr_t, Quaternion >)
|
||||||
|
@@ -296,6 +296,11 @@ struct Quaternion
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -6,6 +6,9 @@
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
struct CtxJSON;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Helper constants used by the bas types.
|
* Helper constants used by the bas types.
|
||||||
*/
|
*/
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -360,6 +361,19 @@ String Sphere::ToString() const
|
|||||||
return fmt::format("{},{},{},{}", pos.x, pos.y, pos.z, rad);
|
return fmt::format("{},{},{},{}", pos.x, pos.y, pos.z, rad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Sphere::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{},r:{}}},", pos.x, pos.y, pos.z, rad);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", pos.x, pos.y, pos.z, rad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Sphere::SetRadius(Value nr)
|
void Sphere::SetRadius(Value nr)
|
||||||
{
|
{
|
||||||
@@ -527,6 +541,7 @@ void Register_Sphere(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Sphere::ToString)
|
.Func(_SC("_tostring"), &Sphere::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Sphere::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Sphere >, SQFloat, SQInteger, bool, std::nullptr_t, Sphere >)
|
||||||
|
@@ -341,6 +341,11 @@ struct Sphere
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set the specified radius.
|
* Set the specified radius.
|
||||||
*/
|
*/
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -295,6 +296,19 @@ String Vector2::ToString() const
|
|||||||
return fmt::format("{},{}", x, y);
|
return fmt::format("{},{}", x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Vector2::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{}}},", x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{}],", x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Vector2::SetScalar(Value ns)
|
void Vector2::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -428,6 +442,7 @@ void Register_Vector2(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Vector2::ToString)
|
.Func(_SC("_tostring"), &Vector2::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Vector2::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector2 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2 >)
|
||||||
|
@@ -285,6 +285,11 @@ struct Vector2
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -441,6 +442,19 @@ String Vector2i::ToString() const
|
|||||||
return fmt::format("{},{}", x, y);
|
return fmt::format("{},{}", x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Vector2i::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{}}},", x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{}],", x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Vector2i::SetScalar(Value ns)
|
void Vector2i::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -574,6 +588,7 @@ void Register_Vector2i(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Vector2i::ToString)
|
.Func(_SC("_tostring"), &Vector2i::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Vector2i::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector2i >, SQFloat, SQInteger, bool, std::nullptr_t, Vector2i >)
|
||||||
|
@@ -390,6 +390,11 @@ struct Vector2i
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -331,6 +332,19 @@ String Vector3::ToString() const
|
|||||||
return fmt::format("{},{},{}", x, y, z);
|
return fmt::format("{},{},{}", x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Vector3::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{}}},", x, y, z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{}],", x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Vector3::SetScalar(Value ns)
|
void Vector3::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -696,6 +710,7 @@ void Register_Vector3(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Vector3::ToString)
|
.Func(_SC("_tostring"), &Vector3::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Vector3::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector3 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector3 >)
|
||||||
|
@@ -297,6 +297,11 @@ struct Vector3
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "Base/DynArg.hpp"
|
#include "Base/DynArg.hpp"
|
||||||
#include "Core/Buffer.hpp"
|
#include "Core/Buffer.hpp"
|
||||||
#include "Core/Utility.hpp"
|
#include "Core/Utility.hpp"
|
||||||
|
#include "Library/JSON.hpp"
|
||||||
#include "Library/Numeric/Random.hpp"
|
#include "Library/Numeric/Random.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -344,6 +345,19 @@ String Vector4::ToString() const
|
|||||||
return fmt::format("{},{},{},{}", x, y, z, w);
|
return fmt::format("{},{},{},{}", x, y, z, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Vector4::ToJSON(CtxJSON & ctx) const
|
||||||
|
{
|
||||||
|
if (ctx.mObjectOverArray)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "{{x:{},y:{},z:{},w:{}}},", x, y, z, w);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(ctx.mOutput), "[{},{},{},{}],", x, y, z, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Vector4::SetScalar(Value ns)
|
void Vector4::SetScalar(Value ns)
|
||||||
{
|
{
|
||||||
@@ -526,6 +540,7 @@ void Register_Vector4(HSQUIRRELVM vm)
|
|||||||
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
||||||
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
||||||
.Func(_SC("_tostring"), &Vector4::ToString)
|
.Func(_SC("_tostring"), &Vector4::ToString)
|
||||||
|
.Func(_SC("_tojson"), &Vector4::ToJSON)
|
||||||
// Meta-methods
|
// Meta-methods
|
||||||
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
||||||
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< Vector4 >, SQFloat, SQInteger, bool, std::nullptr_t, Vector4 >)
|
||||||
|
@@ -295,6 +295,11 @@ struct Vector4
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String ToString() const;
|
SQMOD_NODISCARD String ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a JSON string.
|
||||||
|
*/
|
||||||
|
void ToJSON(CtxJSON & ctx) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Set all components to the specified scalar value.
|
* Set all components to the specified scalar value.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
# Create the Squirrel module
|
# Create the Squirrel module
|
||||||
add_library(SqModule MODULE SqBase.hpp Main.cpp
|
add_library(SqModule MODULE SqBase.hpp Main.cpp
|
||||||
|
# SDK
|
||||||
|
SDK/sqmod.h
|
||||||
# VCMP
|
# VCMP
|
||||||
VCMP/vcmp.h
|
VCMP/vcmp.h
|
||||||
VCMP/vcmp20.h
|
VCMP/vcmp20.h
|
||||||
@@ -114,6 +116,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
|||||||
Core.cpp Core.hpp
|
Core.cpp Core.hpp
|
||||||
Logger.cpp Logger.hpp
|
Logger.cpp Logger.hpp
|
||||||
Register.cpp
|
Register.cpp
|
||||||
|
Exports.cpp
|
||||||
)
|
)
|
||||||
# Various definitions required by the plug-in
|
# Various definitions required by the plug-in
|
||||||
target_compile_definitions(SqModule PRIVATE SCRAT_USE_EXCEPTIONS=1)
|
target_compile_definitions(SqModule PRIVATE SCRAT_USE_EXCEPTIONS=1)
|
||||||
@@ -201,6 +204,7 @@ else(WIN32)
|
|||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
# Include current directory in the search path
|
# Include current directory in the search path
|
||||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/SDK)
|
||||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/VCMP)
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/VCMP)
|
||||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Sqrat)
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Sqrat)
|
||||||
# Include PCRE directory in the header search path
|
# Include PCRE directory in the header search path
|
||||||
@@ -222,12 +226,12 @@ if(WIN32 AND MINGW AND COPY_DEPENDENCIES)
|
|||||||
endif()
|
endif()
|
||||||
# Make sure the deps folder exists
|
# Make sure the deps folder exists
|
||||||
file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
# Copy dependencies into the plug-ins folder (only so it can be distributed with the DLL)
|
# Copy dependencies into the deps folder (only so it can be distributed with the DLL)
|
||||||
file(COPY "${MINGW_BIN_PATH}/zlib1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/zlib1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libpq.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libpq.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libzstd.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libzstd.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libpsl-5.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libpsl-5.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libffi-7.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libffi-8.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libcurl-4.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libcurl-4.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libssh2-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libssh2-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libidn2-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libidn2-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
@@ -245,17 +249,17 @@ if(WIN32 AND MINGW AND COPY_DEPENDENCIES)
|
|||||||
file(COPY "${MINGW_BIN_PATH}/libp11-kit-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libp11-kit-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libbrotlidec.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libbrotlidec.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libbrotlicommon.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libbrotlicommon.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libunistring-2.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libunistring-5.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libnghttp2-14.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libnghttp2-14.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libwinpthread-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libwinpthread-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libstdc++-6.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libstdc++-6.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT FORCE_32BIT_BIN)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT FORCE_32BIT_BIN)
|
||||||
file(COPY "${MINGW_BIN_PATH}/libgcc_s_seh-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libgcc_s_seh-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libssl-1_1-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libssl-3-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-1_1-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libcrypto-3-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
else()
|
else()
|
||||||
file(COPY "${MINGW_BIN_PATH}/libssl-1_1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libssl-3.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-1_1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libcrypto-3.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
endif()
|
endif()
|
||||||
if(POCO_UNBUNDLED)
|
if(POCO_UNBUNDLED)
|
||||||
file(COPY "${MINGW_BIN_PATH}/libexpat-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libexpat-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
|
123
module/Core.cpp
123
module/Core.cpp
@@ -161,6 +161,7 @@ Core::Core() noexcept
|
|||||||
, m_Scripts()
|
, m_Scripts()
|
||||||
, m_PendingScripts()
|
, m_PendingScripts()
|
||||||
, m_Options()
|
, m_Options()
|
||||||
|
, m_ExtCommands{nullptr, nullptr, nullptr, nullptr}
|
||||||
, m_Blips()
|
, m_Blips()
|
||||||
, m_Checkpoints()
|
, m_Checkpoints()
|
||||||
, m_KeyBinds()
|
, m_KeyBinds()
|
||||||
@@ -441,9 +442,9 @@ bool Core::Execute()
|
|||||||
m_LockPostLoadSignal = false;
|
m_LockPostLoadSignal = false;
|
||||||
m_LockUnloadSignal = false;
|
m_LockUnloadSignal = false;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to register their API");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins that the API is being registered");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xDEADBABE, "");
|
_Func->SendPluginCommand(SQMOD_LOAD_CMD, SQMOD_HOST_NAME);
|
||||||
|
|
||||||
// Load pending scripts while we're in the bounds of the allowed recursiveness
|
// Load pending scripts while we're in the bounds of the allowed recursiveness
|
||||||
for (unsigned levels = 0; !m_PendingScripts.empty() && (levels < 8); ++levels)
|
for (unsigned levels = 0; !m_PendingScripts.empty() && (levels < 8); ++levels)
|
||||||
@@ -511,9 +512,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
// Clear the callbacks
|
// Clear the callbacks
|
||||||
ResetSignalPair(mOnUnload);
|
ResetSignalPair(mOnUnload);
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release their resources");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release their resources");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xDEADC0DE, "");
|
_Func->SendPluginCommand(SQMOD_TERMINATE_CMD, SQMOD_HOST_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
cLogDbg(m_Verbosity >= 1, "Clearing the entity containers");
|
cLogDbg(m_Verbosity >= 1, "Clearing the entity containers");
|
||||||
@@ -596,9 +597,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
HSQUIRRELVM sq_vm = m_VM;
|
HSQUIRRELVM sq_vm = m_VM;
|
||||||
m_VM = nullptr;
|
m_VM = nullptr;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine is closing");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine is closing");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xBAAAAAAD, "");
|
_Func->SendPluginCommand(SQMOD_CLOSING_CMD, SQMOD_HOST_NAME);
|
||||||
// Release any callbacks from the logger
|
// Release any callbacks from the logger
|
||||||
Logger::Get().Release();
|
Logger::Get().Release();
|
||||||
cLogDbg(m_Verbosity >= 2, "Closing Virtual Machine");
|
cLogDbg(m_Verbosity >= 2, "Closing Virtual Machine");
|
||||||
@@ -629,9 +630,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
// Destroy the VM context, if any
|
// Destroy the VM context, if any
|
||||||
delete ctx;
|
delete ctx;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release the virtual machine");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine was closed");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xDEADBEAF, "");
|
_Func->SendPluginCommand(SQMOD_RELEASED_CMD, SQMOD_HOST_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputMessage("Squirrel plug-in was successfully terminated");
|
OutputMessage("Squirrel plug-in was successfully terminated");
|
||||||
@@ -904,6 +905,81 @@ String Core::FetchCodeLine(const SQChar * src, SQInteger line, bool trim)
|
|||||||
return script->FetchLine(line, trim);
|
return script->FetchLine(line, trim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int32_t Core::RegisterExtCommand(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
ExtPluginCommand_t * slot = nullptr;
|
||||||
|
// Find a free slot or matching function pointer in the pool
|
||||||
|
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||||
|
{
|
||||||
|
// Is this slot available and are we still looking for a slot?
|
||||||
|
if (m_ExtCommands[i] == nullptr && slot == nullptr)
|
||||||
|
{
|
||||||
|
slot = &m_ExtCommands[i]; // Found a slot
|
||||||
|
}
|
||||||
|
// We keep looking for duplicates even if we found the slot
|
||||||
|
else if (m_ExtCommands[i] == fn)
|
||||||
|
{
|
||||||
|
return 0; // Already registered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Do we have a free slot?
|
||||||
|
if (slot != nullptr)
|
||||||
|
{
|
||||||
|
*slot = fn; // Use this slot
|
||||||
|
return 1; // Successfully registered
|
||||||
|
}
|
||||||
|
// No space in the pool
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int32_t Core::UnregisterExtCommand(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
// Find the matching function pointer
|
||||||
|
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||||
|
{
|
||||||
|
// Is this the same pointer?
|
||||||
|
if (m_ExtCommands[i] != nullptr && m_ExtCommands[i] == fn)
|
||||||
|
{
|
||||||
|
// Forget about it
|
||||||
|
m_ExtCommands[i] = nullptr;
|
||||||
|
return 1; // Successfully unregistered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No space
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int32_t Core::SendExtCommand(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
int32_t count = 0;
|
||||||
|
// Send the command to all registered function pointers
|
||||||
|
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||||
|
{
|
||||||
|
if (m_ExtCommands[i] != nullptr)
|
||||||
|
{
|
||||||
|
const int32_t r = m_ExtCommands[i](target, req, tag, data, size);
|
||||||
|
// Command processed
|
||||||
|
++count;
|
||||||
|
// Command failed?
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
LogErr("External command failed (%i): target(%i), req(%i), tag(%i), data(%p), size (%zu)",
|
||||||
|
r, target, req, tag, data, size);
|
||||||
|
}
|
||||||
|
// Command consumed?
|
||||||
|
else if (r > 0)
|
||||||
|
{
|
||||||
|
break; // This function pointer requested exclusive access over this command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return how many function pointers received this command
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
|
bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
|
||||||
{
|
{
|
||||||
@@ -2371,6 +2447,8 @@ void Core::InitEvents()
|
|||||||
InitSignalPair(mOnServerOption, m_Events, "ServerOption");
|
InitSignalPair(mOnServerOption, m_Events, "ServerOption");
|
||||||
InitSignalPair(mOnScriptReload, m_Events, "ScriptReload");
|
InitSignalPair(mOnScriptReload, m_Events, "ScriptReload");
|
||||||
InitSignalPair(mOnScriptLoaded, m_Events, "ScriptLoaded");
|
InitSignalPair(mOnScriptLoaded, m_Events, "ScriptLoaded");
|
||||||
|
InitSignalPair(mOnExtCommandReply, m_Events, "ExtCommandReply");
|
||||||
|
InitSignalPair(mOnExtCommandEvent, m_Events, "ExtCommandEvent");
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Core::DropEvents()
|
void Core::DropEvents()
|
||||||
@@ -2516,6 +2594,8 @@ void Core::DropEvents()
|
|||||||
ResetSignalPair(mOnServerOption);
|
ResetSignalPair(mOnServerOption);
|
||||||
ResetSignalPair(mOnScriptReload);
|
ResetSignalPair(mOnScriptReload);
|
||||||
ResetSignalPair(mOnScriptLoaded);
|
ResetSignalPair(mOnScriptLoaded);
|
||||||
|
ResetSignalPair(mOnExtCommandReply);
|
||||||
|
ResetSignalPair(mOnExtCommandEvent);
|
||||||
m_Events.Release();
|
m_Events.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2861,6 +2941,31 @@ static LightObj & SqGetClientDataBuffer()
|
|||||||
return Core::Get().GetClientDataBuffer();
|
return Core::Get().GetClientDataBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static SQInteger SqSendExtCommand(int32_t target, int32_t req, int32_t tag, SqBuffer & buffer)
|
||||||
|
{
|
||||||
|
// Default to an empty/null buffer
|
||||||
|
const uint8_t * data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
// Does the buffer actually point to anything?
|
||||||
|
if (buffer.GetRef())
|
||||||
|
{
|
||||||
|
data = buffer.GetRef()->Begin< uint8_t >();
|
||||||
|
size = buffer.GetRef()->PositionAs< size_t >();
|
||||||
|
}
|
||||||
|
// Forward the request
|
||||||
|
return Core::Get().SendExtCommand(target, req, tag, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static SQInteger SqSendExtCommandStr(int32_t target, int32_t req, int32_t tag, StackStrF & str)
|
||||||
|
{
|
||||||
|
// Forward the request
|
||||||
|
return Core::Get().SendExtCommand(target, req, tag,
|
||||||
|
reinterpret_cast< const uint8_t * >(str.mPtr),
|
||||||
|
str.mLen <= 0 ? 0 : static_cast< size_t >(str.mLen));
|
||||||
|
}
|
||||||
|
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
void Register_Core(HSQUIRRELVM vm)
|
void Register_Core(HSQUIRRELVM vm)
|
||||||
{
|
{
|
||||||
@@ -2910,6 +3015,8 @@ void Register_Core(HSQUIRRELVM vm)
|
|||||||
.Func(_SC("DestroyPickup"), &SqDelPickup)
|
.Func(_SC("DestroyPickup"), &SqDelPickup)
|
||||||
.Func(_SC("DestroyVehicle"), &SqDelVehicle)
|
.Func(_SC("DestroyVehicle"), &SqDelVehicle)
|
||||||
.Func(_SC("ClientDataBuffer"), &SqGetClientDataBuffer)
|
.Func(_SC("ClientDataBuffer"), &SqGetClientDataBuffer)
|
||||||
|
.Func(_SC("SendExtCommand"), &SqSendExtCommand)
|
||||||
|
.FmtFunc(_SC("SendExtCommandStr"), &SqSendExtCommandStr)
|
||||||
.Func(_SC("OnPreLoad"), &SqGetPreLoadEvent)
|
.Func(_SC("OnPreLoad"), &SqGetPreLoadEvent)
|
||||||
.Func(_SC("OnPostLoad"), &SqGetPostLoadEvent)
|
.Func(_SC("OnPostLoad"), &SqGetPostLoadEvent)
|
||||||
.Func(_SC("OnUnload"), &SqGetUnloadEvent)
|
.Func(_SC("OnUnload"), &SqGetUnloadEvent)
|
||||||
|
@@ -9,6 +9,9 @@
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "SDK/sqmod.h"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
@@ -56,6 +59,8 @@ public:
|
|||||||
typedef std::vector< ScriptSrc > Scripts; // List of loaded scripts.
|
typedef std::vector< ScriptSrc > Scripts; // List of loaded scripts.
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
typedef std::unordered_map< String, String > Options; // List of custom options.
|
typedef std::unordered_map< String, String > Options; // List of custom options.
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
typedef std::array< ExtPluginCommand_t, 4 > ExtCommands; // 4 external command parsers should be enough.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -68,6 +73,7 @@ private:
|
|||||||
Scripts m_Scripts; // Loaded scripts objects.
|
Scripts m_Scripts; // Loaded scripts objects.
|
||||||
Scripts m_PendingScripts; // Pending scripts objects.
|
Scripts m_PendingScripts; // Pending scripts objects.
|
||||||
Options m_Options; // Custom configuration options.
|
Options m_Options; // Custom configuration options.
|
||||||
|
ExtCommands m_ExtCommands; // External command parsers pointers.
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
Blips m_Blips; // Blips pool.
|
Blips m_Blips; // Blips pool.
|
||||||
@@ -399,6 +405,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String FetchCodeLine(const SQChar * src, SQInteger line, bool trim = true);
|
SQMOD_NODISCARD String FetchCodeLine(const SQChar * src, SQInteger line, bool trim = true);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Register a pointer to a function used to processes commands from script.
|
||||||
|
* Returns -1 it failed (no free slot), 0 if it was already registered and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t RegisterExtCommand(ExtPluginCommand_t fn);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Remove a pointer to a function used to processes commands from script.
|
||||||
|
* Returns -1 it failed (no free slot) and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t UnregisterExtCommand(ExtPluginCommand_t fn);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Send a command to all functions currently registered to receive them.
|
||||||
|
*/
|
||||||
|
int32_t SendExtCommand(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@@ -710,6 +733,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
void EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t size);
|
void EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Send a response to the script that may have resulted from a previous command.
|
||||||
|
*/
|
||||||
|
void EmitExtCommandReply(int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Forward an event to the script from an external plug-in.
|
||||||
|
*/
|
||||||
|
void EmitExtCommandEvent(int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@@ -864,6 +897,8 @@ public:
|
|||||||
SignalPair mOnServerOption{};
|
SignalPair mOnServerOption{};
|
||||||
SignalPair mOnScriptReload{};
|
SignalPair mOnScriptReload{};
|
||||||
SignalPair mOnScriptLoaded{};
|
SignalPair mOnScriptLoaded{};
|
||||||
|
SignalPair mOnExtCommandReply{};
|
||||||
|
SignalPair mOnExtCommandEvent{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
@@ -285,13 +285,13 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Make sure that the specified element is withing buffer range
|
// Make sure that the specified element is withing buffer range
|
||||||
else if (n > (m_Cap - sizeof(T)))
|
else if (n > (m_Cap - sizeof(T)))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Element of size (%d) at index (%u) is out of buffer capacity (%u)"),
|
ThrowMemExcept(fmt::runtime("Element of size ({}) at index ({}) is out of buffer capacity ({})"),
|
||||||
sizeof(T), n, m_Cap);
|
sizeof(T), n, m_Cap);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -306,13 +306,13 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Make sure that the specified element is withing buffer range
|
// Make sure that the specified element is withing buffer range
|
||||||
else if (n > (m_Cap - sizeof(T)))
|
else if (n > (m_Cap - sizeof(T)))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Element of size (%d) at index (%u) is out of buffer capacity (%u)"),
|
ThrowMemExcept(fmt::runtime("Element of size ({}) at index ({}) is out of buffer capacity ({})"),
|
||||||
sizeof(T), n, m_Cap);
|
sizeof(T), n, m_Cap);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -359,7 +359,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -374,7 +374,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -389,7 +389,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least two elements of this type
|
// Make sure that the buffer can host at least two elements of this type
|
||||||
if (m_Cap < (sizeof(T) * 2))
|
if (m_Cap < (sizeof(T) * 2))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -404,7 +404,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least two elements of this type
|
// Make sure that the buffer can host at least two elements of this type
|
||||||
if (m_Cap < (sizeof(T) * 2))
|
if (m_Cap < (sizeof(T) * 2))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -419,7 +419,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -434,7 +434,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -449,7 +449,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least two elements of this type
|
// Make sure that the buffer can host at least two elements of this type
|
||||||
if (m_Cap < (sizeof(T) * 2))
|
if (m_Cap < (sizeof(T) * 2))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -464,7 +464,7 @@ public:
|
|||||||
// Make sure that the buffer can host at least two elements of this type
|
// Make sure that the buffer can host at least two elements of this type
|
||||||
if (m_Cap < (sizeof(T) * 2))
|
if (m_Cap < (sizeof(T) * 2))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host two elements of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host two elements of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -540,7 +540,7 @@ public:
|
|||||||
// Make sure that at least one element of this type exists after the cursor
|
// Make sure that at least one element of this type exists after the cursor
|
||||||
if ((m_Cur + sizeof(T)) > m_Cap)
|
if ((m_Cur + sizeof(T)) > m_Cap)
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||||
sizeof(T), m_Cur, m_Cap);
|
sizeof(T), m_Cur, m_Cap);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -555,7 +555,7 @@ public:
|
|||||||
// Make sure that at least one element of this type exists after the cursor
|
// Make sure that at least one element of this type exists after the cursor
|
||||||
if ((m_Cur + sizeof(T)) > m_Cap)
|
if ((m_Cur + sizeof(T)) > m_Cap)
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||||
sizeof(T), m_Cur, m_Cap);
|
sizeof(T), m_Cur, m_Cap);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -570,7 +570,7 @@ public:
|
|||||||
// The cursor must have at least one element of this type behind
|
// The cursor must have at least one element of this type behind
|
||||||
if (m_Cur < sizeof(T))
|
if (m_Cur < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Cannot read an element of size (%u) before the cursor at (%u)"),
|
ThrowMemExcept(fmt::runtime("Cannot read an element of size ({}) before the cursor at ({})"),
|
||||||
sizeof(T), m_Cur);
|
sizeof(T), m_Cur);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -585,7 +585,7 @@ public:
|
|||||||
// The cursor must have at least one element of this type behind
|
// The cursor must have at least one element of this type behind
|
||||||
if (m_Cur < sizeof(T))
|
if (m_Cur < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Cannot read an element of size (%u) before the cursor at (%u)"),
|
ThrowMemExcept(fmt::runtime("Cannot read an element of size ({}) before the cursor at ({})"),
|
||||||
sizeof(T), m_Cur);
|
sizeof(T), m_Cur);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -600,13 +600,13 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// There must be buffer left for at least two elements of this type after the cursor
|
// There must be buffer left for at least two elements of this type after the cursor
|
||||||
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
|
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||||
sizeof(T), m_Cur + sizeof(T), m_Cap);
|
sizeof(T), m_Cur + sizeof(T), m_Cap);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -621,13 +621,13 @@ public:
|
|||||||
// Make sure that the buffer can host at least one element of this type
|
// Make sure that the buffer can host at least one element of this type
|
||||||
if (m_Cap < sizeof(T))
|
if (m_Cap < sizeof(T))
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Buffer capacity of (%u) is unable to host an element of size (%u)"),
|
ThrowMemExcept(fmt::runtime("Buffer capacity of ({}) is unable to host an element of size ({})"),
|
||||||
m_Cap, sizeof(T));
|
m_Cap, sizeof(T));
|
||||||
}
|
}
|
||||||
// There must be buffer left for at least two elements of this type after the cursor
|
// There must be buffer left for at least two elements of this type after the cursor
|
||||||
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
|
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)"),
|
ThrowMemExcept(fmt::runtime("Element of size ({}) starting at ({}) exceeds buffer capacity ({})"),
|
||||||
sizeof(T), m_Cur + sizeof(T), m_Cap);
|
sizeof(T), m_Cur + sizeof(T), m_Cap);
|
||||||
}
|
}
|
||||||
// Return the requested element
|
// Return the requested element
|
||||||
@@ -708,7 +708,7 @@ public:
|
|||||||
// See if the requested capacity doesn't exceed the limit
|
// See if the requested capacity doesn't exceed the limit
|
||||||
if (n > Max< T >())
|
if (n > Max< T >())
|
||||||
{
|
{
|
||||||
ThrowMemExcept(fmt::runtime("Requested buffer of (%u) elements exceeds the (%u) limit"), n, Max< T >());
|
ThrowMemExcept(fmt::runtime("Requested buffer of ({}) elements exceeds the ({}) limit"), n, Max< T >());
|
||||||
}
|
}
|
||||||
// Is there an existing buffer?
|
// Is there an existing buffer?
|
||||||
else if (n && !m_Cap)
|
else if (n && !m_Cap)
|
||||||
|
@@ -248,6 +248,14 @@ String SqTypeName(HSQUIRRELVM vm, SQInteger idx)
|
|||||||
return String(val.mPtr, static_cast< size_t >(val.mLen));
|
return String(val.mPtr, static_cast< size_t >(val.mLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
String SqTypeName(HSQUIRRELVM vm, LightObj & obj)
|
||||||
|
{
|
||||||
|
const StackGuard sg(vm);
|
||||||
|
sq_pushobject(vm, obj);
|
||||||
|
return SqTypeName(vm, -1);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
LightObj BufferToStrObj(const Buffer & b)
|
LightObj BufferToStrObj(const Buffer & b)
|
||||||
{
|
{
|
||||||
|
@@ -242,6 +242,11 @@ SQMOD_NODISCARD const SQChar * SqTypeName(SQObjectType type);
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String SqTypeName(HSQUIRRELVM vm, SQInteger idx);
|
SQMOD_NODISCARD String SqTypeName(HSQUIRRELVM vm, SQInteger idx);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the string representation of a certain type from a script object.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD String SqTypeName(HSQUIRRELVM vm, LightObj & obj);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Create a script string instance from a buffer.
|
* Create a script string instance from a buffer.
|
||||||
*/
|
*/
|
||||||
|
@@ -347,7 +347,7 @@ void Core::EmitIncomingConnection(char * player_name, size_t name_buffer_size, c
|
|||||||
// Release any stored buffer information
|
// Release any stored buffer information
|
||||||
m_IncomingNameBuffer = nullptr;
|
m_IncomingNameBuffer = nullptr;
|
||||||
m_IncomingNameCapacity = 0;
|
m_IncomingNameCapacity = 0;
|
||||||
// We catched the exception so we can release the assigned buffer
|
// We caught the exception so we can release the assigned buffer
|
||||||
throw; // re-throw it
|
throw; // re-throw it
|
||||||
}
|
}
|
||||||
// Release any stored buffer information
|
// Release any stored buffer information
|
||||||
@@ -2246,6 +2246,44 @@ void Core::EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t
|
|||||||
m_ClientData.Release();
|
m_ClientData.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Core::EmitExtCommandReply(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE<] Core::ExtCommandReply(%i, %i, %p, %zu)", sender, tag, data, size)
|
||||||
|
// Don't even bother if there's no one listening
|
||||||
|
if (!(mOnExtCommandReply.first->IsEmpty()))
|
||||||
|
{
|
||||||
|
// Allocate a buffer with the received size
|
||||||
|
Buffer b(static_cast< Buffer::SzType >(size));
|
||||||
|
// Replicate the data to the allocated buffer
|
||||||
|
b.Write(0, reinterpret_cast< Buffer::ConstPtr >(data), static_cast< Buffer::SzType >(size));
|
||||||
|
// Prepare an object for the obtained buffer
|
||||||
|
LightObj obj(SqTypeIdentity< SqBuffer >{}, m_VM, std::move(b));
|
||||||
|
// Forward the event call
|
||||||
|
(*mOnExtCommandReply.first)(sender, tag, obj, size);
|
||||||
|
}
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE>] Core::ExtCommandReply")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Core::EmitExtCommandEvent(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE<] Core::ExtCommandEvent(%i, %i, %p, %zu)", sender, tag, data, size)
|
||||||
|
// Don't even bother if there's no one listening
|
||||||
|
if (!(mOnExtCommandEvent.first->IsEmpty()))
|
||||||
|
{
|
||||||
|
// Allocate a buffer with the received size
|
||||||
|
Buffer b(static_cast< Buffer::SzType >(size));
|
||||||
|
// Replicate the data to the allocated buffer
|
||||||
|
b.Write(0, reinterpret_cast< Buffer::ConstPtr >(data), static_cast< Buffer::SzType >(size));
|
||||||
|
// Prepare an object for the obtained buffer
|
||||||
|
LightObj obj(SqTypeIdentity< SqBuffer >{}, m_VM, std::move(b));
|
||||||
|
// Forward the event call
|
||||||
|
(*mOnExtCommandEvent.first)(sender, tag, obj, size);
|
||||||
|
}
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE>] Core::ExtCommandEvent")
|
||||||
|
}
|
||||||
|
|
||||||
#undef NULL_SQOBJ_ // don't need this anymore
|
#undef NULL_SQOBJ_ // don't need this anymore
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@@ -80,7 +80,7 @@ struct ThreadPoolItem
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Invoked in main thread by the thread pool after the task was completed.
|
* Invoked in main thread by the thread pool after the task was completed.
|
||||||
* If it returns true then it will be put back into the queue to be processed again.
|
* If it returns true then it will be put back into the queue to be processed again.
|
||||||
* If the boolean parameter is trye then the thread-pool is in the process of shutting down.
|
* If the boolean parameter is true then the thread-pool is in the process of shutting down.
|
||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD virtual bool OnCompleted(bool SQ_UNUSED_ARG(stop)) { return false; }
|
SQMOD_NODISCARD virtual bool OnCompleted(bool SQ_UNUSED_ARG(stop)) { return false; }
|
||||||
|
|
||||||
@@ -110,13 +110,13 @@ private:
|
|||||||
* Destructor.
|
* Destructor.
|
||||||
*/
|
*/
|
||||||
~ThreadPool();
|
~ThreadPool();
|
||||||
|
public:
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
using Item = std::unique_ptr< ThreadPoolItem >; // Owning pointer of an item.
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
using Pool = std::vector< std::thread >; // Worker container.
|
using Pool = std::vector< std::thread >; // Worker container.
|
||||||
using Item = std::unique_ptr< ThreadPoolItem >; // Owning pointer of an item.
|
|
||||||
// --------------------------------------------------------------------------------------------
|
|
||||||
using Finished = moodycamel::ConcurrentQueue< Item >; // Finished items.
|
using Finished = moodycamel::ConcurrentQueue< Item >; // Finished items.
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
@@ -190,6 +190,14 @@ public:
|
|||||||
Enqueue(Item{item});
|
Enqueue(Item{item});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Queue an item to be processed. Will take ownership of the given pointer!
|
||||||
|
*/
|
||||||
|
template < class T > void CastEnqueue(std::unique_ptr< T > && item)
|
||||||
|
{
|
||||||
|
Enqueue(Item{std::forward< std::unique_ptr< T > >(item)});
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Queue an item to be processed. Will take ownership of the given pointer!
|
* Queue an item to be processed. Will take ownership of the given pointer!
|
||||||
*/
|
*/
|
||||||
|
73
module/Exports.cpp
Normal file
73
module/Exports.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Core.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <sqmod.h>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t RegisterCommandFn(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
return Core::Get().RegisterExtCommand(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t UnregisterCommandFn(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
return Core::Get().UnregisterExtCommand(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t SendCommandFn(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
return Core::Get().SendExtCommand(target, req, tag, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t SendCommandReplyFn(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
// Mark the initialization as successful by default
|
||||||
|
const CoreState cs(SQMOD_SUCCESS);
|
||||||
|
// Forward the call to the script callbacks
|
||||||
|
Core::Get().EmitExtCommandReply(sender, tag, data, size);
|
||||||
|
// Return the last known plug-in state
|
||||||
|
return Core::Get().GetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t SendCommandEventFn(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
// Mark the initialization as successful by default
|
||||||
|
const CoreState cs(SQMOD_SUCCESS);
|
||||||
|
// Forward the call to the script callbacks
|
||||||
|
Core::Get().EmitExtCommandEvent(sender, tag, data, size);
|
||||||
|
// Return the last known plug-in state
|
||||||
|
return Core::Get().GetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static const SQ_MOD_EXPORTS g_SqModExports{
|
||||||
|
sizeof(SQ_MOD_EXPORTS),
|
||||||
|
&RegisterCommandFn,
|
||||||
|
&UnregisterCommandFn,
|
||||||
|
&SendCommandFn,
|
||||||
|
&SendCommandReplyFn,
|
||||||
|
&SendCommandEventFn
|
||||||
|
};
|
||||||
|
|
||||||
|
// The server needs a pointer to a pointer, and a persistent one
|
||||||
|
static const SQ_MOD_EXPORTS * g_SqModExportsPtr = &g_SqModExports;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void InitExports()
|
||||||
|
{
|
||||||
|
// Tell the server about the pointer to the exports structure
|
||||||
|
_Func->ExportFunctions(_Info->pluginId, reinterpret_cast< const void ** >(&g_SqModExportsPtr), sizeof(HSQ_MOD_EXPORTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
@@ -351,6 +351,33 @@ Vector4 SqBuffer::ReadVector4() const
|
|||||||
return {value};
|
return {value};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
extern SQInteger SqFromNativeJSON(HSQUIRRELVM vm, const char * data, size_t size);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQInteger SqBuffer::GetJSON(HSQUIRRELVM vm) const
|
||||||
|
{
|
||||||
|
// Remember the current stack size
|
||||||
|
const SQInteger top = sq_gettop(vm);
|
||||||
|
// Was the JSON string size specified?
|
||||||
|
if (top < 2)
|
||||||
|
{
|
||||||
|
return sq_throwerror(vm, _SC("Please specify the size of the JSON string to parse"));
|
||||||
|
}
|
||||||
|
// Do we even point to a valid buffer?
|
||||||
|
if (!m_Buffer)
|
||||||
|
{
|
||||||
|
return sq_throwerror(vm, _SC("Invalid memory buffer reference"));
|
||||||
|
}
|
||||||
|
// Validate the buffer itself
|
||||||
|
else if (!(*m_Buffer))
|
||||||
|
{
|
||||||
|
return sq_throwerror(vm, _SC("Invalid memory buffer"));
|
||||||
|
}
|
||||||
|
// Attempt to create the JSON object and push it on the stack
|
||||||
|
return SqFromNativeJSON(vm, &m_Buffer->Cursor< char >(), static_cast< size_t >(Var< SQInteger >{vm, 2}.value));
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQInteger SqBuffer::GetCRC32(SQInteger n) const
|
SQInteger SqBuffer::GetCRC32(SQInteger n) const
|
||||||
{
|
{
|
||||||
@@ -500,6 +527,7 @@ void Register_Buffer(HSQUIRRELVM vm)
|
|||||||
.Func(_SC("ADLER32"), &SqBuffer::GetADLER32)
|
.Func(_SC("ADLER32"), &SqBuffer::GetADLER32)
|
||||||
.Func(_SC("Base32"), &SqBuffer::GetBase32)
|
.Func(_SC("Base32"), &SqBuffer::GetBase32)
|
||||||
.Func(_SC("Base64"), &SqBuffer::GetBase64)
|
.Func(_SC("Base64"), &SqBuffer::GetBase64)
|
||||||
|
.SquirrelMethod< SqBuffer, &SqBuffer::GetJSON >(_SC("GetJSON"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -294,33 +294,41 @@ public:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Reposition the edit cursor to the specified number of elements ahead.
|
* Reposition the edit cursor to the specified number of elements ahead.
|
||||||
*/
|
*/
|
||||||
void Advance(SQInteger n) const
|
SqBuffer & Advance(SQInteger n)
|
||||||
{
|
{
|
||||||
Valid().Advance(ConvTo< SzType >::From(n));
|
Valid().Advance(ConvTo< SzType >::From(n));
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Reposition the edit cursor to the specified number of elements behind.
|
* Reposition the edit cursor to the specified number of elements behind.
|
||||||
*/
|
*/
|
||||||
void Retreat(SQInteger n) const
|
SqBuffer & Retreat(SQInteger n)
|
||||||
{
|
{
|
||||||
Valid().Retreat(ConvTo< SzType >::From(n));
|
Valid().Retreat(ConvTo< SzType >::From(n));
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Reposition the edit cursor to a fixed position within the buffer.
|
* Reposition the edit cursor to a fixed position within the buffer.
|
||||||
*/
|
*/
|
||||||
void Move(SQInteger n) const
|
SqBuffer & Move(SQInteger n)
|
||||||
{
|
{
|
||||||
Valid().Move(ConvTo< SzType >::From(n));
|
Valid().Move(ConvTo< SzType >::From(n));
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Append a value to the current cursor location and advance the cursor.
|
* Append a value to the current cursor location and advance the cursor.
|
||||||
*/
|
*/
|
||||||
void Push(SQInteger v) const
|
SqBuffer & Push(SQInteger v)
|
||||||
{
|
{
|
||||||
Valid().Push(ConvTo< Value >::From(v));
|
Valid().Push(ConvTo< Value >::From(v));
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@@ -414,15 +422,17 @@ public:
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Grow the size of the internal buffer by the specified amount of bytes.
|
* Grow the size of the internal buffer by the specified amount of bytes.
|
||||||
*/
|
*/
|
||||||
void Grow(SQInteger n) const
|
SqBuffer & Grow(SQInteger n)
|
||||||
{
|
{
|
||||||
return Valid().Grow(ConvTo< SzType >::From(n) * sizeof(Value));
|
Valid().Grow(ConvTo< SzType >::From(n) * sizeof(Value));
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Makes sure there is enough capacity to hold the specified element count.
|
* Makes sure there is enough capacity to hold the specified element count.
|
||||||
*/
|
*/
|
||||||
void Adjust(SQInteger n)
|
SqBuffer & Adjust(SQInteger n)
|
||||||
{
|
{
|
||||||
// Validate the managed buffer reference
|
// Validate the managed buffer reference
|
||||||
Validate();
|
Validate();
|
||||||
@@ -438,6 +448,8 @@ public:
|
|||||||
{
|
{
|
||||||
STHROWF("{}", e.what()); // Re-package
|
STHROWF("{}", e.what()); // Re-package
|
||||||
}
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@@ -770,6 +782,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD Vector4 ReadVector4() const;
|
SQMOD_NODISCARD Vector4 ReadVector4() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Transform a portion of the data in the buffer to a JSON object.
|
||||||
|
* This has the benefit that a temporary string doesn't have to be created.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger GetJSON(HSQUIRRELVM vm) const;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Compute the CRC-32 checksums on the data in the buffer.
|
* Compute the CRC-32 checksums on the data in the buffer.
|
||||||
*/
|
*/
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include "Library/JSON.hpp"
|
#include "Library/JSON.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <sajson.h>
|
||||||
#include <sqratConst.h>
|
#include <sqratConst.h>
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -11,13 +12,10 @@
|
|||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static SQInteger SqToJSON(HSQUIRRELVM vm) noexcept
|
SQMOD_DECL_TYPENAME(SqCtxJSON, _SC("SqCtxJSON"))
|
||||||
{
|
|
||||||
return sq_throwerror(vm, _SC("Not implemented yet!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static SQInteger SqFromJson_Push(HSQUIRRELVM vm, const sajson::value & node) noexcept
|
static SQInteger SqFromJson_Push(HSQUIRRELVM vm, const sajson::value & node) noexcept // NOLINT(misc-no-recursion)
|
||||||
{
|
{
|
||||||
// Operation result
|
// Operation result
|
||||||
SQInteger r = SQ_OK;
|
SQInteger r = SQ_OK;
|
||||||
@@ -151,11 +149,616 @@ static SQInteger SqFromJSON(HSQUIRRELVM vm) noexcept
|
|||||||
return SQ_SUCCEEDED(r) ? 1 : r;
|
return SQ_SUCCEEDED(r) ? 1 : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQInteger SqFromNativeJSON(HSQUIRRELVM vm, const char * data, size_t size)
|
||||||
|
{
|
||||||
|
// Attempt to parse the specified JSON string
|
||||||
|
const sajson::document & document = sajson::parse(sajson::dynamic_allocation(), sajson::string(data, size));
|
||||||
|
// See if there was an error
|
||||||
|
if (!document.is_valid())
|
||||||
|
{
|
||||||
|
return sq_throwerror(vm, document.get_error_message_as_cstring());
|
||||||
|
}
|
||||||
|
// Process the nodes that were parsed from the string
|
||||||
|
SQInteger r = SqFromJson_Push(vm, document.get_root());
|
||||||
|
// We either have a value to return or we propagate some error
|
||||||
|
return SQ_SUCCEEDED(r) ? 1 : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::OpenArray()
|
||||||
|
{
|
||||||
|
// Add the array-begin character
|
||||||
|
mOutput.push_back('[');
|
||||||
|
// Go forward one level
|
||||||
|
Advance();
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::CloseArray()
|
||||||
|
{
|
||||||
|
// If the last character is a comma then replace it
|
||||||
|
if (mOutput.back() == ',')
|
||||||
|
{
|
||||||
|
mOutput.back() = ']';
|
||||||
|
}
|
||||||
|
// Append the array-end character
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOutput.push_back(']');
|
||||||
|
}
|
||||||
|
// Move the comma after the closing character
|
||||||
|
mOutput.push_back(',');
|
||||||
|
// Go back one level
|
||||||
|
Retreat();
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::ReopenArray()
|
||||||
|
{
|
||||||
|
// If the last character is a comma then remove it
|
||||||
|
if (mOutput.back() == ',')
|
||||||
|
{
|
||||||
|
mOutput.pop_back();
|
||||||
|
}
|
||||||
|
// If the last character is the array-end character then replace it with a comma
|
||||||
|
if (mOutput.back() == ']')
|
||||||
|
{
|
||||||
|
mOutput.back() = ',';
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::OpenObject()
|
||||||
|
{
|
||||||
|
// Add the object-begin character
|
||||||
|
mOutput.push_back('{');
|
||||||
|
// Go forward one level
|
||||||
|
Advance();
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::CloseObject()
|
||||||
|
{
|
||||||
|
// If the last character is a comma then replace it
|
||||||
|
if (mOutput.back() == ',')
|
||||||
|
{
|
||||||
|
mOutput.back() = '}';
|
||||||
|
}
|
||||||
|
// Append the object-end character
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOutput.push_back('}');
|
||||||
|
}
|
||||||
|
// Move the comma after the closing character
|
||||||
|
mOutput.push_back(',');
|
||||||
|
// Go back one level
|
||||||
|
Retreat();
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::ReopenObject()
|
||||||
|
{
|
||||||
|
// If the last character is a comma then remove it
|
||||||
|
if (mOutput.back() == ',')
|
||||||
|
{
|
||||||
|
mOutput.pop_back();
|
||||||
|
}
|
||||||
|
// If the last character is the object-end character then replace it with a comma
|
||||||
|
if (mOutput.back() == '}')
|
||||||
|
{
|
||||||
|
mOutput.back() = ',';
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::MakeKey()
|
||||||
|
{
|
||||||
|
// If the last character is a comma then replace it
|
||||||
|
if (mOutput.back() == ',')
|
||||||
|
{
|
||||||
|
mOutput.back() = ':';
|
||||||
|
}
|
||||||
|
// Append the array-end character
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOutput.push_back(':');
|
||||||
|
}
|
||||||
|
// Allow the hook to react
|
||||||
|
if (mKeyHook)
|
||||||
|
{
|
||||||
|
mKeyHook(*this);
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
bool CtxJSON::CheckWeakRefWrap(HSQUIRRELVM vm, SQInteger idx) noexcept
|
||||||
|
{
|
||||||
|
SQRESULT r = sq_getweakrefval(vm, idx);
|
||||||
|
// Whether the type doesn't have to be wrapped
|
||||||
|
bool w = true;
|
||||||
|
// Attempt to grab the value pointed by the weak reference
|
||||||
|
if (SQ_SUCCEEDED(r))
|
||||||
|
{
|
||||||
|
// Attempt to serialize the actual value
|
||||||
|
w = sq_gettype(vm, -1) != OT_TABLE && sq_gettype(vm, -1) != OT_ARRAY && sq_gettype(vm, -1) == OT_INSTANCE;
|
||||||
|
// Pop the referenced value
|
||||||
|
sq_poptop(vm);
|
||||||
|
}
|
||||||
|
// Wrap the value by default
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::SerializeParams(HSQUIRRELVM vm)
|
||||||
|
{
|
||||||
|
bool wrap_everything_in_array = false;
|
||||||
|
// Clear the output buffer if necessary
|
||||||
|
mOutput.clear();
|
||||||
|
mDepth = 0;
|
||||||
|
// Fetch the number of objects on the stack
|
||||||
|
const auto top = sq_gettop(vm);
|
||||||
|
// If there's more than one argument then they all get wrapped inside an array
|
||||||
|
// If there is one argument and is not an array, table or instance then do the same
|
||||||
|
if (top > 2 || (sq_gettype(vm, 2) != OT_TABLE &&
|
||||||
|
sq_gettype(vm, 2) != OT_ARRAY &&
|
||||||
|
sq_gettype(vm, 2) != OT_INSTANCE &&
|
||||||
|
CheckWeakRefWrap(vm, 2)))
|
||||||
|
{
|
||||||
|
wrap_everything_in_array = true;
|
||||||
|
// Open an array
|
||||||
|
OpenArray();
|
||||||
|
}
|
||||||
|
// Serialize every specified argument
|
||||||
|
for (SQInteger i = 2; i <= top; ++i)
|
||||||
|
{
|
||||||
|
if (SQRESULT r = SerializeAt(vm, i); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Was everything wrapped inside an array?
|
||||||
|
if (wrap_everything_in_array)
|
||||||
|
{
|
||||||
|
CloseArray();
|
||||||
|
}
|
||||||
|
// Remove trailing separator, if any
|
||||||
|
if (mOutput.back() == ',')
|
||||||
|
{
|
||||||
|
mOutput.pop_back();
|
||||||
|
}
|
||||||
|
// Push the output string on the stack
|
||||||
|
sq_pushstring(vm, mOutput.c_str(), static_cast< SQInteger >(mOutput.size()));
|
||||||
|
// Specify that we have a value on the stack
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::SerializeAt(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||||
|
{
|
||||||
|
// Identify object type
|
||||||
|
switch (sq_gettype(vm, idx))
|
||||||
|
{
|
||||||
|
case OT_NULL: {
|
||||||
|
PushNull();
|
||||||
|
} break;
|
||||||
|
case OT_INTEGER: {
|
||||||
|
SQInteger v;
|
||||||
|
// Attempt to retrieve the value from the stack
|
||||||
|
if (SQRESULT r = sq_getinteger(vm, idx, &v); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
// Write the value in the output
|
||||||
|
PushInteger(v);
|
||||||
|
} break;
|
||||||
|
case OT_FLOAT: {
|
||||||
|
SQFloat v;
|
||||||
|
// Attempt to retrieve the value from the stack
|
||||||
|
if (SQRESULT r = sq_getfloat(vm, idx, &v); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
// Write the value in the output
|
||||||
|
#ifdef SQUSEDOUBLE
|
||||||
|
PushDouble(v);
|
||||||
|
#else
|
||||||
|
PushFloat(v);
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
|
case OT_BOOL: {
|
||||||
|
SQBool v;
|
||||||
|
// Attempt to retrieve the value from the stack
|
||||||
|
if (SQRESULT r = sq_getbool(vm, idx, &v); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
// Write the value in the output
|
||||||
|
PushBool(v != SQFalse);
|
||||||
|
} break;
|
||||||
|
case OT_STRING: {
|
||||||
|
const SQChar * v = nullptr;
|
||||||
|
SQInteger n = 0;
|
||||||
|
// Attempt to retrieve and convert the string
|
||||||
|
if (SQRESULT r = sq_getstringandsize(vm, idx, &v, &n); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
// Write the value in the output
|
||||||
|
PushString(v, static_cast< size_t >(n));
|
||||||
|
} break;
|
||||||
|
case OT_TABLE: {
|
||||||
|
if (SQRESULT r = SerializeTable(vm, idx); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case OT_ARRAY: {
|
||||||
|
if (SQRESULT r = SerializeArray(vm, idx); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case OT_INSTANCE: {
|
||||||
|
if (SQRESULT r = SerializeInstance(vm, idx); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case OT_WEAKREF: {
|
||||||
|
if (SQRESULT r = SerializeWeakRef(vm, idx); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case OT_USERDATA:
|
||||||
|
case OT_CLOSURE:
|
||||||
|
case OT_NATIVECLOSURE:
|
||||||
|
case OT_GENERATOR:
|
||||||
|
case OT_USERPOINTER:
|
||||||
|
case OT_THREAD:
|
||||||
|
case OT_FUNCPROTO:
|
||||||
|
case OT_CLASS:
|
||||||
|
case OT_OUTER:
|
||||||
|
return sq_throwerrorf(vm, _SC("Type (%s) is not serializable"), SqTypeName(sq_gettype(vm, 2)));
|
||||||
|
}
|
||||||
|
// Serialization was successful
|
||||||
|
return SQ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::SerializeArray(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||||
|
{
|
||||||
|
// Begin array scope
|
||||||
|
OpenArray();
|
||||||
|
// Push null to initiate iteration
|
||||||
|
sq_pushnull(vm);
|
||||||
|
// So we can use absolute stack indexes to avoid errors
|
||||||
|
const auto top = sq_gettop(vm);
|
||||||
|
// Start iterating the array at the specified position in the stack
|
||||||
|
for(SQRESULT r = SQ_OK; SQ_SUCCEEDED(sq_next(vm, idx));)
|
||||||
|
{
|
||||||
|
// Attempt serialization of the currently iterated value
|
||||||
|
r = SerializeAt(vm, top + 2);
|
||||||
|
// Check for failures
|
||||||
|
if (SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
// Pop the null iterator, key and value from the stack
|
||||||
|
sq_pop(vm, 3);
|
||||||
|
// Propagate the error
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
// Pop the key and value from the stack (i.e. cleanup after `sq_next`)
|
||||||
|
sq_pop(vm, 2);
|
||||||
|
}
|
||||||
|
// Pop the null iterator
|
||||||
|
sq_poptop(vm);
|
||||||
|
// Close array scope
|
||||||
|
CloseArray();
|
||||||
|
// Serialization was successful
|
||||||
|
return SQ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::SerializeTable(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||||
|
{
|
||||||
|
// Begin object scope
|
||||||
|
OpenObject();
|
||||||
|
// Push null to initiate iteration
|
||||||
|
sq_pushnull(vm);
|
||||||
|
// So we can use absolute stack indexes to avoid errors
|
||||||
|
const auto top = sq_gettop(vm);
|
||||||
|
// Start iterating the object at the specified position in the stack
|
||||||
|
for(SQRESULT r = SQ_OK; SQ_SUCCEEDED(sq_next(vm, idx));)
|
||||||
|
{
|
||||||
|
if (sq_gettype(vm, -2) == OT_STRING)
|
||||||
|
{
|
||||||
|
// Attempt serialization of the currently iterated element key
|
||||||
|
r = SerializeAt(vm, top + 1);
|
||||||
|
// Can we proceed with the value?
|
||||||
|
if (SQ_SUCCEEDED(r))
|
||||||
|
{
|
||||||
|
// Mark the value above as the key of this element and
|
||||||
|
// attempt serialization of the currently iterated element value
|
||||||
|
r = MakeKey().SerializeAt(vm, top + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = sq_throwerror(vm, _SC("Only string values are accepted as object keys"));
|
||||||
|
}
|
||||||
|
// Check for failures
|
||||||
|
if (SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
// Pop the null iterator, key and value from the stack
|
||||||
|
sq_pop(vm, 3);
|
||||||
|
// Propagate the error
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
// Pop the key and value from the stack (i.e. cleanup after `sq_next`)
|
||||||
|
sq_pop(vm, 2);
|
||||||
|
}
|
||||||
|
// Pop the null iterator
|
||||||
|
sq_poptop(vm);
|
||||||
|
// Close object scope
|
||||||
|
CloseObject();
|
||||||
|
// Serialization was successful
|
||||||
|
return SQ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::SerializeInstance(HSQUIRRELVM vm, SQInteger idx)
|
||||||
|
{
|
||||||
|
sq_pushstring(vm, mMetaMethod.c_str(), static_cast< SQInteger >(mMetaMethod.size()));
|
||||||
|
// Attempt to retrieve the meta-method from the instance
|
||||||
|
if(SQRESULT r = sq_get(vm, idx); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
// Make sure this is actually a closure/function that we can invoke
|
||||||
|
else if (const auto t = sq_gettype(vm, -1); t != OT_CLOSURE && t != OT_NATIVECLOSURE)
|
||||||
|
{
|
||||||
|
// Remove whatever is on the stack
|
||||||
|
sq_poptop(vm);
|
||||||
|
// Abort the operation as we can't do anything about it
|
||||||
|
return sq_throwerrorf(vm, _SC("`_tojson` meta-method is not a closure for type (%s)"), SqTypeName(vm, idx).c_str());
|
||||||
|
}
|
||||||
|
// Push the instance itself the stack (the environment)
|
||||||
|
sq_push(vm, idx);
|
||||||
|
// Push this instance on the stack (the json context)
|
||||||
|
ClassType< CtxJSON >::PushInstance(vm, this);
|
||||||
|
// Invoke the function to perform the conversion in this context
|
||||||
|
SQRESULT r = sq_call(vm, 2, SQFalse, SQFalse);
|
||||||
|
// Remove the closure from the stack
|
||||||
|
sq_poptop(vm);
|
||||||
|
// Propagate the result, whatever that is
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::SerializeWeakRef(HSQUIRRELVM vm, SQInteger idx) // NOLINT(misc-no-recursion)
|
||||||
|
{
|
||||||
|
SQRESULT r = sq_getweakrefval(vm, idx);
|
||||||
|
// Attempt to grab the value pointed by the weak reference
|
||||||
|
if (SQ_SUCCEEDED(r))
|
||||||
|
{
|
||||||
|
// Attempt to serialize the actual value
|
||||||
|
r = SerializeAt(vm, sq_gettop(vm));
|
||||||
|
// Pop the referenced value
|
||||||
|
sq_poptop(vm);
|
||||||
|
}
|
||||||
|
// Propagate the error, if any
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::PushValues(HSQUIRRELVM vm)
|
||||||
|
{
|
||||||
|
// Fetch the number of objects on the stack
|
||||||
|
const auto top = sq_gettop(vm);
|
||||||
|
// Do we have a value?
|
||||||
|
if (top < 2)
|
||||||
|
{
|
||||||
|
return sq_throwerror(vm, _SC("Must specify at least one value to be pushed"));
|
||||||
|
}
|
||||||
|
// Serialize every specified argument
|
||||||
|
for (SQInteger i = 2; i <= top; ++i)
|
||||||
|
{
|
||||||
|
if (SQRESULT r = SerializeAt(vm, i); SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
sq_push(vm, 1);
|
||||||
|
// Specify that a value was returned
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQRESULT CtxJSON::PushElement(HSQUIRRELVM vm)
|
||||||
|
{
|
||||||
|
// Fetch the number of objects on the stack
|
||||||
|
const auto top = sq_gettop(vm);
|
||||||
|
// Do we have a value?
|
||||||
|
if (top < 3)
|
||||||
|
{
|
||||||
|
return sq_throwerrorf(vm, _SC("Not enough parameters. Received %lld but %lld needed"), top-1, 2);
|
||||||
|
}
|
||||||
|
else if (sq_gettype(vm, 2) != OT_STRING)
|
||||||
|
{
|
||||||
|
return sq_throwerrorf(vm, _SC("Element key must be a string"));
|
||||||
|
}
|
||||||
|
// Attempt serialization of the currently iterated element key
|
||||||
|
if (SQRESULT r = SerializeAt(vm, 2); SQ_SUCCEEDED(r))
|
||||||
|
{
|
||||||
|
// Mark the value above as the key of this element and
|
||||||
|
// attempt serialization of the currently iterated element value
|
||||||
|
r = MakeKey().SerializeAt(vm, 3);
|
||||||
|
// Check for failures
|
||||||
|
if (SQ_FAILED(r))
|
||||||
|
{
|
||||||
|
return r; // Propagate the error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
sq_push(vm, 1);
|
||||||
|
// Specify that a value was returned
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
CtxJSON & CtxJSON::PushKey(StackStrF & key)
|
||||||
|
{
|
||||||
|
// Validate the string value
|
||||||
|
if (key.mLen >= 0 && SQ_SUCCEEDED(key.mRes))
|
||||||
|
{
|
||||||
|
PushString(key.mPtr, static_cast< size_t >(key.mLen));
|
||||||
|
MakeKey();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STHROWF("Invalid object key");
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushNull()
|
||||||
|
{
|
||||||
|
mOutput.append("null,");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushInteger(SQInteger value)
|
||||||
|
{
|
||||||
|
fmt::format_int f(value);
|
||||||
|
// Append the formatted integer to the buffer
|
||||||
|
mOutput.append(f.data(), f.size());
|
||||||
|
mOutput.push_back(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushFloat(float value)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(mOutput), "{},", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushDouble(double value)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(mOutput), "{},", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushBool(bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
mOutput.append("true,", 5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOutput.append("false,", 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushString(const SQChar * str)
|
||||||
|
{
|
||||||
|
mOutput.push_back('"');
|
||||||
|
mOutput.append(str);
|
||||||
|
mOutput.push_back('"');
|
||||||
|
mOutput.push_back(',');
|
||||||
|
// Allow the hook to know
|
||||||
|
mString.assign(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CtxJSON::PushString(const SQChar * str, size_t length)
|
||||||
|
{
|
||||||
|
mOutput.push_back('"');
|
||||||
|
mOutput.append(str, length);
|
||||||
|
mOutput.push_back('"');
|
||||||
|
mOutput.push_back(',');
|
||||||
|
// Allow the hook to know
|
||||||
|
mString.assign(str, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static SQInteger SqToJSON(HSQUIRRELVM vm) noexcept
|
||||||
|
{
|
||||||
|
// Make sure the instance is cleaned up even in the case of exceptions
|
||||||
|
DeleteGuard< CtxJSON > sq_dg(new CtxJSON());
|
||||||
|
// Remember the instance, so we don't have to cast the script object back
|
||||||
|
auto ctx = sq_dg.Get();
|
||||||
|
// Turn it into a script object because it may be passed as a parameter to `_tojson` meta-methods
|
||||||
|
LightObj obj(sq_dg, vm);
|
||||||
|
// Proceed with the serialization
|
||||||
|
return ctx->SerializeParams(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static SQInteger SqToCompactJSON(HSQUIRRELVM vm) noexcept
|
||||||
|
{
|
||||||
|
// Make sure the instance is cleaned up even in the case of exceptions
|
||||||
|
DeleteGuard< CtxJSON > sq_dg(new CtxJSON(false));
|
||||||
|
// Remember the instance, so we don't have to cast the script object back
|
||||||
|
auto ctx = sq_dg.Get();
|
||||||
|
// Turn it into a script object because it may be passed as a parameter to `_tojson` meta-methods
|
||||||
|
LightObj obj(sq_dg, vm);
|
||||||
|
// Proceed with the serialization
|
||||||
|
return ctx->SerializeParams(vm);
|
||||||
|
}
|
||||||
|
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
void Register_JSON(HSQUIRRELVM vm)
|
void Register_JSON(HSQUIRRELVM vm)
|
||||||
{
|
{
|
||||||
RootTable(vm).SquirrelFunc(_SC("SqToJSON"), SqToJSON);
|
RootTable(vm).SquirrelFunc(_SC("SqToJSON"), SqToJSON);
|
||||||
|
RootTable(vm).SquirrelFunc(_SC("SqToCompactJSON"), SqToCompactJSON);
|
||||||
RootTable(vm).SquirrelFunc(_SC("SqFromJSON"), SqFromJSON);
|
RootTable(vm).SquirrelFunc(_SC("SqFromJSON"), SqFromJSON);
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
RootTable(vm).Bind(_SC("SqCtxJSON"),
|
||||||
|
Class< CtxJSON, NoCopy< CtxJSON > >(vm, SqCtxJSON::Str)
|
||||||
|
// Constructors
|
||||||
|
.Ctor()
|
||||||
|
.Ctor< bool >()
|
||||||
|
.Ctor< bool, StackStrF & >()
|
||||||
|
// Meta-methods
|
||||||
|
.SquirrelFunc(_SC("_typename"), &SqCtxJSON::Fn)
|
||||||
|
// Properties
|
||||||
|
.Prop(_SC("Output"), &CtxJSON::GetOutput)
|
||||||
|
.Prop(_SC("Depth"), &CtxJSON::GetDepth)
|
||||||
|
.Prop(_SC("OOA"), &CtxJSON::GetObjectOverArray, &CtxJSON::SetObjectOverArray)
|
||||||
|
.Prop(_SC("ObjectOverArray"), &CtxJSON::GetObjectOverArray, &CtxJSON::SetObjectOverArray)
|
||||||
|
// Member Methods
|
||||||
|
.SquirrelMethod< CtxJSON, &CtxJSON::SerializeParams >(_SC("Serialize"))
|
||||||
|
.SquirrelMethod< CtxJSON, &CtxJSON::PushValues >(_SC("PushValues"))
|
||||||
|
.SquirrelMethod< CtxJSON, &CtxJSON::PushElement >(_SC("PushElement"))
|
||||||
|
.Func(_SC("OpenArray"), &CtxJSON::OpenArray)
|
||||||
|
.Func(_SC("CloseArray"), &CtxJSON::CloseArray)
|
||||||
|
.Func(_SC("OpenObject"), &CtxJSON::OpenObject)
|
||||||
|
.Func(_SC("CloseObject"), &CtxJSON::CloseObject)
|
||||||
|
.Func(_SC("MakeKey"), &CtxJSON::MakeKey)
|
||||||
|
.FmtFunc(_SC("PushKey"), &CtxJSON::PushKey)
|
||||||
|
.Func(_SC("SetOOA"), &CtxJSON::SetObjectOverArray)
|
||||||
|
.Func(_SC("SetObjectOverArray"), &CtxJSON::SetObjectOverArray)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@@ -5,12 +5,281 @@
|
|||||||
#include "Library/IO/Buffer.hpp"
|
#include "Library/IO/Buffer.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#include <sajson.h>
|
#include <functional>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <fmt/args.h>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <fmt/xchar.h>
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* JSON serializer. The generated JSON output is always minified for efficiency reasons.
|
||||||
|
*/
|
||||||
|
struct CtxJSON
|
||||||
|
{
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Output string.
|
||||||
|
*/
|
||||||
|
String mOutput{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Prefer a table with named members even when a simple array would do the job.
|
||||||
|
* Take a Vector3 for example. Compact array [x, y, z] or named object {x: #.#, y: #.#, z: #.#}
|
||||||
|
*/
|
||||||
|
bool mObjectOverArray{true};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* How nested are we currently.
|
||||||
|
*/
|
||||||
|
uint32_t mDepth{0};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* The meta-method name to use on objects.
|
||||||
|
*/
|
||||||
|
String mMetaMethod{"_tojson"};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Last pushed string value. Can be used to heck for key name in the hook.
|
||||||
|
*/
|
||||||
|
String mString{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Internal utility used to monitor the existence of certain keys to allow overloading.
|
||||||
|
*/
|
||||||
|
std::function< void(CtxJSON&) > mKeyHook{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
CtxJSON() = default;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
explicit CtxJSON(bool ooa)
|
||||||
|
: CtxJSON()
|
||||||
|
{
|
||||||
|
mObjectOverArray = ooa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
CtxJSON(bool ooa, StackStrF & mmname)
|
||||||
|
: CtxJSON()
|
||||||
|
{
|
||||||
|
mObjectOverArray = ooa;
|
||||||
|
// Allow custom metamethod names
|
||||||
|
mMetaMethod.assign(mmname.mPtr, static_cast< size_t >(mmname.mLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Internal constructor.
|
||||||
|
*/
|
||||||
|
explicit CtxJSON(std::function< void(CtxJSON&) > && kh)
|
||||||
|
: CtxJSON()
|
||||||
|
{
|
||||||
|
mKeyHook = std::move(kh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy constructor.
|
||||||
|
*/
|
||||||
|
CtxJSON(const CtxJSON &) = default;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Move constructor.
|
||||||
|
*/
|
||||||
|
CtxJSON(CtxJSON &&) noexcept = default;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~CtxJSON() = default;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy assignment operator.
|
||||||
|
*/
|
||||||
|
CtxJSON & operator = (const CtxJSON &) = default;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Move assignment operator.
|
||||||
|
*/
|
||||||
|
CtxJSON & operator = (CtxJSON &&) noexcept = default;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the current depth.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD const String & GetOutput() const noexcept
|
||||||
|
{
|
||||||
|
return mOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the current depth.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger GetDepth() const noexcept
|
||||||
|
{
|
||||||
|
return mDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve whether objects are preferred over arrays.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD bool GetObjectOverArray() const noexcept
|
||||||
|
{
|
||||||
|
return mObjectOverArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve whether objects are preferred over arrays.
|
||||||
|
*/
|
||||||
|
CtxJSON & SetObjectOverArray(bool toggle) noexcept
|
||||||
|
{
|
||||||
|
mObjectOverArray = toggle;
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Increase indentation by one level.
|
||||||
|
*/
|
||||||
|
void Advance() noexcept
|
||||||
|
{
|
||||||
|
++mDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Decrease indentation by one level.
|
||||||
|
*/
|
||||||
|
void Retreat() noexcept
|
||||||
|
{
|
||||||
|
assert(mDepth > 0);
|
||||||
|
if (mDepth) --mDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Begin writing an array.
|
||||||
|
*/
|
||||||
|
CtxJSON & OpenArray();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Stop writing an array.
|
||||||
|
*/
|
||||||
|
CtxJSON & CloseArray();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Resume writing an array.
|
||||||
|
*/
|
||||||
|
CtxJSON & ReopenArray();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Begin writing an object.
|
||||||
|
*/
|
||||||
|
CtxJSON & OpenObject();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Stop writing an object.
|
||||||
|
*/
|
||||||
|
CtxJSON & CloseObject();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Resume writing an object.
|
||||||
|
*/
|
||||||
|
CtxJSON & ReopenObject();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Begin writing a key value.
|
||||||
|
*/
|
||||||
|
CtxJSON & MakeKey();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Check whether the specified weak-ref points to a type of value that must be wrapped.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD static bool CheckWeakRefWrap(HSQUIRRELVM vm, SQInteger idx) noexcept;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize given arguments.
|
||||||
|
*/
|
||||||
|
SQRESULT SerializeParams(HSQUIRRELVM vm);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize the value a specific position in the stack.
|
||||||
|
*/
|
||||||
|
SQRESULT SerializeAt(HSQUIRRELVM vm, SQInteger idx);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize the array a specific position in the stack. Stack index must be absolute!
|
||||||
|
*/
|
||||||
|
SQRESULT SerializeArray(HSQUIRRELVM vm, SQInteger idx);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize the table a specific position in the stack. Stack index must be absolute!
|
||||||
|
*/
|
||||||
|
SQRESULT SerializeTable(HSQUIRRELVM vm, SQInteger idx);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize the instance a specific position in the stack. Stack index must be absolute!
|
||||||
|
*/
|
||||||
|
SQRESULT SerializeInstance(HSQUIRRELVM vm, SQInteger idx);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize the weak-ref a specific position in the stack. Stack index must be absolute!
|
||||||
|
*/
|
||||||
|
SQRESULT SerializeWeakRef(HSQUIRRELVM vm, SQInteger idx);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize a value to the current container. It assumes an array or object is currently open.
|
||||||
|
*/
|
||||||
|
SQRESULT PushValues(HSQUIRRELVM vm);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Serialize a key/value pair to the current object. It assumes an object is currently open.
|
||||||
|
*/
|
||||||
|
SQRESULT PushElement(HSQUIRRELVM vm);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Push a key in the output. It assumes an object was open and previous element closed properly.
|
||||||
|
*/
|
||||||
|
CtxJSON & PushKey(StackStrF & key);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write a null value to the output.
|
||||||
|
*/
|
||||||
|
void PushNull();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write an integer value to the output.
|
||||||
|
*/
|
||||||
|
void PushInteger(SQInteger value);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write a single precision floating point value to the output.
|
||||||
|
*/
|
||||||
|
void PushFloat(float value);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write a double precision floating point value to the output.
|
||||||
|
*/
|
||||||
|
void PushDouble(double value);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write a boolean value to the output.
|
||||||
|
*/
|
||||||
|
void PushBool(bool value);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write a string value to the output.
|
||||||
|
*/
|
||||||
|
void PushString(const SQChar * str);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Write a string value to the output.
|
||||||
|
*/
|
||||||
|
void PushString(const SQChar * str, size_t length);
|
||||||
|
};
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@@ -22,6 +22,8 @@ void InitializeNet()
|
|||||||
#endif
|
#endif
|
||||||
#ifndef NO_SSL
|
#ifndef NO_SSL
|
||||||
f |= MG_FEATURES_SSL;
|
f |= MG_FEATURES_SSL;
|
||||||
|
#else
|
||||||
|
OutputMessage("Network compiled without SSL support.");
|
||||||
#endif
|
#endif
|
||||||
#ifndef NO_CGI
|
#ifndef NO_CGI
|
||||||
f |= MG_FEATURES_CGI;
|
f |= MG_FEATURES_CGI;
|
||||||
@@ -135,6 +137,11 @@ int WebSocketClient::DataHandler(int flags, char * data, size_t data_len) noexce
|
|||||||
{
|
{
|
||||||
LogFtl("Failed to queue web-socket data");
|
LogFtl("Failed to queue web-socket data");
|
||||||
}
|
}
|
||||||
|
// Should we auto-close the connection
|
||||||
|
if (((flags & 0xF) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE) && mAutoClose.load() == true)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
// Return 1 to keep the connection open
|
// Return 1 to keep the connection open
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -173,6 +180,7 @@ void Register_Net(HSQUIRRELVM vm)
|
|||||||
.Prop(_SC("OnClose"), &WebSocketClient::GetOnClose, &WebSocketClient::SetOnClose)
|
.Prop(_SC("OnClose"), &WebSocketClient::GetOnClose, &WebSocketClient::SetOnClose)
|
||||||
.Prop(_SC("Valid"), &WebSocketClient::IsValid)
|
.Prop(_SC("Valid"), &WebSocketClient::IsValid)
|
||||||
.Prop(_SC("Closing"), &WebSocketClient::IsClosing)
|
.Prop(_SC("Closing"), &WebSocketClient::IsClosing)
|
||||||
|
.Prop(_SC("AutoClose"), &WebSocketClient::GetAutoClose, &WebSocketClient::SetAutoClose)
|
||||||
// Member Methods
|
// Member Methods
|
||||||
.FmtFunc(_SC("SetTag"), &WebSocketClient::ApplyTag)
|
.FmtFunc(_SC("SetTag"), &WebSocketClient::ApplyTag)
|
||||||
.FmtFunc(_SC("SetData"), &WebSocketClient::ApplyData)
|
.FmtFunc(_SC("SetData"), &WebSocketClient::ApplyData)
|
||||||
|
@@ -159,6 +159,13 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
*/
|
*/
|
||||||
std::atomic< bool > mClosed{false};
|
std::atomic< bool > mClosed{false};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Whether to not keep the connection open after receiving the close event.
|
||||||
|
* Internally this event is ignored but if set to true the connection is immediatelly closed
|
||||||
|
* in the internal event handler, before the event may reach the script callback.
|
||||||
|
*/
|
||||||
|
std::atomic< bool > mAutoClose{false};
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Server host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost".
|
* Server host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost".
|
||||||
*/
|
*/
|
||||||
@@ -184,7 +191,8 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
*/
|
*/
|
||||||
WebSocketClient()
|
WebSocketClient()
|
||||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
, mPort(0), mSecure(false), mClosing(false), mClosed(false), mHost(), mPath(), mOrigin(), mExtensions()
|
, mPort(0), mSecure(false), mClosing(false), mClosed(false), mAutoClose(false)
|
||||||
|
, mHost(), mPath(), mOrigin(), mExtensions()
|
||||||
{
|
{
|
||||||
ChainInstance(); // Remember this instance
|
ChainInstance(); // Remember this instance
|
||||||
}
|
}
|
||||||
@@ -194,7 +202,7 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
*/
|
*/
|
||||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path)
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path)
|
||||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
, mPort(port), mSecure(false), mClosing(false), mClosed(false)
|
, mPort(port), mSecure(false), mClosing(false), mClosed(false), mAutoClose(false)
|
||||||
, mHost(host.mPtr, host.GetSize())
|
, mHost(host.mPtr, host.GetSize())
|
||||||
, mPath(path.mPtr, path.GetSize())
|
, mPath(path.mPtr, path.GetSize())
|
||||||
, mOrigin(), mExtensions()
|
, mOrigin(), mExtensions()
|
||||||
@@ -207,7 +215,7 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
*/
|
*/
|
||||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure)
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure)
|
||||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
, mPort(port), mSecure(secure), mClosing(false), mClosed(false)
|
, mPort(port), mSecure(secure), mClosing(false), mClosed(false), mAutoClose(false)
|
||||||
, mHost(host.mPtr, host.GetSize())
|
, mHost(host.mPtr, host.GetSize())
|
||||||
, mPath(path.mPtr, path.GetSize())
|
, mPath(path.mPtr, path.GetSize())
|
||||||
, mOrigin(), mExtensions()
|
, mOrigin(), mExtensions()
|
||||||
@@ -220,7 +228,7 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
*/
|
*/
|
||||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin)
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin)
|
||||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
, mPort(port), mSecure(secure), mClosing(false), mClosed(false)
|
, mPort(port), mSecure(secure), mClosing(false), mClosed(false), mAutoClose(false)
|
||||||
, mHost(host.mPtr, host.GetSize())
|
, mHost(host.mPtr, host.GetSize())
|
||||||
, mPath(path.mPtr, path.GetSize())
|
, mPath(path.mPtr, path.GetSize())
|
||||||
, mOrigin(origin.mPtr, origin.GetSize())
|
, mOrigin(origin.mPtr, origin.GetSize())
|
||||||
@@ -234,7 +242,7 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
*/
|
*/
|
||||||
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin, StackStrF & ext)
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin, StackStrF & ext)
|
||||||
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
, mPort(port), mSecure(secure), mClosing(false), mClosed(false)
|
, mPort(port), mSecure(secure), mClosing(false), mClosed(false), mAutoClose(false)
|
||||||
, mHost(host.mPtr, host.GetSize())
|
, mHost(host.mPtr, host.GetSize())
|
||||||
, mPath(path.mPtr, path.GetSize())
|
, mPath(path.mPtr, path.GetSize())
|
||||||
, mOrigin(origin.mPtr, origin.GetSize())
|
, mOrigin(origin.mPtr, origin.GetSize())
|
||||||
@@ -294,6 +302,22 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
|||||||
return mClosing.load();
|
return mClosing.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve whether auto-closing is enabled or not.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD bool GetAutoClose() const
|
||||||
|
{
|
||||||
|
return mAutoClose.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify whether auto-closing is enabled or not.
|
||||||
|
*/
|
||||||
|
void SetAutoClose(bool toggle)
|
||||||
|
{
|
||||||
|
mAutoClose.store(toggle);
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Retrieve the associated user tag.
|
* Retrieve the associated user tag.
|
||||||
*/
|
*/
|
||||||
|
@@ -8,6 +8,9 @@
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQMOD_DECL_TYPENAME(SqIdPoolTypename, _SC("SqIdPool"))
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Probably not the best implementation but should cover all sorts of weird cases.
|
* Probably not the best implementation but should cover all sorts of weird cases.
|
||||||
*/
|
*/
|
||||||
@@ -83,15 +86,18 @@ static SQInteger SqExtractIPv4(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
extern void Register_IdPool(HSQUIRRELVM vm, Table & ns);
|
||||||
extern void Register_Vector(HSQUIRRELVM vm, Table & ns);
|
extern void Register_Vector(HSQUIRRELVM vm, Table & ns);
|
||||||
extern void Register_Native_String(HSQUIRRELVM vm, Table & ns);
|
extern void Register_Native_String(HSQUIRRELVM vm, Table & ns);
|
||||||
extern void Register_ServerAnnouncer(HSQUIRRELVM vm, Table & ns);
|
extern void Register_ServerAnnouncer(HSQUIRRELVM vm, Table & ns);
|
||||||
|
|
||||||
|
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
void Register_Utils(HSQUIRRELVM vm)
|
void Register_Utils(HSQUIRRELVM vm)
|
||||||
{
|
{
|
||||||
Table ns(vm);
|
Table ns(vm);
|
||||||
|
|
||||||
|
Register_IdPool(vm, ns);
|
||||||
Register_Vector(vm, ns);
|
Register_Vector(vm, ns);
|
||||||
Register_Native_String(vm, ns);
|
Register_Native_String(vm, ns);
|
||||||
Register_ServerAnnouncer(vm, ns);
|
Register_ServerAnnouncer(vm, ns);
|
||||||
@@ -101,4 +107,35 @@ void Register_Utils(HSQUIRRELVM vm)
|
|||||||
RootTable(vm).Bind(_SC("SqUtils"), ns);
|
RootTable(vm).Bind(_SC("SqUtils"), ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Register_IdPool(HSQUIRRELVM vm, Table & ns)
|
||||||
|
{
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
ns.Bind(_SC("IdPool"),
|
||||||
|
Class< SqIdPool, NoCopy< SqIdPool > >(vm, SqIdPoolTypename::Str)
|
||||||
|
// Constructors
|
||||||
|
.Ctor()
|
||||||
|
.template Ctor< SqIdPool::Type >()
|
||||||
|
.template Ctor< SqIdPool::Type, SqIdPool::Type >()
|
||||||
|
// Meta-methods
|
||||||
|
.SquirrelFunc(_SC("_typename"), &SqIdPoolTypename::Fn)
|
||||||
|
// Member Variables
|
||||||
|
.ConstVar(_SC("Next"), &SqIdPool::mNext)
|
||||||
|
.ConstVar(_SC("Step"), &SqIdPool::mStep)
|
||||||
|
.ConstVar(_SC("Start"), &SqIdPool::mStart)
|
||||||
|
// Properties
|
||||||
|
.Prop(_SC("FreeCount"), &SqIdPool::FreeCount)
|
||||||
|
.Prop(_SC("UsedCount"), &SqIdPool::UsedCount)
|
||||||
|
// Member Methods
|
||||||
|
.Func(_SC("Reset"), &SqIdPool::Reset)
|
||||||
|
.Func(_SC("Acquire"), &SqIdPool::Acquire)
|
||||||
|
.Func(_SC("Release"), &SqIdPool::Release)
|
||||||
|
.Func(_SC("Using"), &SqIdPool::Using)
|
||||||
|
.Func(_SC("EachUsed"), &SqIdPool::EachUsed)
|
||||||
|
.Func(_SC("WhileUsed"), &SqIdPool::WhileUsed)
|
||||||
|
.Func(_SC("EachFree"), &SqIdPool::EachFree)
|
||||||
|
.Func(_SC("WhileFree"), &SqIdPool::WhileFree)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@@ -6,4 +6,187 @@
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Helper utility used to provide reusable unique IDs of signed integer type.
|
||||||
|
* It is not thread-safe since the script runs in single-threaded mode.
|
||||||
|
*/
|
||||||
|
struct SqIdPool
|
||||||
|
{
|
||||||
|
using Type = SQInteger; // Type that is used to represent an ID.
|
||||||
|
using Pool = std::vector< Type >; // Container for both used and unused IDs.
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
// Pool of available IDs.
|
||||||
|
Pool mPool{};
|
||||||
|
// Pool of currently used IDs.
|
||||||
|
Pool mUsed{};
|
||||||
|
// The ID that will be generated next time the pool is empty.
|
||||||
|
Type mNext{0};
|
||||||
|
// How much to increment with each ID.
|
||||||
|
Type mStep{1};
|
||||||
|
// Where to start generating IDs.
|
||||||
|
Type mStart{0};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Base constructors.
|
||||||
|
*/
|
||||||
|
SqIdPool() noexcept = default;
|
||||||
|
SqIdPool(Type start) noexcept
|
||||||
|
: SqIdPool(start, 1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
SqIdPool(Type start, Type step) noexcept
|
||||||
|
: mPool(), mUsed(), mNext(start), mStep(step), mStart(start)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy/Move constructors (disabled).
|
||||||
|
*/
|
||||||
|
SqIdPool(const SqIdPool &) noexcept = delete;
|
||||||
|
SqIdPool(SqIdPool &&) noexcept = delete;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy/Move assignment operators (disabled).
|
||||||
|
*/
|
||||||
|
SqIdPool & operator = (const SqIdPool &) noexcept = delete;
|
||||||
|
SqIdPool & operator = (SqIdPool &&) noexcept = delete;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Discard all current IDs (free and used) and reset the start to the specified start.
|
||||||
|
* This invalidates all IDs that are currently left in use.
|
||||||
|
*/
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
mNext = mStart;
|
||||||
|
mPool.clear();
|
||||||
|
mUsed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Acquire a unique ID from the pool.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD Type Acquire()
|
||||||
|
{
|
||||||
|
Type id = mNext;
|
||||||
|
// Do we have some reusable IDs?
|
||||||
|
if (mPool.empty())
|
||||||
|
{
|
||||||
|
mNext += mStep; // Create a new one and update the next one
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
id = mPool.back(); // Get one from the back of the pool
|
||||||
|
mPool.pop_back(); // Remove it from the free pool
|
||||||
|
}
|
||||||
|
// Store it in the list of active IDs
|
||||||
|
mUsed.push_back(id);
|
||||||
|
// Return this ID
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Release a unique ID back to the pool.
|
||||||
|
*/
|
||||||
|
bool Release(Type id)
|
||||||
|
{
|
||||||
|
// Find the specified ID into
|
||||||
|
for (Pool::size_type i = 0; i < mUsed.size(); ++i)
|
||||||
|
{
|
||||||
|
// Is this the ID we're looking for?
|
||||||
|
if (mUsed[i] == id)
|
||||||
|
{
|
||||||
|
// Swap the element with the last one
|
||||||
|
std::swap(mUsed[i], mUsed.back());
|
||||||
|
// Remove the last element
|
||||||
|
mUsed.pop_back();
|
||||||
|
// Make this ID available, again
|
||||||
|
mPool.push_back(id);
|
||||||
|
// We actually found this ID
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This ID does not belong to this pool
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Check if the pool has the specified ID currently in use.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD bool Using(Type id)
|
||||||
|
{
|
||||||
|
return std::find(mUsed.begin(), mUsed.end(), id) != mUsed.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the number of IDs that are currently available in the free pool.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger FreeCount() const
|
||||||
|
{
|
||||||
|
return mPool.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the number of IDs that are currently in use.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger UsedCount() const
|
||||||
|
{
|
||||||
|
return mUsed.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Iterate all used IDs through a functor.
|
||||||
|
*/
|
||||||
|
void EachUsed(Function & fn) const
|
||||||
|
{
|
||||||
|
for (const auto & id : mUsed)
|
||||||
|
{
|
||||||
|
fn.Execute(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Iterate all used IDs through a functor until stopped (i.e false is returned).
|
||||||
|
*/
|
||||||
|
void WhileUsed(Function & fn) const
|
||||||
|
{
|
||||||
|
for (const auto & id : mUsed)
|
||||||
|
{
|
||||||
|
auto ret = fn.Eval(id);
|
||||||
|
// (null || true) == continue & false == break
|
||||||
|
if (!ret.IsNull() || !ret.template Cast< bool >())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Iterate all free IDs through a functor.
|
||||||
|
*/
|
||||||
|
void EachFree(Function & fn) const
|
||||||
|
{
|
||||||
|
for (const auto & id : mPool)
|
||||||
|
{
|
||||||
|
fn.Execute(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Iterate all free IDs through a functor until stopped (i.e false is returned).
|
||||||
|
*/
|
||||||
|
void WhileFree(Function & fn) const
|
||||||
|
{
|
||||||
|
for (const auto & id : mPool)
|
||||||
|
{
|
||||||
|
auto ret = fn.Eval(id);
|
||||||
|
// (null || true) == continue & false == break
|
||||||
|
if (!ret.IsNull() || !ret.template Cast< bool >())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
@@ -17,7 +17,7 @@ namespace SqMod {
|
|||||||
static bool g_Reload = false;
|
static bool g_Reload = false;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//extern void InitExports();
|
extern void InitExports();
|
||||||
extern void InitializeNet();
|
extern void InitializeNet();
|
||||||
extern void InitializePocoDataConnectors();
|
extern void InitializePocoDataConnectors();
|
||||||
extern void ProcessRoutines();
|
extern void ProcessRoutines();
|
||||||
@@ -97,7 +97,7 @@ static uint8_t OnServerInitialise()
|
|||||||
{
|
{
|
||||||
SQMOD_SV_EV_TRACEBACK("[TRACE<] OnServerInitialise")
|
SQMOD_SV_EV_TRACEBACK("[TRACE<] OnServerInitialise")
|
||||||
// Signal outside plug-ins to do fetch our proxies
|
// Signal outside plug-ins to do fetch our proxies
|
||||||
//_Func->SendPluginCommand(0xDABBAD00, "%d", 1);
|
_Func->SendPluginCommand(SQMOD_INITIALIZE_CMD, "%d", 1);
|
||||||
// Attempt to load the module core
|
// Attempt to load the module core
|
||||||
if (Core::Get().Execute())
|
if (Core::Get().Execute())
|
||||||
{
|
{
|
||||||
@@ -1083,7 +1083,7 @@ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * funcs, PluginCallback
|
|||||||
_Clbk->OnEntityStreamingChange = OnEntityStreamingChange;
|
_Clbk->OnEntityStreamingChange = OnEntityStreamingChange;
|
||||||
#endif
|
#endif
|
||||||
// Attempt to initialize the plug-in exports
|
// Attempt to initialize the plug-in exports
|
||||||
//InitExports();
|
InitExports();
|
||||||
// Dummy spacing
|
// Dummy spacing
|
||||||
puts("");
|
puts("");
|
||||||
// Initialization was successful
|
// Initialization was successful
|
||||||
|
@@ -55,40 +55,60 @@ SQMOD_DECL_TYPENAME(CVehicleTn, _SC("CVehicle"))
|
|||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Used to fetch the legacy entity instance even if a native one was specified.
|
* Used to fetch the legacy entity instance even if a native one was specified.
|
||||||
*/
|
*/
|
||||||
template < class T, class U > inline T & GetLgEnt(LightObj & o)
|
template < class LEGACY, class NATIVE > inline LEGACY & GetLgEnt(LightObj & o)
|
||||||
{
|
{
|
||||||
auto type = static_cast< AbstractStaticClassData * >(o.GetTypeTag());
|
const auto type = static_cast< AbstractStaticClassData * >(o.GetTypeTag());
|
||||||
// Legacy entity type?
|
// Legacy entity type?
|
||||||
if (type == StaticClassTypeTag< T >::Get())
|
if (type == StaticClassTypeTag< LEGACY >::Get())
|
||||||
{
|
{
|
||||||
return *o.CastI< T >();
|
return *o.CastI< LEGACY >();
|
||||||
}
|
}
|
||||||
// Native entity type?
|
// Native entity type?
|
||||||
if (type == StaticClassTypeTag< U >::Get())
|
if (type == StaticClassTypeTag< NATIVE >::Get())
|
||||||
{
|
{
|
||||||
return *EntityInstSelect< U >(o.CastI< U >()->GetID()).mLgInst;
|
return *EntityInstSelect< NATIVE >::Get(o.CastI< NATIVE >()->GetID()).mLgInst;
|
||||||
}
|
}
|
||||||
STHROWF("Invalid entity type");
|
STHROWF("Invalid entity type: {}", SqTypeName(SqVM(), o));
|
||||||
|
SQ_UNREACHABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Used to fetch the native entity instance even if a legacy one was specified.
|
||||||
|
*/
|
||||||
|
template < class LEGACY, class NATIVE > inline NATIVE & GetNativeEnt(LightObj & o)
|
||||||
|
{
|
||||||
|
const auto type = static_cast< AbstractStaticClassData * >(o.GetTypeTag());
|
||||||
|
// Legacy entity type?
|
||||||
|
if (type == StaticClassTypeTag< LEGACY >::Get())
|
||||||
|
{
|
||||||
|
return o.CastI< LEGACY >()->Get();
|
||||||
|
}
|
||||||
|
// Native entity type?
|
||||||
|
if (type == StaticClassTypeTag< NATIVE >::Get())
|
||||||
|
{
|
||||||
|
return *EntityInstSelect< NATIVE >::Get(o.CastI< NATIVE >()->GetID()).mInst;
|
||||||
|
}
|
||||||
|
STHROWF("Invalid entity type: {}", SqTypeName(SqVM(), o));
|
||||||
SQ_UNREACHABLE
|
SQ_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Used to fetch the legacy entity identifier even if a native one was specified.
|
* Used to fetch the legacy entity identifier even if a native one was specified.
|
||||||
*/
|
*/
|
||||||
template < class T, class U > SQMOD_NODISCARD inline int32_t GetLgEntID(LightObj & o)
|
template < class LEGACY, class NATIVE > SQMOD_NODISCARD inline int32_t GetLgEntID(LightObj & o)
|
||||||
{
|
{
|
||||||
auto type = static_cast< AbstractStaticClassData * >(o.GetTypeTag());
|
const auto type = static_cast< AbstractStaticClassData * >(o.GetTypeTag());
|
||||||
// Legacy entity type?
|
// Legacy entity type?
|
||||||
if (type == StaticClassTypeTag< T >::Get())
|
if (type == StaticClassTypeTag< LEGACY >::Get())
|
||||||
{
|
{
|
||||||
return o.CastI< T >()->mID;
|
return o.CastI< LEGACY >()->mID;
|
||||||
}
|
}
|
||||||
// Native entity type?
|
// Native entity type?
|
||||||
if (type == StaticClassTypeTag< U >::Get())
|
if (type == StaticClassTypeTag< NATIVE >::Get())
|
||||||
{
|
{
|
||||||
return o.CastI< U >()->GetID();
|
return o.CastI< NATIVE >()->GetID();
|
||||||
}
|
}
|
||||||
STHROWF("Invalid entity type");
|
STHROWF("Invalid entity type: {}", SqTypeName(SqVM(), o));
|
||||||
SQ_UNREACHABLE
|
SQ_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,14 +498,14 @@ struct LgCheckpoint
|
|||||||
SQMOD_NODISCARD int GetWorld() const { return Get().GetWorld(); }
|
SQMOD_NODISCARD int GetWorld() const { return Get().GetWorld(); }
|
||||||
SQMOD_NODISCARD LgARGB GetColor() const { const Color4 c = Get().GetColor(); return LgARGB{c.a, c.r, c.g, c.b}; }
|
SQMOD_NODISCARD LgARGB GetColor() const { const Color4 c = Get().GetColor(); return LgARGB{c.a, c.r, c.g, c.b}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetPos() const
|
SQMOD_NODISCARD LgEntityVector GetPos() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Checkpoint, 0, Get().GetPosition()); }
|
{ return {mID, LgEntityType::Checkpoint, 0, Get().GetPosition()}; }
|
||||||
SQMOD_NODISCARD float GetRadius() const { return Get().GetRadius(); }
|
SQMOD_NODISCARD float GetRadius() const { return Get().GetRadius(); }
|
||||||
SQMOD_NODISCARD int GetID() const { return mID; }
|
SQMOD_NODISCARD int GetID() const { return mID; }
|
||||||
SQMOD_NODISCARD LgPlayer * GetOwner() const
|
SQMOD_NODISCARD LgPlayer * GetOwner() const
|
||||||
{ const int id = Get().GetOwnerID(); return VALID_ENTITYEX(id, SQMOD_PLAYER_POOL) ? Core::Get().GetPlayer(id).mLgInst : nullptr; }
|
{ const int id = Get().GetOwnerID(); return VALID_ENTITYEX(id, SQMOD_PLAYER_POOL) ? Core::Get().GetPlayer(id).mLgInst : nullptr; }
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
void Delete() const { _Func->DeleteCheckPoint(GetIdentifier()); }
|
void Delete() const { _Func->DeleteCheckPoint(GetIdentifier()); }
|
||||||
SQMOD_NODISCARD bool StreamedToPlayer(LgPlayer & player) const;
|
SQMOD_NODISCARD bool StreamedToPlayer(LightObj & player) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
@@ -546,11 +566,11 @@ struct LgObject
|
|||||||
SQMOD_NODISCARD int GetAlpha() const { return Get().GetAlpha(); }
|
SQMOD_NODISCARD int GetAlpha() const { return Get().GetAlpha(); }
|
||||||
SQMOD_NODISCARD int GetWorld() const { return Get().GetWorld(); }
|
SQMOD_NODISCARD int GetWorld() const { return Get().GetWorld(); }
|
||||||
SQMOD_NODISCARD LgEntityVector GetPos() const
|
SQMOD_NODISCARD LgEntityVector GetPos() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Object, LgObjectVectorFlag::Pos, Get().GetPosition()); }
|
{ return {mID, LgEntityType::Object, LgObjectVectorFlag::Pos, Get().GetPosition()}; }
|
||||||
SQMOD_NODISCARD LgEntityQuaternion GetRotation() const
|
SQMOD_NODISCARD LgEntityQuaternion GetRotation() const
|
||||||
{ return LgEntityQuaternion(mID, LgEntityType::Object, 0, Get().GetRotation()); }
|
{ return {mID, LgEntityType::Object, 0, Get().GetRotation()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetRotationEuler() const
|
SQMOD_NODISCARD LgEntityVector GetRotationEuler() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Object, LgObjectVectorFlag::Rotation, Get().GetRotationEuler()); }
|
{ return {mID, LgEntityType::Object, LgObjectVectorFlag::Rotation, Get().GetRotationEuler()}; }
|
||||||
SQMOD_NODISCARD int GetID() const { return mID; }
|
SQMOD_NODISCARD int GetID() const { return mID; }
|
||||||
SQMOD_NODISCARD bool GetReportingShots() const { return Get().GetShotReport(); }
|
SQMOD_NODISCARD bool GetReportingShots() const { return Get().GetShotReport(); }
|
||||||
SQMOD_NODISCARD bool GetReportingBumps() const { return Get().GetTouchedReport(); }
|
SQMOD_NODISCARD bool GetReportingBumps() const { return Get().GetTouchedReport(); }
|
||||||
@@ -563,7 +583,7 @@ struct LgObject
|
|||||||
void RotateToEuler(const Vector3 & rotation, int time) const { Get().RotateToEuler(rotation, static_cast< uint32_t >(time)); }
|
void RotateToEuler(const Vector3 & rotation, int time) const { Get().RotateToEuler(rotation, static_cast< uint32_t >(time)); }
|
||||||
void RotateByEuler(const Vector3 & rotOffset, int time) const { Get().RotateByEuler(rotOffset, static_cast< uint32_t >(time)); }
|
void RotateByEuler(const Vector3 & rotOffset, int time) const { Get().RotateByEuler(rotOffset, static_cast< uint32_t >(time)); }
|
||||||
void SetAlpha(int alpha, int fadeTime) const { Get().SetAlphaEx(alpha, static_cast< uint32_t >(fadeTime)); }
|
void SetAlpha(int alpha, int fadeTime) const { Get().SetAlphaEx(alpha, static_cast< uint32_t >(fadeTime)); }
|
||||||
SQMOD_NODISCARD bool StreamedToPlayer(LgPlayer & player) const;
|
SQMOD_NODISCARD bool StreamedToPlayer(LightObj & player) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
@@ -627,7 +647,7 @@ struct LgPickup
|
|||||||
SQMOD_NODISCARD bool GetAuto() const { return Get().GetAutomatic(); }
|
SQMOD_NODISCARD bool GetAuto() const { return Get().GetAutomatic(); }
|
||||||
SQMOD_NODISCARD int GetAutoTimer() const { return Get().GetAutoTimer(); }
|
SQMOD_NODISCARD int GetAutoTimer() const { return Get().GetAutoTimer(); }
|
||||||
SQMOD_NODISCARD LgEntityVector GetPos() const
|
SQMOD_NODISCARD LgEntityVector GetPos() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Pickup, 0, Get().GetPosition()); }
|
{ return {mID, LgEntityType::Pickup, 0, Get().GetPosition()}; }
|
||||||
SQMOD_NODISCARD int GetModel() const { return Get().GetModel(); }
|
SQMOD_NODISCARD int GetModel() const { return Get().GetModel(); }
|
||||||
SQMOD_NODISCARD int GetQuantity() const { return Get().GetQuantity(); }
|
SQMOD_NODISCARD int GetQuantity() const { return Get().GetQuantity(); }
|
||||||
SQMOD_NODISCARD int GetID() const { return mID; }
|
SQMOD_NODISCARD int GetID() const { return mID; }
|
||||||
@@ -635,7 +655,7 @@ struct LgPickup
|
|||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
void Delete() const { _Func->DeletePickup(GetIdentifier()); }
|
void Delete() const { _Func->DeletePickup(GetIdentifier()); }
|
||||||
void Respawn() const { Get().Refresh(); }
|
void Respawn() const { Get().Refresh(); }
|
||||||
SQMOD_NODISCARD bool StreamedToPlayer(LgPlayer & player) const;
|
SQMOD_NODISCARD bool StreamedToPlayer(LightObj & player) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
@@ -703,7 +723,7 @@ struct LgPlayer
|
|||||||
void SetScore(int score) const { Get().SetScore(score); }
|
void SetScore(int score) const { Get().SetScore(score); }
|
||||||
void SetImmunity(uint32_t immunity) const { Get().SetImmunity(immunity); }
|
void SetImmunity(uint32_t immunity) const { Get().SetImmunity(immunity); }
|
||||||
void SetHeading(float heading) const { Get().SetHeading(heading); }
|
void SetHeading(float heading) const { Get().SetHeading(heading); }
|
||||||
void SetVehicle(LgVehicle & vehicle) const;
|
void SetVehicle(LightObj & vehicle) const;
|
||||||
void SetFrozen(bool toggle) const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionControllable, static_cast< uint8_t >(!toggle)); }
|
void SetFrozen(bool toggle) const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionControllable, static_cast< uint8_t >(!toggle)); }
|
||||||
void SetDriveByEnabled(bool toggle) const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionDriveBy, static_cast< uint8_t >(toggle)); }
|
void SetDriveByEnabled(bool toggle) const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionDriveBy, static_cast< uint8_t >(toggle)); }
|
||||||
void SetWhiteScanLines(bool toggle) const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionWhiteScanlines, static_cast< uint8_t >(toggle)); }
|
void SetWhiteScanLines(bool toggle) const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionWhiteScanlines, static_cast< uint8_t >(toggle)); }
|
||||||
@@ -720,7 +740,7 @@ struct LgPlayer
|
|||||||
void SetWantedLevel(int level) const { Get().SetWantedLevel(level); }
|
void SetWantedLevel(int level) const { Get().SetWantedLevel(level); }
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
SQMOD_NODISCARD LgEntityVector GetPosition() const
|
SQMOD_NODISCARD LgEntityVector GetPosition() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Player, LgPlayerVectorFlag::Pos, Get().GetPosition()); }
|
{ return {mID, LgEntityType::Player, LgPlayerVectorFlag::Pos, Get().GetPosition()}; }
|
||||||
SQMOD_NODISCARD int GetClass() const { return Get().GetClass(); }
|
SQMOD_NODISCARD int GetClass() const { return Get().GetClass(); }
|
||||||
SQMOD_NODISCARD bool GetAdmin() const { return Get().GetAdmin(); }
|
SQMOD_NODISCARD bool GetAdmin() const { return Get().GetAdmin(); }
|
||||||
SQMOD_NODISCARD const SQChar * GetIP() const { return Get().GetIP(); }
|
SQMOD_NODISCARD const SQChar * GetIP() const { return Get().GetIP(); }
|
||||||
@@ -732,7 +752,7 @@ struct LgPlayer
|
|||||||
SQMOD_NODISCARD const SQChar * GetName() const { return Get().GetName(); }
|
SQMOD_NODISCARD const SQChar * GetName() const { return Get().GetName(); }
|
||||||
SQMOD_NODISCARD int GetTeam() const { return Get().GetTeam(); }
|
SQMOD_NODISCARD int GetTeam() const { return Get().GetTeam(); }
|
||||||
SQMOD_NODISCARD int GetSkin() const { return Get().GetSkin(); }
|
SQMOD_NODISCARD int GetSkin() const { return Get().GetSkin(); }
|
||||||
SQMOD_NODISCARD LgEntityRGB GetColour() const { return LgEntityRGB(mID, LgEntityType::Player, 0, Get().GetColor()); }
|
SQMOD_NODISCARD LgEntityRGB GetColour() const { return {mID, LgEntityType::Player, 0, Get().GetColor()}; }
|
||||||
SQMOD_NODISCARD int GetMoney() const { return Get().GetMoney(); }
|
SQMOD_NODISCARD int GetMoney() const { return Get().GetMoney(); }
|
||||||
SQMOD_NODISCARD int GetScore() const { return Get().GetScore(); }
|
SQMOD_NODISCARD int GetScore() const { return Get().GetScore(); }
|
||||||
SQMOD_NODISCARD int GetPing() const { return Get().GetPing(); }
|
SQMOD_NODISCARD int GetPing() const { return Get().GetPing(); }
|
||||||
@@ -764,7 +784,7 @@ struct LgPlayer
|
|||||||
SQMOD_NODISCARD LgPlayer * GetSpectateTarget() const
|
SQMOD_NODISCARD LgPlayer * GetSpectateTarget() const
|
||||||
{ const int id = _Func->GetPlayerSpectateTarget(GetIdentifier()); return VALID_ENTITYEX(id, SQMOD_PLAYER_POOL) ? Core::Get().GetPlayer(id).mLgInst : nullptr; }
|
{ const int id = _Func->GetPlayerSpectateTarget(GetIdentifier()); return VALID_ENTITYEX(id, SQMOD_PLAYER_POOL) ? Core::Get().GetPlayer(id).mLgInst : nullptr; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetSpeed() const
|
SQMOD_NODISCARD LgEntityVector GetSpeed() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Player, LgPlayerVectorFlag::Speed, Get().GetSpeed()); }
|
{ return {mID, LgEntityType::Player, LgPlayerVectorFlag::Speed, Get().GetSpeed()}; }
|
||||||
SQMOD_NODISCARD bool GetCanUseColors() const { return _Func->GetPlayerOption(GetIdentifier(), vcmpPlayerOptionChatTagsEnabled) >= 1; }
|
SQMOD_NODISCARD bool GetCanUseColors() const { return _Func->GetPlayerOption(GetIdentifier(), vcmpPlayerOptionChatTagsEnabled) >= 1; }
|
||||||
SQMOD_NODISCARD bool GetMarkerVisible() const { return _Func->GetPlayerOption(GetIdentifier(), vcmpPlayerOptionHasMarker) >= 1; }
|
SQMOD_NODISCARD bool GetMarkerVisible() const { return _Func->GetPlayerOption(GetIdentifier(), vcmpPlayerOptionHasMarker) >= 1; }
|
||||||
SQMOD_NODISCARD bool GetDrunkStatus() const { return _Func->GetPlayerOption(GetIdentifier(), vcmpPlayerOptionDrunkEffects) >= 1; }
|
SQMOD_NODISCARD bool GetDrunkStatus() const { return _Func->GetPlayerOption(GetIdentifier(), vcmpPlayerOptionDrunkEffects) >= 1; }
|
||||||
@@ -801,8 +821,8 @@ struct LgPlayer
|
|||||||
SQMOD_NODISCARD int GetWeaponAtSlot(int slot) const { return Get().GetWeaponAtSlot(slot); }
|
SQMOD_NODISCARD int GetWeaponAtSlot(int slot) const { return Get().GetWeaponAtSlot(slot); }
|
||||||
SQMOD_NODISCARD int GetAmmoAtSlot(int slot) const { return Get().GetAmmoAtSlot(slot); }
|
SQMOD_NODISCARD int GetAmmoAtSlot(int slot) const { return Get().GetAmmoAtSlot(slot); }
|
||||||
void SetAlpha(int alpha, int fadeTime) const { Get().SetAlphaEx(alpha, fadeTime); }
|
void SetAlpha(int alpha, int fadeTime) const { Get().SetAlphaEx(alpha, fadeTime); }
|
||||||
SQMOD_NODISCARD bool StreamedToPlayer(const LgPlayer & player) const { return Get().IsStreamedFor(player.Get()); }
|
SQMOD_NODISCARD bool StreamedToPlayer(LightObj & player) const { return Get().IsStreamedFor(GetNativeEnt< LgPlayer, CPlayer >(player)); }
|
||||||
void SetVehicleSlot(const LgVehicle & vehicle, int slot) const;
|
void SetVehicleSlot(LightObj & vehicle, int slot) const;
|
||||||
void Select() const { Get().ForceSelect(); }
|
void Select() const { Get().ForceSelect(); }
|
||||||
void RestoreCamera() const { Get().RestoreCamera(); }
|
void RestoreCamera() const { Get().RestoreCamera(); }
|
||||||
void RemoveMarker() const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionHasMarker, 0); }
|
void RemoveMarker() const { _Func->SetPlayerOption(GetIdentifier(), vcmpPlayerOptionHasMarker, 0); }
|
||||||
@@ -915,13 +935,13 @@ struct LgVehicle
|
|||||||
SQMOD_NODISCARD int GetModel() const { return Get().GetModel(); }
|
SQMOD_NODISCARD int GetModel() const { return Get().GetModel(); }
|
||||||
SQMOD_NODISCARD uint32_t GetImmunity() const { return Get().GetImmunity(); }
|
SQMOD_NODISCARD uint32_t GetImmunity() const { return Get().GetImmunity(); }
|
||||||
SQMOD_NODISCARD LgEntityVector GetPosition() const
|
SQMOD_NODISCARD LgEntityVector GetPosition() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::Pos, Get().GetPosition()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::Pos, Get().GetPosition()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetSpawnPos() const
|
SQMOD_NODISCARD LgEntityVector GetSpawnPos() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::SpawnPos, Get().GetSpawnPosition()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::SpawnPos, Get().GetSpawnPosition()}; }
|
||||||
SQMOD_NODISCARD LgEntityQuaternion GetSpawnAngle() const
|
SQMOD_NODISCARD LgEntityQuaternion GetSpawnAngle() const
|
||||||
{ return LgEntityQuaternion(mID, LgEntityType::Vehicle, LgVehicleQuaternionFlag::SpawnAngle, Get().GetSpawnRotation()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleQuaternionFlag::SpawnAngle, Get().GetSpawnRotation()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetSpawnAngleEuler() const
|
SQMOD_NODISCARD LgEntityVector GetSpawnAngleEuler() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::SpawnAngle, Get().GetSpawnRotationEuler()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::SpawnAngle, Get().GetSpawnRotationEuler()}; }
|
||||||
SQMOD_NODISCARD uint32_t GetIdleRespawnTimer() const { return Get().GetIdleRespawnTimer(); }
|
SQMOD_NODISCARD uint32_t GetIdleRespawnTimer() const { return Get().GetIdleRespawnTimer(); }
|
||||||
SQMOD_NODISCARD float GetHealth() const { return Get().GetHealth(); }
|
SQMOD_NODISCARD float GetHealth() const { return Get().GetHealth(); }
|
||||||
SQMOD_NODISCARD int GetColour1() const { return Get().GetPrimaryColor(); }
|
SQMOD_NODISCARD int GetColour1() const { return Get().GetPrimaryColor(); }
|
||||||
@@ -939,21 +959,21 @@ struct LgVehicle
|
|||||||
SQMOD_NODISCARD int GetSyncType() const { return Get().GetSyncType(); }
|
SQMOD_NODISCARD int GetSyncType() const { return Get().GetSyncType(); }
|
||||||
SQMOD_NODISCARD bool GetWrecked() const { return Get().IsWrecked(); }
|
SQMOD_NODISCARD bool GetWrecked() const { return Get().IsWrecked(); }
|
||||||
SQMOD_NODISCARD LgEntityQuaternion GetRotation() const
|
SQMOD_NODISCARD LgEntityQuaternion GetRotation() const
|
||||||
{ return LgEntityQuaternion(mID, LgEntityType::Vehicle, LgVehicleQuaternionFlag::Angle, Get().GetRotation()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleQuaternionFlag::Angle, Get().GetRotation()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetEulerRotation() const
|
SQMOD_NODISCARD LgEntityVector GetEulerRotation() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::Angle, Get().GetRotationEuler()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::Angle, Get().GetRotationEuler()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetSpeed() const
|
SQMOD_NODISCARD LgEntityVector GetSpeed() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::Speed, Get().GetSpeed()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::Speed, Get().GetSpeed()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetRelativeSpeed() const
|
SQMOD_NODISCARD LgEntityVector GetRelativeSpeed() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::RelSpeed, Get().GetRelativeSpeed()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::RelSpeed, Get().GetRelativeSpeed()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetTurnSpeed() const
|
SQMOD_NODISCARD LgEntityVector GetTurnSpeed() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::TurnSpeed, Get().GetTurnSpeed()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::TurnSpeed, Get().GetTurnSpeed()}; }
|
||||||
SQMOD_NODISCARD LgEntityVector GetRelativeTurnSpeed() const
|
SQMOD_NODISCARD LgEntityVector GetRelativeTurnSpeed() const
|
||||||
{ return LgEntityVector(mID, LgEntityType::Vehicle, LgVehicleVectorFlag::RelTurnSpeed, Get().GetRelativeTurnSpeed()); }
|
{ return {mID, LgEntityType::Vehicle, LgVehicleVectorFlag::RelTurnSpeed, Get().GetRelativeTurnSpeed()}; }
|
||||||
SQMOD_NODISCARD int GetRadio() const { return Get().GetRadio(); }
|
SQMOD_NODISCARD int GetRadio() const { return Get().GetRadio(); }
|
||||||
SQMOD_NODISCARD bool GetRadioLockStatus() const { return _Func->GetVehicleOption(GetIdentifier(), vcmpVehicleOptionRadioLocked) >= 1; }
|
SQMOD_NODISCARD bool GetRadioLockStatus() const { return _Func->GetVehicleOption(GetIdentifier(), vcmpVehicleOptionRadioLocked) >= 1; }
|
||||||
SQMOD_NODISCARD bool GetGhost() const { return _Func->GetVehicleOption(GetIdentifier(), vcmpVehicleOptionGhost) >= 1; }
|
SQMOD_NODISCARD bool GetGhost() const { return _Func->GetVehicleOption(GetIdentifier(), vcmpVehicleOptionGhost) >= 1; }
|
||||||
SQMOD_NODISCARD LgVector GetTurretRotation() const { const Vector2 v = Get().GetTurretRotation(); return LgVector(v.x, v.y, 0); }
|
SQMOD_NODISCARD LgVector GetTurretRotation() const { const Vector2 v = Get().GetTurretRotation(); return {v.x, v.y, 0}; }
|
||||||
SQMOD_NODISCARD bool GetSingleUse() const { return _Func->GetVehicleOption(GetIdentifier(), vcmpVehicleOptionSingleUse) >= 1; }
|
SQMOD_NODISCARD bool GetSingleUse() const { return _Func->GetVehicleOption(GetIdentifier(), vcmpVehicleOptionSingleUse) >= 1; }
|
||||||
SQMOD_NODISCARD bool GetTaxiLight() const { return (_Func->GetVehicleLightsData(GetIdentifier()) & (1 << 8)) != 0; }
|
SQMOD_NODISCARD bool GetTaxiLight() const { return (_Func->GetVehicleLightsData(GetIdentifier()) & (1 << 8)) != 0; }
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
@@ -966,7 +986,7 @@ struct LgVehicle
|
|||||||
void SetPartStatus(int part, int status) const { Get().SetPartStatus(part, status); }
|
void SetPartStatus(int part, int status) const { Get().SetPartStatus(part, status); }
|
||||||
SQMOD_NODISCARD int GetTyreStatus(int tyre) const { return Get().GetTyreStatus(tyre); }
|
SQMOD_NODISCARD int GetTyreStatus(int tyre) const { return Get().GetTyreStatus(tyre); }
|
||||||
void SetTyreStatus(int part, int status) const { Get().SetTyreStatus(part, status); }
|
void SetTyreStatus(int part, int status) const { Get().SetTyreStatus(part, status); }
|
||||||
SQMOD_NODISCARD bool GetStreamedForPlayer(LgPlayer & player) const { return Get().IsStreamedFor(player.Get()); }
|
SQMOD_NODISCARD bool GetStreamedForPlayer(LightObj & player) const { return Get().IsStreamedFor(GetNativeEnt< LgPlayer, CPlayer >(player)); }
|
||||||
SQMOD_NODISCARD LgPlayer * GetOccupant(int slot) const
|
SQMOD_NODISCARD LgPlayer * GetOccupant(int slot) const
|
||||||
{ const int id = _Func->GetVehicleOccupant(GetIdentifier(), slot); return VALID_ENTITYEX(id, SQMOD_PLAYER_POOL) ? Core::Get().GetPlayer(id).mLgInst : nullptr; }
|
{ const int id = _Func->GetVehicleOccupant(GetIdentifier(), slot); return VALID_ENTITYEX(id, SQMOD_PLAYER_POOL) ? Core::Get().GetPlayer(id).mLgInst : nullptr; }
|
||||||
void SetHandlingData(int rule, float value) const { Get().SetHandlingRule(rule, value); }
|
void SetHandlingData(int rule, float value) const { Get().SetHandlingRule(rule, value); }
|
||||||
@@ -982,11 +1002,11 @@ struct LgVehicle
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
inline bool LgCheckpoint::StreamedToPlayer(LgPlayer & player) const { return Get().IsStreamedFor(player.Get()); }
|
inline bool LgCheckpoint::StreamedToPlayer(LightObj & player) const { return Get().IsStreamedFor(GetNativeEnt< LgPlayer, CPlayer >(player)); }
|
||||||
inline bool LgObject::StreamedToPlayer(LgPlayer & player) const { return Get().IsStreamedFor(player.Get()); }
|
inline bool LgObject::StreamedToPlayer(LightObj & player) const { return Get().IsStreamedFor(GetNativeEnt< LgPlayer, CPlayer >(player)); }
|
||||||
inline bool LgPickup::StreamedToPlayer(LgPlayer & player) const { return Get().IsStreamedFor(player.Get()); }
|
inline bool LgPickup::StreamedToPlayer(LightObj & player) const { return Get().IsStreamedFor(GetNativeEnt< LgPlayer, CPlayer >(player)); }
|
||||||
inline void LgPlayer::SetVehicle(LgVehicle & vehicle) const { Get().Embark(vehicle.Get()); }
|
inline void LgPlayer::SetVehicle(LightObj & vehicle) const { Get().Embark(GetNativeEnt< LgVehicle, CVehicle >(vehicle)); }
|
||||||
inline void LgPlayer::SetVehicleSlot(const LgVehicle & vehicle, int slot) const { Get().EmbarkEx(vehicle.Get(), slot, true, false); }
|
inline void LgPlayer::SetVehicleSlot(LightObj & vehicle, int slot) const { Get().EmbarkEx(GetNativeEnt< LgVehicle, CVehicle >(vehicle), slot, true, false); }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LgCheckpointSetID(LgCheckpoint * inst, int32_t id) { assert(inst); if (inst) inst->mID = id; }
|
void LgCheckpointSetID(LgCheckpoint * inst, int32_t id) { assert(inst); if (inst) inst->mID = id; }
|
||||||
@@ -1434,8 +1454,8 @@ static void LgUnbanIP(StackStrF & ip) { _Func->UnbanIP(const_cast< SQChar * >(ip
|
|||||||
SQMOD_NODISCARD static bool LgIsIPBanned(StackStrF & ip) { return _Func->IsIPBanned(const_cast< SQChar * >(ip.mPtr)) >= 1; }
|
SQMOD_NODISCARD static bool LgIsIPBanned(StackStrF & ip) { return _Func->IsIPBanned(const_cast< SQChar * >(ip.mPtr)) >= 1; }
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQMOD_NODISCARD static int LgGetPlayerIDFromName(StackStrF & name) { return _Func->GetPlayerIdFromName(name.mPtr); }
|
SQMOD_NODISCARD static int LgGetPlayerIDFromName(StackStrF & name) { return _Func->GetPlayerIdFromName(name.mPtr); }
|
||||||
SQMOD_NODISCARD static bool LgIsWorldCompatibleWithPlayer (LgPlayer & player, int world)
|
SQMOD_NODISCARD static bool LgIsWorldCompatibleWithPlayer(LightObj & player, int world)
|
||||||
{ return _Func->IsPlayerWorldCompatible(player.GetIdentifier(), world) >= 1; }
|
{ return _Func->IsPlayerWorldCompatible(GetLgEntID< LgPlayer, CPlayer >(player), world) >= 1; }
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static LightObj & LgCreatePickupCompat(int model, const Vector3 & pos)
|
static LightObj & LgCreatePickupCompat(int model, const Vector3 & pos)
|
||||||
{ return Core::Get().NewPickup(model, 1, 0, pos.x, pos.y, pos.z, 255, false, SQMOD_CREATE_DEFAULT, NullLightObj()).mLgObj; }
|
{ return Core::Get().NewPickup(model, 1, 0, pos.x, pos.y, pos.z, 255, false, SQMOD_CREATE_DEFAULT, NullLightObj()).mLgObj; }
|
||||||
@@ -1449,7 +1469,7 @@ static LightObj & LgCreatePickup(int model, int world, int quantity, const Vecto
|
|||||||
static LightObj & LgCreateObject(int model, int world, const Vector3 & pos, int alpha)
|
static LightObj & LgCreateObject(int model, int world, const Vector3 & pos, int alpha)
|
||||||
{ return Core::Get().NewObject(model, world, pos.x, pos.y, pos.z, alpha, SQMOD_CREATE_DEFAULT, NullLightObj()).mLgObj; }
|
{ return Core::Get().NewObject(model, world, pos.x, pos.y, pos.z, alpha, SQMOD_CREATE_DEFAULT, NullLightObj()).mLgObj; }
|
||||||
static LightObj & LgCreateCheckpoint(LightObj & player, int world, bool sphere, const Vector3 & pos, const Color4 & col, float radius) {
|
static LightObj & LgCreateCheckpoint(LightObj & player, int world, bool sphere, const Vector3 & pos, const Color4 & col, float radius) {
|
||||||
const int32_t id = player.IsNull() ? -1 : player.CastI< LgPlayer >()->GetIdentifier();
|
const int32_t id = player.IsNull() ? -1 : GetLgEntID< LgPlayer, CPlayer >(player);
|
||||||
return Core::Get().NewCheckpoint(id, world, sphere, pos.x, pos.y, pos.z, col.r, col.g, col.b, col.a, radius, SQMOD_CREATE_DEFAULT, NullLightObj()).mLgObj;
|
return Core::Get().NewCheckpoint(id, world, sphere, pos.x, pos.y, pos.z, col.r, col.g, col.b, col.a, radius, SQMOD_CREATE_DEFAULT, NullLightObj()).mLgObj;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@@ -1507,30 +1527,30 @@ SQMOD_NODISCARD static int LgBindKey(bool down, int key1, int key2, int key3)
|
|||||||
SQMOD_NODISCARD static bool LgRemoveKeybind(int id) { return _Func->RemoveKeyBind(id) == vcmpErrorNone; }
|
SQMOD_NODISCARD static bool LgRemoveKeybind(int id) { return _Func->RemoveKeyBind(id) == vcmpErrorNone; }
|
||||||
static void LgRemoveAllKeybinds() { _Func->RemoveAllKeyBinds(); }
|
static void LgRemoveAllKeybinds() { _Func->RemoveAllKeyBinds(); }
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQMOD_NODISCARD static bool LgGetCinematicBorder(LgPlayer & player) { return _Func->GetPlayerOption(player.GetIdentifier(), vcmpPlayerOptionWidescreen) >= 1; }
|
SQMOD_NODISCARD static bool LgGetCinematicBorder(LightObj & player) { return _Func->GetPlayerOption(GetLgEntID< LgPlayer, CPlayer >(player), vcmpPlayerOptionWidescreen) >= 1; }
|
||||||
SQMOD_NODISCARD static bool LgGetGreenScanLines(LgPlayer & player) { return _Func->GetPlayerOption(player.GetIdentifier(), vcmpPlayerOptionGreenScanlines) >= 1; }
|
SQMOD_NODISCARD static bool LgGetGreenScanLines(LightObj & player) { return _Func->GetPlayerOption(GetLgEntID< LgPlayer, CPlayer >(player), vcmpPlayerOptionGreenScanlines) >= 1; }
|
||||||
SQMOD_NODISCARD static bool LgGetWhiteScanLines(LgPlayer & player) { return _Func->GetPlayerOption(player.GetIdentifier(), vcmpPlayerOptionWhiteScanlines) >= 1; }
|
SQMOD_NODISCARD static bool LgGetWhiteScanLines(LightObj & player) { return _Func->GetPlayerOption(GetLgEntID< LgPlayer, CPlayer >(player), vcmpPlayerOptionWhiteScanlines) >= 1; }
|
||||||
static void LgSetCinematicBorder(LgPlayer & player, bool toggle) { _Func->SetPlayerOption(player.GetIdentifier(), vcmpPlayerOptionWidescreen, static_cast< uint8_t >(toggle)); }
|
static void LgSetCinematicBorder(LightObj & player, bool toggle) { _Func->SetPlayerOption(GetLgEntID< LgPlayer, CPlayer >(player), vcmpPlayerOptionWidescreen, static_cast< uint8_t >(toggle)); }
|
||||||
static void LgSetGreenScanLines(LgPlayer & player, bool toggle) { _Func->SetPlayerOption(player.GetIdentifier(), vcmpPlayerOptionGreenScanlines, static_cast< uint8_t >(toggle)); }
|
static void LgSetGreenScanLines(LightObj & player, bool toggle) { _Func->SetPlayerOption(GetLgEntID< LgPlayer, CPlayer >(player), vcmpPlayerOptionGreenScanlines, static_cast< uint8_t >(toggle)); }
|
||||||
static void LgSetWhiteScanLines(LgPlayer & player, bool toggle) { _Func->SetPlayerOption(player.GetIdentifier(), vcmpPlayerOptionWhiteScanlines, static_cast< uint8_t >(toggle)); }
|
static void LgSetWhiteScanLines(LightObj & player, bool toggle) { _Func->SetPlayerOption(GetLgEntID< LgPlayer, CPlayer >(player), vcmpPlayerOptionWhiteScanlines, static_cast< uint8_t >(toggle)); }
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static void LgKickPlayer(LgPlayer & player) { _Func->KickPlayer(player.GetIdentifier()); }
|
static void LgKickPlayer(LightObj & player) { _Func->KickPlayer(GetLgEntID< LgPlayer, CPlayer >(player)); }
|
||||||
static void LgBanPlayer(LgPlayer & player) { _Func->BanPlayer(player.GetIdentifier()); }
|
static void LgBanPlayer(LightObj & player) { _Func->BanPlayer(GetLgEntID< LgPlayer, CPlayer >(player)); }
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static void LgMessage(StackStrF & msg) { _Func->SendClientMessage(-1, 0x0b5fa5ff, "%s", msg.mPtr); }
|
static void LgMessage(StackStrF & msg) { _Func->SendClientMessage(-1, 0x0b5fa5ff, "%s", msg.mPtr); }
|
||||||
static void LgMessagePlayer(StackStrF & msg, LgPlayer & player) { _Func->SendClientMessage(player.GetIdentifier(), 0x0b5fa5ff, "%s", msg.mPtr); }
|
static void LgMessagePlayer(StackStrF & msg, LightObj & player) { _Func->SendClientMessage(GetLgEntID< LgPlayer, CPlayer >(player), 0x0b5fa5ff, "%s", msg.mPtr); }
|
||||||
static void LgMessageAllExcept(StackStrF & msg, LgPlayer & player) {
|
static void LgMessageAllExcept(StackStrF & msg, LightObj & player) {
|
||||||
const int32_t p = player.GetIdentifier();
|
const auto p = GetLgEntID< LgPlayer, CPlayer >(player);
|
||||||
const SQChar * m = msg.mPtr;
|
const SQChar * m = msg.mPtr;
|
||||||
ForeachConnectedPlayer([=](int32_t id) { if (id != p) _Func->SendClientMessage(id, 0x0b5fa5ff, "%s", m); });
|
ForeachConnectedPlayer([=](int32_t id) { if (id != p) _Func->SendClientMessage(id, 0x0b5fa5ff, "%s", m); });
|
||||||
}
|
}
|
||||||
static void LgPrivMessage(LgPlayer & player, StackStrF & msg) { _Func->SendClientMessage(player.GetIdentifier(), 0x007f16ff, "** pm >> %s", msg.mPtr); }
|
static void LgPrivMessage(LightObj & player, StackStrF & msg) { _Func->SendClientMessage(GetLgEntID< LgPlayer, CPlayer >(player), 0x007f16ff, "** pm >> %s", msg.mPtr); }
|
||||||
static void LgPrivMessageAll(StackStrF & msg) {
|
static void LgPrivMessageAll(StackStrF & msg) {
|
||||||
const SQChar * m = msg.mPtr;
|
const SQChar * m = msg.mPtr;
|
||||||
ForeachConnectedPlayer([=](int32_t id) { _Func->SendClientMessage(id, 0x007f16ff, "** pm >> %s", m); });
|
ForeachConnectedPlayer([=](int32_t id) { _Func->SendClientMessage(id, 0x007f16ff, "** pm >> %s", m); });
|
||||||
}
|
}
|
||||||
static void LgSendPlayerMessage(LgPlayer & source, LgPlayer & target, StackStrF & msg) {
|
static void LgSendPlayerMessage(LightObj & source, LightObj & target, StackStrF & msg) {
|
||||||
_Func->SendClientMessage(target.GetIdentifier(), 0x007f16ff, "** pm from %s >> %s", source.Get().GetName(), msg.mPtr);
|
_Func->SendClientMessage(GetLgEntID< LgPlayer, CPlayer >(target), 0x007f16ff, "** pm from %s >> %s",GetNativeEnt< LgPlayer, CPlayer >(source).GetName(), msg.mPtr);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
SQMOD_NODISCARD static const SQChar * LgGetWeaponName(int id) { return GetWeaponName(static_cast< uint32_t >(id)); }
|
SQMOD_NODISCARD static const SQChar * LgGetWeaponName(int id) { return GetWeaponName(static_cast< uint32_t >(id)); }
|
||||||
@@ -2302,8 +2322,8 @@ struct LgStream {
|
|||||||
int32_t id;
|
int32_t id;
|
||||||
if (target.IsNull()) id = -1;
|
if (target.IsNull()) id = -1;
|
||||||
else if (target.GetType() == OT_INTEGER || target.GetType() == OT_FLOAT) id = target.Cast< int32_t >();
|
else if (target.GetType() == OT_INTEGER || target.GetType() == OT_FLOAT) id = target.Cast< int32_t >();
|
||||||
else if (static_cast< AbstractStaticClassData * >(target.GetTypeTag()) == StaticClassTypeTag< LgPlayer >::Get()) {
|
else if (target.GetType() == OT_INSTANCE) {
|
||||||
id = target.CastI< LgPlayer >()->GetIdentifier();
|
id = GetLgEntID< LgPlayer, CPlayer >(target);
|
||||||
} else STHROWF("Invalid target type");
|
} else STHROWF("Invalid target type");
|
||||||
if (id >= SQMOD_PLAYER_POOL) STHROWF("Invalid player ID");
|
if (id >= SQMOD_PLAYER_POOL) STHROWF("Invalid player ID");
|
||||||
_Func->SendClientScriptData(id, m_OutputStreamData, m_OutputStreamEnd);
|
_Func->SendClientScriptData(id, m_OutputStreamData, m_OutputStreamEnd);
|
||||||
|
@@ -2146,12 +2146,12 @@ struct SqDataAsyncBuilder
|
|||||||
SqDataAsyncBuilder & operator = (SqDataAsyncBuilder && o) = default;
|
SqDataAsyncBuilder & operator = (SqDataAsyncBuilder && o) = default;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Create the task with the suplied information and submit it to the worker pool.
|
* Create the task with the supplied information and submit it to the worker pool.
|
||||||
*/
|
*/
|
||||||
void Submit() { Submit_(NullLightObj()); }
|
void Submit() { Submit_(NullLightObj()); }
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Create the task with the suplied information and submit it to the worker pool.
|
* Create the task with the supplied information and submit it to the worker pool.
|
||||||
*/
|
*/
|
||||||
void Submit_(LightObj & ctx);
|
void Submit_(LightObj & ctx);
|
||||||
|
|
||||||
|
@@ -1,6 +1,3 @@
|
|||||||
#ifndef _REGISTER_HPP_
|
|
||||||
#define _REGISTER_HPP_
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#include <squirrelex.h>
|
#include <squirrelex.h>
|
||||||
|
|
||||||
@@ -144,5 +141,3 @@ bool RegisterAPI(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
|
||||||
#endif // _REGISTER_HPP_
|
|
||||||
|
75
module/SDK/sqmod.h
Normal file
75
module/SDK/sqmod.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#if !defined(_SQ_MOD_API_H_)
|
||||||
|
#define _SQ_MOD_API_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#ifndef SQMOD_API_EXPORT
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define SQMOD_API_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define SQMOD_API_EXPORT extern "C"
|
||||||
|
#else
|
||||||
|
#define SQMOD_API_EXPORT extern "C"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SQMOD_HOST_NAME "SqModHost"
|
||||||
|
#define SQMOD_INITIALIZE_CMD 0xDABBAD00 // host plug-in was initialized
|
||||||
|
#define SQMOD_LOAD_CMD 0xDEADBABE // API is being registered
|
||||||
|
#define SQMOD_TERMINATE_CMD 0xDEADC0DE // release your resources
|
||||||
|
#define SQMOD_CLOSING_CMD 0xBAAAAAAD // virtual machine is closing
|
||||||
|
#define SQMOD_RELEASED_CMD 0xDEADBEAF // virtual machine was closed
|
||||||
|
#define SQMOD_API_VER 1
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
typedef int32_t(*ExtPluginCommand_t)(int32_t, int32_t, int32_t, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* The structure exported by the host plug-in to import the module and squirrel API.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t StructSize;
|
||||||
|
/* Register a pointer to a function used to processes commands from script.
|
||||||
|
This is like the functionality offered by SendPluginCommand but offers interaction from
|
||||||
|
script side without interfering with other native plugins. And also offers a few extra
|
||||||
|
methods of identification to provide back and forth communication.
|
||||||
|
It offers a bare minimum, primitive way of interacting with the script from native plug-ins.
|
||||||
|
return : -1 it failed (no free slot), 0 if it was already registered and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t (*RegisterCommand) (ExtPluginCommand_t fn);
|
||||||
|
/* Remove a pointer to a function used to processes commands from script.
|
||||||
|
return : -1 it failed (no free slot) and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t (*UnregisterCommand) (ExtPluginCommand_t fn);
|
||||||
|
/* Send a command to all functions currently registered to receive them. This is mostly used by the script.
|
||||||
|
target - ideally a unique value that can be used to identify the intended audience for the command.
|
||||||
|
req : ideally a unique value that can be used to identify the requested information from the command.
|
||||||
|
tag : ideally a unique value that can be used to identify a later response if one is generated.
|
||||||
|
data : binary data that represents the command payload. the command is free to interpret it however it wants.
|
||||||
|
size : size of the binary data. most likely in bytes but the command is free to interpret it however it wants.
|
||||||
|
*/
|
||||||
|
int32_t (*SendCommand) (int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
/* Send a response to the script that may have resulted from a previous command. This is mostly by the native plug-ins.
|
||||||
|
sender : ideally a unique value that can be used to identify the intended who generated the response.
|
||||||
|
tag : ideally a unique value that can be used to identify what the generated response might contain/provide.
|
||||||
|
data : binary data that represents the command payload. the command is free to interpret it however it wants.
|
||||||
|
size : size of the binary data. most likely in bytes but the command is free to interpret it however it wants.
|
||||||
|
*/
|
||||||
|
int32_t (*SendCommandReply) (int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
/* Forward an event to the script from an external plug-in. This is mostly by the native plug-ins.
|
||||||
|
Similar to SendCommandReply but may not have been the result of a previous command.
|
||||||
|
*/
|
||||||
|
int32_t (*SendCommandEvent) (int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
} sq_mod_exports, SQ_MOD_EXPORTS, *HSQ_MOD_EXPORTS;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif /*_SQ_MOD_API_H_*/
|
@@ -195,21 +195,7 @@ struct LightObj {
|
|||||||
///
|
///
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
template<class T, class... A>
|
template<class T, class... A>
|
||||||
LightObj(SqTypeIdentity< T > SQ_UNUSED_ARG(t), HSQUIRRELVM vm, A&&... a) {
|
LightObj(SqTypeIdentity< T > SQ_UNUSED_ARG(t), HSQUIRRELVM vm, A&&... a) : LightObj(DeleteGuard< T >(new T(std::forward< A >(a)...))) {
|
||||||
// Create the instance and guard it to make sure it gets deleted in case of exceptions
|
|
||||||
DeleteGuard< T > instance(new T(std::forward< A >(a)...));
|
|
||||||
// Preserve the stack state
|
|
||||||
const StackGuard sg(vm);
|
|
||||||
// Push the instance on the stack
|
|
||||||
ClassType<T>::PushInstance(vm, instance);
|
|
||||||
// Attempt to retrieve it
|
|
||||||
if (SQ_FAILED(sq_getstackobj(vm, -1, &mObj))) {
|
|
||||||
sq_resetobject(&mObj);
|
|
||||||
} else {
|
|
||||||
sq_addref(vm, &mObj);
|
|
||||||
}
|
|
||||||
// Stop guarding the instance
|
|
||||||
instance.Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -246,7 +232,21 @@ struct LightObj {
|
|||||||
///
|
///
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
template<class T>
|
template<class T>
|
||||||
LightObj(DeleteGuard<T> guard, HSQUIRRELVM v = SqVM()) : LightObj(guard.Get(), v) {
|
LightObj(DeleteGuard<T> && guard, HSQUIRRELVM v = SqVM()) : LightObj(guard.Get(), v) {
|
||||||
|
guard.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Constructs an LightObj from a C++ instance wrapped inside a DeleteGuard
|
||||||
|
///
|
||||||
|
/// \param instance Pointer to a C++ class instance that has been bound already
|
||||||
|
/// \param v VM that the object will exist in
|
||||||
|
///
|
||||||
|
/// \tparam T Type of instance
|
||||||
|
///
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<class T>
|
||||||
|
LightObj(DeleteGuard<T> & guard, HSQUIRRELVM v = SqVM()) : LightObj(guard.Get(), v) {
|
||||||
guard.Release();
|
guard.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <Poco/Exception.h>
|
#include <Poco/Exception.h>
|
||||||
@@ -1580,12 +1581,31 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Helper structure for one element from the top of stack. Uses default global VM instead.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct SqPopTopGuardLite
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Base constructor.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
SqPopTopGuardLite() noexcept = default;
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Destructor. Pops the specified elements from the stack.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
~SqPopTopGuardLite()
|
||||||
|
{
|
||||||
|
sq_poptop(SqVM());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Helper structure for one element from the top of stack.
|
/// Helper structure for one element from the top of stack.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
struct SqPopTopGuard
|
struct SqPopTopGuard
|
||||||
{
|
{
|
||||||
HSQUIRRELVM mVM; // The VM from which the elements must be popped.
|
HSQUIRRELVM mVM; // The VM from which the elements must be popped.
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Base constructor.
|
/// Base constructor.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1603,13 +1623,70 @@ struct SqPopTopGuard
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Helper structure for popping elements from the stack. Uses default global VM instead.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct SqPopGuardLite
|
||||||
|
{
|
||||||
|
SQInteger mNum{0}; // The number of elements to be popped.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Base constructor.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
explicit SqPopGuardLite(SQInteger num) noexcept
|
||||||
|
: mNum(num)
|
||||||
|
{
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Destructor. Pops the specified elements from the stack.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
~SqPopGuardLite()
|
||||||
|
{
|
||||||
|
sq_pop(SqVM(), mNum);
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Increment the number of elements to be popped.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
SqPopGuardLite & operator ++ ()
|
||||||
|
{
|
||||||
|
++mNum;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Decrement the number of elements to be popped.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
SqPopGuardLite & operator -- ()
|
||||||
|
{
|
||||||
|
--mNum;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Increase the number of elements to be popped.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
SqPopGuardLite & operator += (SQInteger n)
|
||||||
|
{
|
||||||
|
mNum += n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Decrease the number of elements to be popped.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
SqPopGuardLite & operator -= (SQInteger n)
|
||||||
|
{
|
||||||
|
mNum -= n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Helper structure for popping elements from the stack.
|
/// Helper structure for popping elements from the stack.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
struct SqPopGuard
|
struct SqPopGuard
|
||||||
{
|
{
|
||||||
HSQUIRRELVM mVM; // The VM from which the elements must be popped.
|
HSQUIRRELVM mVM{nullptr}; // The VM from which the elements must be popped.
|
||||||
SQInteger mNum; // The number of elements to be popped.
|
SQInteger mNum{0}; // The number of elements to be popped.
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Base constructor.
|
/// Base constructor.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1659,17 +1736,79 @@ struct SqPopGuard
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Implements RAII to restore the VM stack to it's initial size on function exit. Uses default global VM instead.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct StackGuardLite
|
||||||
|
{
|
||||||
|
SQInteger mTop{0}; ///< The top of the stack when this instance was created.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StackGuardLite() noexcept
|
||||||
|
: mTop(sq_gettop(SqVM()))
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Copy constructor. (disabled)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StackGuardLite(const StackGuardLite &) = delete;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Move constructor. (disabled)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StackGuardLite(StackGuardLite &&) = delete;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Destructor.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
~StackGuardLite()
|
||||||
|
{
|
||||||
|
Restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Copy assignment operator. (disabled)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StackGuardLite & operator = (const StackGuardLite &) = delete;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Move assignment operator. (disabled)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StackGuardLite & operator = (StackGuardLite &&) = delete;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Restore the stack to what was known to be.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Restore() const
|
||||||
|
{
|
||||||
|
auto vm = SqVM();
|
||||||
|
// Retrieve the new stack top
|
||||||
|
const SQInteger top = sq_gettop(vm);
|
||||||
|
// Did the stack size change?
|
||||||
|
if (top > mTop)
|
||||||
|
{
|
||||||
|
sq_pop(vm, top - mTop); // Trim the stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Implements RAII to restore the VM stack to it's initial size on function exit.
|
/// Implements RAII to restore the VM stack to it's initial size on function exit.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
struct StackGuard
|
struct StackGuard
|
||||||
{
|
{
|
||||||
|
HSQUIRRELVM mVM{nullptr}; ///< The VM where the stack should be restored.
|
||||||
|
SQInteger mTop{0}; ///< The top of the stack when this instance was created.
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Default constructor.
|
/// Default constructor.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
StackGuard()
|
StackGuard()
|
||||||
: m_VM(SqVM()), m_Top(sq_gettop(m_VM))
|
: mVM(SqVM()), mTop(sq_gettop(mVM))
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -1677,8 +1816,8 @@ struct StackGuard
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Base constructor.
|
/// Base constructor.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
StackGuard(HSQUIRRELVM vm)
|
explicit StackGuard(HSQUIRRELVM vm)
|
||||||
: m_VM(vm), m_Top(sq_gettop(vm))
|
: mVM(vm), mTop(sq_gettop(vm))
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -1717,18 +1856,13 @@ struct StackGuard
|
|||||||
void Restore() const
|
void Restore() const
|
||||||
{
|
{
|
||||||
// Retrieve the new stack top
|
// Retrieve the new stack top
|
||||||
const SQInteger top = sq_gettop(m_VM);
|
const SQInteger top = sq_gettop(mVM);
|
||||||
// Did the stack size change?
|
// Did the stack size change?
|
||||||
if (top > m_Top)
|
if (top > mTop)
|
||||||
{
|
{
|
||||||
sq_pop(m_VM, top - m_Top); // Trim the stack
|
sq_pop(mVM, top - mTop); // Trim the stack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
HSQUIRRELVM m_VM; ///< The VM where the stack should be restored.
|
|
||||||
SQInteger m_Top; ///< The top of the stack when this instance was created.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -2131,18 +2265,13 @@ inline void ErrorToException(HSQUIRRELVM vm, bool keep = false) {
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
template < typename T > struct DeleteGuard
|
template < typename T > struct DeleteGuard
|
||||||
{
|
{
|
||||||
private:
|
T * mPtr; // Pointer to the instance to manage.
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
|
||||||
T * m_Ptr; // Pointer to the instance to manage.
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Default constructor.
|
/// Default constructor.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
explicit DeleteGuard(T * ptr)
|
explicit DeleteGuard(T * ptr)
|
||||||
: m_Ptr(ptr)
|
: mPtr(ptr)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -2152,7 +2281,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
template<class... A>
|
template<class... A>
|
||||||
explicit DeleteGuard(SqInPlace SQ_UNUSED_ARG(t), A&&... a)
|
explicit DeleteGuard(SqInPlace SQ_UNUSED_ARG(t), A&&... a)
|
||||||
: m_Ptr(new T(std::forward< A >(a)...))
|
: mPtr(new T(std::forward< A >(a)...))
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -2166,9 +2295,9 @@ public:
|
|||||||
/// Move constructor.
|
/// Move constructor.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
DeleteGuard(DeleteGuard && o) noexcept
|
DeleteGuard(DeleteGuard && o) noexcept
|
||||||
: m_Ptr(o.m_Ptr)
|
: mPtr(o.mPtr)
|
||||||
{
|
{
|
||||||
o.m_Ptr = nullptr;
|
o.mPtr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2176,9 +2305,9 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
~DeleteGuard()
|
~DeleteGuard()
|
||||||
{
|
{
|
||||||
if (m_Ptr)
|
if (mPtr)
|
||||||
{
|
{
|
||||||
delete m_Ptr;
|
delete mPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2197,7 +2326,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
operator T * () const
|
operator T * () const
|
||||||
{
|
{
|
||||||
return m_Ptr;
|
return mPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2205,7 +2334,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
T * Get() const
|
T * Get() const
|
||||||
{
|
{
|
||||||
return m_Ptr;
|
return mPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2213,7 +2342,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
void Release()
|
void Release()
|
||||||
{
|
{
|
||||||
m_Ptr = nullptr;
|
mPtr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2221,8 +2350,8 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
T * Grab()
|
T * Grab()
|
||||||
{
|
{
|
||||||
T * ptr = m_Ptr;
|
T * ptr = mPtr;
|
||||||
m_Ptr = nullptr;
|
mPtr = nullptr;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2320,18 +2449,13 @@ template < typename T > T * SqChainedInstances< T >::sHead = nullptr;
|
|||||||
/// @cond DEV
|
/// @cond DEV
|
||||||
/// Used internally to get and manipulate the underlying type of variables - retrieved from cppreference.com
|
/// Used internally to get and manipulate the underlying type of variables - retrieved from cppreference.com
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
template<class T> struct remove_const {typedef T type;};
|
template<class T> using remove_const = std::remove_const< T >;
|
||||||
template<class T> struct remove_const<const T> {typedef T type;};
|
template<class T> using remove_volatile = std::remove_volatile< T >;
|
||||||
template<class T> struct remove_volatile {typedef T type;};
|
template<class T> using remove_cv = std::remove_cv< T >;
|
||||||
template<class T> struct remove_volatile<volatile T> {typedef T type;};
|
template<class T> struct is_pointer : public std::is_pointer< T > { };
|
||||||
template<class T> struct remove_cv {typedef typename remove_volatile<typename remove_const<T>::type>::type type;};
|
template<class T,class D> struct is_pointer<SharedPtr<T,D> > : public std::true_type { };
|
||||||
template<class T> struct is_pointer_helper {static constexpr bool value = false;};
|
template<class T,class D> struct is_pointer<WeakPtr<T,D> > : public std::true_type { };
|
||||||
template<class T> struct is_pointer_helper<T*> {static constexpr bool value = true;};
|
template<class T> using is_reference = std::is_lvalue_reference< T >;
|
||||||
template<class T,class D> struct is_pointer_helper<SharedPtr<T,D> > {static constexpr bool value = true;};
|
|
||||||
template<class T,class D> struct is_pointer_helper<WeakPtr<T,D> > {static constexpr bool value = true;};
|
|
||||||
template<class T> struct is_pointer : is_pointer_helper<typename remove_cv<T>::type> {};
|
|
||||||
template<class T> struct is_reference {static constexpr bool value = false;};
|
|
||||||
template<class T> struct is_reference<T&> {static constexpr bool value = true;};
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user