Refactoring to move things from GameMode into UlxEngineWrapper subsystem.

This commit is contained in:
2026-02-27 17:00:46 -05:00
parent 0aea1e0798
commit 7bb4854844
6 changed files with 99 additions and 119 deletions

View File

@@ -5,18 +5,13 @@
using namespace LpxCommonTypes; using namespace LpxCommonTypes;
UlxEngineWrapper* UlxEngineWrapper::Instance = nullptr;
void FlxLockedWrapper::DPrintHook(const char *Msg, size_t Size) void UlxEngineWrapper::Initialize(FSubsystemCollectionBase& Collection) {
{ Super::Initialize(Collection);
FString FMessage(Size, (const UTF8CHAR *)Msg); Instance = this;
UE_LOG(LogLuprex, Error, TEXT("%s"), *FMessage);
}
void FlxLockedWrapper::InitWrapper() { // Open the DLL and hook up all the function pointers.
if (Lockable.Wrapper.play_initialize != nullptr) {
// Already initialized.
return;
}
#if PLATFORM_LINUX #if PLATFORM_LINUX
FString dll = FPaths::Combine(FPaths::ProjectDir(), TEXT("luprex/build/Linux/luprexlib.so")); FString dll = FPaths::Combine(FPaths::ProjectDir(), TEXT("luprex/build/Linux/luprexlib.so"));
#elif PLATFORM_WINDOWS #elif PLATFORM_WINDOWS
@@ -30,12 +25,24 @@ void FlxLockedWrapper::InitWrapper() {
using InitFn = void (*)(EngineWrapper*); using InitFn = void (*)(EngineWrapper*);
InitFn init = (InitFn)FPlatformProcess::GetDllExport(DLL, TEXT("init_engine_wrapper")); InitFn init = (InitFn)FPlatformProcess::GetDllExport(DLL, TEXT("init_engine_wrapper"));
if (init != nullptr) { if (init != nullptr) {
init(&Lockable.Wrapper); init(&Wrapper);
Lockable.Wrapper.hook_dprint(DPrintHook); Wrapper.hook_dprint(DPrintHook);
} }
} }
} }
void UlxEngineWrapper::Deinitialize() {
Instance = nullptr;
Super::Deinitialize();
}
void UlxEngineWrapper::DPrintHook(const char *Msg, size_t Size)
{
FString FMessage(Size, (const UTF8CHAR *)Msg);
UE_LOG(LogLuprex, Error, TEXT("%s"), *FMessage);
}
FString FlxLockedWrapper::ChannelPrints() { FString FlxLockedWrapper::ChannelPrints() {
if (Lockable.Wrapper.get_have_prints(Get())) if (Lockable.Wrapper.get_have_prints(Get()))
{ {
@@ -62,22 +69,27 @@ IdView FlxLockedWrapper::GetNear(int64 id, double rx, double ry, double rz) {
} }
StringViewVec FlxLockedWrapper::GetAnimationQueues(IdView ids) { StringViewVec FlxLockedWrapper::GetAnimationQueues(IdView ids) {
// This is only called from the game thread, so
// these static buffers are safe without locking.
static TArray<uint32> AQLenBuffer;
static TArray<const char*> AQStrBuffer;
// How many animation queues are we fetching? // How many animation queues are we fetching?
int num = ids.Num(); int num = ids.Num();
// Enlarge the static buffers if necessary. // Enlarge the buffers if necessary.
// Add a little extra space so we don't have to enlarge // Add a little extra space so we don't have to enlarge
// the buffers every time we get a new tangible. // the buffers every time we get a new tangible.
if (num > Lockable.AQLenBuffer.Num()) { if (num > AQLenBuffer.Num()) {
Lockable.AQLenBuffer.SetNum(num + 1000); AQLenBuffer.SetNum(num + 1000);
Lockable.AQStrBuffer.SetNum(num + 1000); AQStrBuffer.SetNum(num + 1000);
} }
// Get pointers to the static buffers. // Get pointers to the buffers.
uint32* LenBuf = Lockable.AQLenBuffer.GetData(); uint32* LenBuf = AQLenBuffer.GetData();
const char** StrBuf = Lockable.AQStrBuffer.GetData(); const char** StrBuf = AQStrBuffer.GetData();
// Get the animation queues into the static buffers. // Get the animation queues into the buffers.
Lockable.Wrapper.get_animation_queues(Get(), num, (const int64_t *)ids.GetData(), LenBuf, StrBuf); Lockable.Wrapper.get_animation_queues(Get(), num, (const int64_t *)ids.GetData(), LenBuf, StrBuf);
// Transfer data from static buffers into an array of string_view // Transfer data from static buffers into an array of string_view

View File

@@ -11,29 +11,50 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "lpx-enginewrapper.hpp" #include "lpx-enginewrapper.hpp"
#include "Common.h" #include "Common.h"
#include "StreamBuffer.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "LockedWrapper.generated.h"
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// FlxLockableWrapper // UlxEngineWrapper
// //
// Contains the EngineWrapper and a Mutex to lock it. // GameInstanceSubsystem that owns the EngineWrapper and
// This class has no methods. To access the // a Mutex to lock it. To access the EngineWrapper,
// EngineWrapper, construct a FlxLockedWrapper. // construct a FlxLockedWrapper.
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class FlxLockableWrapper { UCLASS()
class INTEGRATION_API UlxEngineWrapper : public UGameInstanceSubsystem {
GENERATED_BODY()
private: private:
static UlxEngineWrapper* Instance;
// Called by luprex to output debugging messages.
// A thin wrapper around UE_LOG.
//
static void DPrintHook(const char *Msg, size_t Size);
FCriticalSection Mutex; FCriticalSection Mutex;
EngineWrapper Wrapper; EngineWrapper Wrapper;
// Temporary buffers used only inside wrapper // The Lua Call Assembly Buffer. Used to build up
// methods. Nothing persistent in these. // a call across multiple UFUNCTION invocations.
// Only accessed from the game thread.
// //
TArray<uint32> AQLenBuffer; FlxStreamBuffer LuaCallBuffer;
TArray<const char*> AQStrBuffer;
public: public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// Get the Lua Call Assembly Buffer.
// Only called from the game thread.
//
static FlxStreamBuffer& GetLuaCallBuffer() { return Instance->LuaCallBuffer; }
friend class FlxLockedWrapper; friend class FlxLockedWrapper;
}; };
@@ -49,12 +70,7 @@ public:
class FlxLockedWrapper { class FlxLockedWrapper {
private: private:
FlxLockableWrapper& Lockable; UlxEngineWrapper& Lockable;
// Called by luprex to output debugging messages.
// A thin wrapper around UE_LOG.
//
static void DPrintHook(const char *Msg, size_t Size);
public: public:
// Import these types into our namespace. // Import these types into our namespace.
@@ -66,7 +82,7 @@ public:
public: public:
// The constructor claims the mutex. // The constructor claims the mutex.
// //
FlxLockedWrapper(FlxLockableWrapper& w) : Lockable(w) { FlxLockedWrapper() : Lockable(*UlxEngineWrapper::Instance) {
Lockable.Mutex.Lock(); Lockable.Mutex.Lock();
} }
@@ -90,13 +106,6 @@ public:
return &Lockable.Wrapper; return &Lockable.Wrapper;
} }
// Initialize the engine wrapper if it's not
// already. All this does is open the DLL and
// hook up all the function pointers in the
// wrapper to point into the DLL.
//
void InitWrapper();
// Fetch Stdout as a string. // Fetch Stdout as a string.
// //
FString ChannelPrints(); FString ChannelPrints();

View File

@@ -1,6 +1,6 @@
#include "LuaCall.h" #include "LuaCall.h"
#include "LuprexGameModeBase.h" #include "LockedWrapper.h"
#include "Tangible.h" #include "Tangible.h"
#include "StreamBuffer.h" #include "StreamBuffer.h"
@@ -199,8 +199,7 @@ FString UlxLuaCallLibrary::AllFunctionsWithPrefix(const TCHAR *Prefix)
void UlxLuaCallLibrary::InvokeLuaExpr(UObject *context, const FString &Code) void UlxLuaCallLibrary::InvokeLuaExpr(UObject *context, const FString &Code)
{ {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxLockedWrapper w;
FlxLockedWrapper w(mode->GetLockableWrapper());
w.InvokeLuaExpr(Code); w.InvokeLuaExpr(Code);
} }
@@ -218,8 +217,7 @@ static int64 ResolvePlaceId(AActor *place)
void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname) void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname)
{ {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
sb.clear(); sb.clear();
sb.write_string(cname); sb.write_string(cname);
sb.write_string(fname); sb.write_string(fname);
@@ -227,29 +225,27 @@ void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, con
void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place) void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place)
{ {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
int64 place_id = ResolvePlaceId(place); int64 place_id = ResolvePlaceId(place);
if (place_id < 0) { sb.clear(); return; } if (place_id < 0) { sb.clear(); return; }
FlxLockedWrapper w(mode->GetLockableWrapper()); FlxLockedWrapper w;
w.InvokeLuaFunction(sb.view(), place_id); w.InvokeLuaFunction(sb.view(), place_id);
sb.clear(); sb.clear();
} }
bool UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place, UlxLuaValues *&ReturnArray) bool UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place, UlxLuaValues *&ReturnArray)
{ {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return false; if (NotInitialized(sb)) return false;
int64 place_id = ResolvePlaceId(place); int64 place_id = ResolvePlaceId(place);
if (place_id < 0) { if (place_id < 0) {
sb.clear(); sb.clear();
ReturnArray = NewObject<UlxLuaValues>(mode); ReturnArray = NewObject<UlxLuaValues>();
return false; return false;
} }
ReturnArray = NewObject<UlxLuaValues>(mode); ReturnArray = NewObject<UlxLuaValues>();
FlxLockedWrapper w(mode->GetLockableWrapper()); FlxLockedWrapper w;
w.ProbeLuaFunction(sb.view(), place_id, [&](std::string_view retpk) { w.ProbeLuaFunction(sb.view(), place_id, [&](std::string_view retpk) {
ReturnArray->Initialize(retpk); ReturnArray->Initialize(retpk);
}); });
@@ -285,8 +281,7 @@ bool UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place, UlxLuaValu
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
void UlxLuaCallLibrary::LuaCallArgument_string(UObject *context, const FString &pstring) { void UlxLuaCallLibrary::LuaCallArgument_string(UObject *context, const FString &pstring) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::STRING); sb.write_lua_value_type(LuaValueType::STRING);
sb.write_string(pstring); sb.write_string(pstring);
@@ -300,40 +295,35 @@ void UlxLuaCallLibrary::LuaCallArgument_name(UObject *context, const FName &pnam
{ {
UE_LOG(LogBlueprint, Error, TEXT("Names passed to lua must be short, and must contain only lowercase and digits")); UE_LOG(LogBlueprint, Error, TEXT("Names passed to lua must be short, and must contain only lowercase and digits"));
} }
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::TOKEN); sb.write_lua_value_type(LuaValueType::TOKEN);
sb.write_string(namestr); sb.write_string(namestr);
} }
void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) { void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::NUMBER); sb.write_lua_value_type(LuaValueType::NUMBER);
sb.write_double(pfloat); sb.write_double(pfloat);
} }
void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) { void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::NUMBER); sb.write_lua_value_type(LuaValueType::NUMBER);
sb.write_double(value); sb.write_double(value);
} }
void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &pvector) { void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &pvector) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::VECTOR); sb.write_lua_value_type(LuaValueType::VECTOR);
sb.write_fvector(pvector); sb.write_fvector(pvector);
} }
void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector2D &pvector) { void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector2D &pvector) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::VECTOR); sb.write_lua_value_type(LuaValueType::VECTOR);
sb.write_double(pvector.X); sb.write_double(pvector.X);
@@ -342,8 +332,7 @@ void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector
} }
void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) { void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxStreamBuffer &sb = UlxEngineWrapper::GetLuaCallBuffer();
FlxStreamBuffer &sb = mode->GetLuaCallBuffer();
if (NotInitialized(sb)) return; if (NotInitialized(sb)) return;
sb.write_lua_value_type(LuaValueType::BOOLEAN); sb.write_lua_value_type(LuaValueType::BOOLEAN);
sb.write_bool(pbool); sb.write_bool(pbool);

View File

@@ -1,6 +1,7 @@
// Copyright Epic Games, Inc. All Rights Reserved. // Copyright Epic Games, Inc. All Rights Reserved.
#include "LuprexGameModeBase.h" #include "LuprexGameModeBase.h"
#include "LockedWrapper.h"
#include "lpx-drvutil.hpp" #include "lpx-drvutil.hpp"
#include "Misc/Paths.h" #include "Misc/Paths.h"
#include "Tangible.h" #include "Tangible.h"
@@ -20,25 +21,17 @@ using namespace LpxCommonTypes;
ALuprexGameModeBase::ALuprexGameModeBase() ALuprexGameModeBase::ALuprexGameModeBase()
{ {
PlayerId = 0;
EngineSeconds = 0.0;
MustCallLookAtChanged = false;
//PrimaryActorTick.bCanEverTick = true; // Probably wrong
//PrimaryActorTick.bTickEvenWhenPaused = true; // Probably wrong
//PrimaryActorTick.TickGroup = TG_PrePhysics; // Probably wrong
ResetToInitialState();
} }
ALuprexGameModeBase::~ALuprexGameModeBase() ALuprexGameModeBase::~ALuprexGameModeBase()
{ {
ResetToInitialState();
} }
// This method runs in the background thread, // This method runs in the background thread,
// at the moment we trigger it. // at the moment we trigger it.
// //
uint32 ALuprexGameModeBase::Run() { uint32 ALuprexGameModeBase::Run() {
FlxLockedWrapper lockedwrap(LockableWrapper); FlxLockedWrapper lockedwrap;
if (lockedwrap->get_rescan_lua_source(lockedwrap.Get())) if (lockedwrap->get_rescan_lua_source(lockedwrap.Get()))
{ {
drvutil::ostringstream srcpak; drvutil::ostringstream srcpak;
@@ -77,7 +70,7 @@ void ALuprexGameModeBase::ResetToInitialState()
// Now that the thread's gone, we should be able to // Now that the thread's gone, we should be able to
// just claim and hold the lock on the wrapper. // just claim and hold the lock on the wrapper.
FlxLockedWrapper w(LockableWrapper); FlxLockedWrapper w;
// Release and close all sockets. // Release and close all sockets.
if (Sockets != nullptr) if (Sockets != nullptr)
@@ -92,12 +85,12 @@ void ALuprexGameModeBase::ResetToInitialState()
w->release(w.Get()); w->release(w.Get());
} }
// Clear the lua call assembly buffer.
UlxEngineWrapper::GetLuaCallBuffer().clear();
// Stop trapping log errors to the debugger. // Stop trapping log errors to the debugger.
BreakToDebuggerLogVerbosityDevice.Reset(); BreakToDebuggerLogVerbosityDevice.Reset();
// Clear the lua call assembly buffer.
LuaCallBuffer.clear();
// Clear the PlayerID // Clear the PlayerID
PlayerId = 0; PlayerId = 0;
@@ -112,7 +105,7 @@ void ALuprexGameModeBase::ResetToInitialState()
void ALuprexGameModeBase::UpdateConsoleOutput() { void ALuprexGameModeBase::UpdateConsoleOutput() {
// Copy Luprex Stdout into the console. // Copy Luprex Stdout into the console.
FlxLockedWrapper lockedwrap(LockableWrapper); FlxLockedWrapper lockedwrap;
if (Playing) { if (Playing) {
FString Text = lockedwrap.ChannelPrints(); FString Text = lockedwrap.ChannelPrints();
if (!Text.IsEmpty()) if (!Text.IsEmpty())
@@ -130,7 +123,7 @@ void ALuprexGameModeBase::UpdateTangibles() {
UlxTangibleManager *TM = GetGameInstance()->GetSubsystem<UlxTangibleManager>(); UlxTangibleManager *TM = GetGameInstance()->GetSubsystem<UlxTangibleManager>();
TanArray alltans; TanArray alltans;
{ {
FlxLockedWrapper w(LockableWrapper); FlxLockedWrapper w;
PlayerId = w.GetActor(); PlayerId = w.GetActor();
IdView nearids = w.GetNear(PlayerId, radius, radius, radius); IdView nearids = w.GetNear(PlayerId, radius, radius, radius);
TM->UpdateNearAccordingToLuprex(nearids); TM->UpdateNearAccordingToLuprex(nearids);
@@ -210,15 +203,12 @@ void ALuprexGameModeBase::BeginPlay()
void ALuprexGameModeBase::InitializeGlobalState() void ALuprexGameModeBase::InitializeGlobalState()
{ {
FlxLockedWrapper w(LockableWrapper); FlxLockedWrapper w;
// Sanity checks. Make sure everything is clean. // Sanity checks. Make sure everything is clean.
checkf(!LuprexUpdateTask.IsRunning(), TEXT("There should be no thread here.")); checkf(!LuprexUpdateTask.IsRunning(), TEXT("There should be no thread here."));
checkf(w->engine == nullptr, TEXT("There should be no engine here.")); checkf(w->engine == nullptr, TEXT("There should be no engine here."));
// Try to initialize the wrapper.
w.InitWrapper();
// If we failed to initialize the wrapper, print an error message. // If we failed to initialize the wrapper, print an error message.
if (w->play_initialize == nullptr) if (w->play_initialize == nullptr)
{ {

View File

@@ -5,8 +5,6 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Engine/HitResult.h" #include "Engine/HitResult.h"
#include "GameFramework/GameModeBase.h" #include "GameFramework/GameModeBase.h"
#include "lpx-enginewrapper.hpp"
#include "StreamBuffer.h"
#include "LuprexSockets.h" #include "LuprexSockets.h"
#include "TriggeredTask.h" #include "TriggeredTask.h"
#include "BreakToDebugger.h" #include "BreakToDebugger.h"
@@ -66,13 +64,6 @@ public:
void LookAtChanged(); void LookAtChanged();
// The Lua Call Assembly Buffer. Used by
// UlxLuaCallLibrary to build up a call across
// multiple UFUNCTION invocations.
//
FlxStreamBuffer &GetLuaCallBuffer() { return LuaCallBuffer; }
// Transfer console output from the Luprex engine to unreal. // Transfer console output from the Luprex engine to unreal.
void UpdateConsoleOutput(); void UpdateConsoleOutput();
@@ -104,24 +95,12 @@ public:
UPROPERTY() UPROPERTY()
FHitResult CurrentLookAt; FHitResult CurrentLookAt;
bool MustCallLookAtChanged; bool MustCallLookAtChanged = false;
// The sensitivity level at which a log message triggers a debugger breakpoint. // The sensitivity level at which a log message triggers a debugger breakpoint.
UPROPERTY(EditAnywhere, Category="Debugging Tools") UPROPERTY(EditAnywhere, Category="Debugging Tools")
ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity; ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity;
// The Luprex EngineWrapper, with a Mutex to protect it.
// To access it, construct a FlxLockedWrapper.
//
FlxLockableWrapper LockableWrapper;
// Get the LockableWrapper.
//
FlxLockableWrapper& GetLockableWrapper() { return LockableWrapper; }
// The Lua Call Assembly Buffer.
FlxStreamBuffer LuaCallBuffer;
// This utility runs the luprex update and socket update in a thread. // This utility runs the luprex update and socket update in a thread.
FTriggeredTask LuprexUpdateTask; FTriggeredTask LuprexUpdateTask;
@@ -129,19 +108,19 @@ public:
TUniquePtr<FlxSockets> Sockets; TUniquePtr<FlxSockets> Sockets;
// True if 'BeginPlay' has been successfully completed. // True if 'BeginPlay' has been successfully completed.
bool Playing; bool Playing = false;
// This is always true unless you use the debugger to set it to false. // This is always true unless you use the debugger to set it to false.
bool TickEnabled; bool TickEnabled = true;
// Current Player ID // Current Player ID
int64 PlayerId; int64 PlayerId = 0;
// Amount of elapsed time since BeginPlay. // Amount of elapsed time since BeginPlay.
float EngineSeconds; float EngineSeconds = 0.0f;
// When do we next rotate the cube. // When do we next rotate the cube.
float NextRotateCube; float NextRotateCube = 1.0f;
// These allow us to pre-tick and post-tick. // These allow us to pre-tick and post-tick.
FDelegateHandle OnWorldPreActorTickHandle; FDelegateHandle OnWorldPreActorTickHandle;

View File

@@ -2,7 +2,8 @@
#include "UtilityLibrary.h" #include "UtilityLibrary.h"
#include "LuprexGameModeBase.h" #include "LockedWrapper.h"
#include "Engine/GameViewportClient.h"
#include "GameFramework/PlayerController.h" #include "GameFramework/PlayerController.h"
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "Kismet/KismetSystemLibrary.h" #include "Kismet/KismetSystemLibrary.h"
@@ -12,6 +13,7 @@
#include "InputMappingContext.h" #include "InputMappingContext.h"
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"
#include "Animation/AnimSequenceBase.h" #include "Animation/AnimSequenceBase.h"
#include "GameFramework/Pawn.h"
#define LOCTEXT_NAMESPACE "Luprex Utility" #define LOCTEXT_NAMESPACE "Luprex Utility"
@@ -256,7 +258,6 @@ FVector UlxUtilityLibrary::GetActorForwardVelocity(const AActor *Actor, double S
void UlxUtilityLibrary::ValidateLuaExpr( void UlxUtilityLibrary::ValidateLuaExpr(
ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code) ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code)
{ {
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context); FlxLockedWrapper w;
FlxLockedWrapper w(mode->GetLockableWrapper());
Status = w.ValidateLuaExpr(Code, ErrorMessage); Status = w.ValidateLuaExpr(Code, ErrorMessage);
} }