2026-02-14 02:14:19 -05:00
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// LockedWrapper.h
|
|
|
|
|
//
|
|
|
|
|
// Mutex-guarded access to the EngineWrapper.
|
|
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-09-03 02:01:32 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "CoreMinimal.h"
|
2023-09-07 03:57:29 -04:00
|
|
|
#include "lpx-enginewrapper.hpp"
|
2026-02-09 13:54:00 -05:00
|
|
|
#include "Common.h"
|
2026-02-27 17:00:46 -05:00
|
|
|
#include "StreamBuffer.h"
|
|
|
|
|
#include "Subsystems/GameInstanceSubsystem.h"
|
|
|
|
|
#include "LockedWrapper.generated.h"
|
2023-09-03 02:01:32 -04:00
|
|
|
|
2026-02-14 02:14:19 -05:00
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
2026-02-27 17:00:46 -05:00
|
|
|
// UlxEngineWrapper
|
2026-02-14 02:14:19 -05:00
|
|
|
//
|
2026-02-27 17:00:46 -05:00
|
|
|
// GameInstanceSubsystem that owns the EngineWrapper and
|
|
|
|
|
// a Mutex to lock it. To access the EngineWrapper,
|
|
|
|
|
// construct a FlxLockedWrapper.
|
2023-09-03 02:01:32 -04:00
|
|
|
//
|
2026-02-14 02:14:19 -05:00
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
2026-02-27 17:00:46 -05:00
|
|
|
UCLASS()
|
|
|
|
|
class INTEGRATION_API UlxEngineWrapper : public UGameInstanceSubsystem {
|
|
|
|
|
GENERATED_BODY()
|
|
|
|
|
|
2023-09-03 02:01:32 -04:00
|
|
|
private:
|
2026-02-27 17:00:46 -05:00
|
|
|
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);
|
|
|
|
|
|
2023-09-03 02:01:32 -04:00
|
|
|
FCriticalSection Mutex;
|
|
|
|
|
EngineWrapper Wrapper;
|
2023-09-08 01:52:30 -04:00
|
|
|
|
2026-02-27 18:40:29 -05:00
|
|
|
// The Lua Call Assembly Buffer. Used to build up a call
|
|
|
|
|
// across multiple UFUNCTION invocations. This is not protected
|
|
|
|
|
// by the mutex, so it should only be used by the game thread.
|
2023-09-08 01:52:30 -04:00
|
|
|
//
|
2026-02-27 17:00:46 -05:00
|
|
|
FlxStreamBuffer LuaCallBuffer;
|
2026-02-14 02:14:19 -05:00
|
|
|
|
2023-09-03 02:01:32 -04:00
|
|
|
public:
|
2026-02-27 17:00:46 -05:00
|
|
|
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; }
|
|
|
|
|
|
2023-09-15 13:28:18 -04:00
|
|
|
friend class FlxLockedWrapper;
|
2023-09-03 02:01:32 -04:00
|
|
|
};
|
|
|
|
|
|
2026-02-14 02:14:19 -05:00
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// FlxLockedWrapper
|
|
|
|
|
//
|
|
|
|
|
// RAII lock guard. The constructor claims the mutex,
|
|
|
|
|
// the destructor releases it. Use operator-> to
|
|
|
|
|
// access the EngineWrapper.
|
|
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-09-15 13:28:18 -04:00
|
|
|
class FlxLockedWrapper {
|
2023-09-03 02:01:32 -04:00
|
|
|
private:
|
2026-02-27 17:00:46 -05:00
|
|
|
UlxEngineWrapper& Lockable;
|
2025-03-28 23:31:44 -04:00
|
|
|
|
2023-09-07 23:50:49 -04:00
|
|
|
public:
|
2026-02-14 02:14:19 -05:00
|
|
|
// Import these types into our namespace.
|
|
|
|
|
//
|
2026-02-09 13:54:00 -05:00
|
|
|
using IdArray = LpxCommonTypes::IdArray;
|
|
|
|
|
using IdView = LpxCommonTypes::IdView;
|
|
|
|
|
using StringViewVec = LpxCommonTypes::StringViewVec;
|
2025-03-28 23:31:44 -04:00
|
|
|
|
2023-09-03 02:01:32 -04:00
|
|
|
public:
|
2026-02-14 02:14:19 -05:00
|
|
|
// The constructor claims the mutex.
|
|
|
|
|
//
|
2026-02-27 17:00:46 -05:00
|
|
|
FlxLockedWrapper() : Lockable(*UlxEngineWrapper::Instance) {
|
2023-09-03 02:01:32 -04:00
|
|
|
Lockable.Mutex.Lock();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 02:14:19 -05:00
|
|
|
// The destructor releases the mutex.
|
|
|
|
|
//
|
2023-09-15 13:28:18 -04:00
|
|
|
~FlxLockedWrapper() {
|
2023-09-03 02:01:32 -04:00
|
|
|
Lockable.Mutex.Unlock();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 02:14:19 -05:00
|
|
|
// Operator-> accesses the EngineWrapper.
|
|
|
|
|
//
|
2023-09-03 02:01:32 -04:00
|
|
|
EngineWrapper* operator ->() {
|
|
|
|
|
return &Lockable.Wrapper;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 02:14:19 -05:00
|
|
|
// Get a pointer to the EngineWrapper. Not very
|
|
|
|
|
// safe because you could keep the pointer after
|
|
|
|
|
// the LockedWrapper is destroyed. Don't do that.
|
|
|
|
|
//
|
2023-09-03 02:01:32 -04:00
|
|
|
EngineWrapper* Get() {
|
|
|
|
|
return &Lockable.Wrapper;
|
|
|
|
|
}
|
2023-09-05 03:20:11 -04:00
|
|
|
|
|
|
|
|
// Fetch Stdout as a string.
|
|
|
|
|
//
|
2026-02-25 17:07:36 -05:00
|
|
|
FString ChannelPrints();
|
2023-09-06 23:25:37 -04:00
|
|
|
|
|
|
|
|
// Get the current Actor ID.
|
|
|
|
|
//
|
|
|
|
|
int64 GetActor();
|
|
|
|
|
|
|
|
|
|
// Get the list of tangibles near the actor.
|
|
|
|
|
//
|
2026-02-14 02:14:19 -05:00
|
|
|
// This function is fast but not free. You should
|
|
|
|
|
// fetch this once per frame and then store the
|
|
|
|
|
// IdView somewhere (like in the TangibleManager).
|
2023-09-06 23:25:37 -04:00
|
|
|
//
|
2023-09-07 23:50:49 -04:00
|
|
|
IdView GetNear(int64 id, double rx, double ry, double rz);
|
2023-09-08 01:52:30 -04:00
|
|
|
|
|
|
|
|
// Get animation queues.
|
|
|
|
|
//
|
|
|
|
|
// The array returned by this is valid until the
|
|
|
|
|
// next time you call this.
|
|
|
|
|
//
|
|
|
|
|
StringViewVec GetAnimationQueues(IdView ids);
|
2026-02-14 03:35:08 -05:00
|
|
|
|
|
|
|
|
// Call a Lua function. The datapk contains the
|
|
|
|
|
// serialized class name, function name, and
|
|
|
|
|
// arguments. If place_id is 0, defaults to the
|
|
|
|
|
// current actor. The OnResult callback receives
|
|
|
|
|
// the raw return data while the lock is held;
|
|
|
|
|
// use it to copy the data before it goes away.
|
|
|
|
|
//
|
|
|
|
|
void ProbeLuaFunction(std::string_view datapk, int64 place_id, TFunction<void(std::string_view)> OnResult);
|
|
|
|
|
|
|
|
|
|
// Invoke a Lua function (fire-and-forget, no
|
|
|
|
|
// return values).
|
|
|
|
|
//
|
|
|
|
|
void InvokeLuaFunction(std::string_view datapk, int64 place_id);
|
|
|
|
|
|
|
|
|
|
// Validate a Lua expression. Returns a syntax
|
|
|
|
|
// classification and an error message. The error
|
|
|
|
|
// message is empty if the code is valid.
|
|
|
|
|
//
|
|
|
|
|
ElxLuaSyntaxCheck ValidateLuaExpr(const FString &Code, FString &ErrorMessage);
|
|
|
|
|
|
|
|
|
|
// Execute a Lua expression.
|
|
|
|
|
//
|
|
|
|
|
void InvokeLuaExpr(const FString &Code);
|
2023-09-03 02:01:32 -04:00
|
|
|
};
|