diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index 2aec9d35..af56ec8e 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -77,6 +77,9 @@ void AIntegrationGameModeBase::ResetToInitialState() w->release(w.Get()); } + // Clear the lua call assembly buffer. + LuaCallBuffer.clear(); + // Reset the clocks. EngineSeconds = 0; NextRotateCube = 1.0; @@ -138,19 +141,26 @@ void AIntegrationGameModeBase::UpdateTangibles() { TangibleManager->DeleteFarawayTangibles(); } -void AIntegrationGameModeBase::InvokeEngioMove(const FString &action, const FVector &xyz, double facing) { - FTCHARToUTF8 utf8action(action); - std::string uaction(utf8action.Get(), utf8action.Length()); - FlxStreamBuffer sb; - sb.write_string("engio"); - sb.write_string("move"); - sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING); - sb.write_string(uaction); - sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR); - sb.write_fvector(xyz); - sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER); - sb.write_double(facing); - std::string_view datapk = sb.view(); +// void AIntegrationGameModeBase::InvokeEngioMove(const FString &action, const FVector &xyz, double facing) { +// FTCHARToUTF8 utf8action(action); +// std::string uaction(utf8action.Get(), utf8action.Length()); +// FlxStreamBuffer sb; +// sb.write_string("engio"); +// sb.write_string("move"); +// sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING); +// sb.write_string(uaction); +// sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR); +// sb.write_fvector(xyz); +// sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER); +// sb.write_double(facing); +// std::string_view datapk = sb.view(); +// FlxLockedWrapper w(LockableWrapper); +// int64 player = w.GetActor(); +// w->play_invoke_lua_call(w.Get(), player, datapk.size(), datapk.data()); +// } + +void AIntegrationGameModeBase::LuaCallInvoke(bool background) { + std::string_view datapk = LuaCallBuffer.view(); FlxLockedWrapper w(LockableWrapper); int64 player = w.GetActor(); w->play_invoke_lua_call(w.Get(), player, datapk.size(), datapk.data()); @@ -302,3 +312,48 @@ void AIntegrationGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) int64 AIntegrationGameModeBase::GetPlayerId() { return PlayerId; } + +AIntegrationGameModeBase *AIntegrationGameModeBase::GetFromWorld(UWorld *world) { + AIntegrationGameModeBase *result = world->GetAuthGameMode(); + if (result == nullptr) { + UE_LOG(LogBlueprint, Fatal, TEXT("No IntegrationGameModeBase in this context")); + } + return result; +} + +AIntegrationGameModeBase *AIntegrationGameModeBase::GetFromContext(UObject *context) { + return GetFromWorld(context->GetWorld()); +} + + // /** Gets the game mode that owns this component, this will always return null on the client */ + // template + // T* GetGameMode() const + // { + // // Note: Intentionally getting the game mode from the world instead of the game state as it can be null during game state initialization + // static_assert(TPointerIsConvertibleFromTo::Value, "'T' template parameter to GetGameMode must be derived from AGameModeBase"); + // const UWorld* World = GetWorld(); + // return World ? World->GetAuthGameMode() : nullptr; + // } + + + // // in GameplayStatics + // /** Returns the current GameModeBase or Null if it can't be retrieved, such as on the client */ + // UFUNCTION(BlueprintPure, Category="Game", meta=(WorldContext="WorldContextObject")) + // static ENGINE_API class AGameModeBase* GetGameMode(const UObject* WorldContextObject); + + // // Give the URL a chance to override it + // if (AGameModeBase* GameModeBase = GetGameMode()) + // { + // EffectiveBotCount = UGameplayStatics::GetIntOption(GameModeBase->OptionsString, TEXT("NumBots"), EffectiveBotCount); + // } + + // // In UWorld + // /** + // * Returns the current Game Mode instance cast to the template type. + // * This can only return a valid pointer on the server and may be null if the cast fails. Will always return null on a client. + // */ + // template< class T > + // T* GetAuthGameMode() const + // { + // return Cast(AuthorityGameMode); + // } diff --git a/Source/Integration/IntegrationGameModeBase.h b/Source/Integration/IntegrationGameModeBase.h index ef6c938b..2f053026 100644 --- a/Source/Integration/IntegrationGameModeBase.h +++ b/Source/Integration/IntegrationGameModeBase.h @@ -6,6 +6,7 @@ #include "GameFramework/GameModeBase.h" #include "lpx-enginewrapper.hpp" #include "DebugPrint.h" +#include "StringDecoder.h" #include "TangibleManager.h" #include "LuprexSockets.h" #include "TriggeredTask.h" @@ -42,8 +43,17 @@ public: UFUNCTION(BlueprintCallable, Category = "Luprex") int64 GetPlayerId(); - UFUNCTION(BlueprintCallable, Category = "Luprex") - void InvokeEngioMove(const FString &action, const FVector &xyz, double facing); + // Assemble a lua call. To call into lua: + // + // * Use LuaCallBegin + // * Get the lua call buffer. + // * Add a class name and a function name to the buffer. + // * Add parameters to the buffer. + // * Use LuaCallInvoke. + // + void LuaCallBegin() { LuaCallBuffer.clear(); } + FlxStreamBuffer &LuaCallGetBuffer() { return LuaCallBuffer; } + void LuaCallInvoke(bool background); // Execute a debugging command, typed on the GUI. void ExecuteDebuggingCommand(FlxLockedWrapper &w, const FString &fs); @@ -62,6 +72,11 @@ public: // to update luprex sockets and update luprex itself. virtual uint32 Run() override; + // Get the AIntegrationGameModeBase given any UObject + // If there is no AIntegrationGameModeBase in that world context, fatal error + static AIntegrationGameModeBase *GetFromWorld(UWorld *world); + static AIntegrationGameModeBase *GetFromContext(UObject *context); + UPROPERTY() UlxTangibleManager *TangibleManager; @@ -72,6 +87,9 @@ public: // To access it, construct a FlxLockedWrapper. FlxLockableWrapper LockableWrapper; + // The Lua Call assembly buffer. + FlxStreamBuffer LuaCallBuffer; + // This utility runs the luprex update and socket update in a thread. FTriggeredTask LuprexUpdateTask; diff --git a/Source/Integration/LuaCall.cpp b/Source/Integration/LuaCall.cpp new file mode 100644 index 00000000..799f0f17 --- /dev/null +++ b/Source/Integration/LuaCall.cpp @@ -0,0 +1,46 @@ + +#include "LuaCall.h" +#include "IntegrationGameModeBase.h" + +void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname) { + +} + +void UlxLuaCallLibrary::LuaCallAddStringParameter(UObject *context, const FString &pstring) { + +} + + +void UlxLuaCallLibrary::LuaCallAddFloatParameter(UObject *context, double pfloat) { + +} + + +void UlxLuaCallLibrary::LuaCallAddVectorParameter(UObject *context, const FVector &pvector) { + +} + + +void UlxLuaCallLibrary::LuaCallAddBooleanParameter(UObject *context, bool pbool) { + +} + + +void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, bool background) { + +} + +void UlxLuaCallLibrary::InvokeEngioMove(UObject *context, const FString &action, const FVector &xyz, double facing) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetBuffer(); + mode->LuaCallBegin(); + sb.write_string("engio"); + sb.write_string("move"); + sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING); + sb.write_string(action); + sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR); + sb.write_fvector(xyz); + sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER); + sb.write_double(facing); + mode->LuaCallInvoke(true); +} diff --git a/Source/Integration/LuaCall.h b/Source/Integration/LuaCall.h new file mode 100644 index 00000000..0b94d9f1 --- /dev/null +++ b/Source/Integration/LuaCall.h @@ -0,0 +1,41 @@ +#pragma once + +#include "CoreMinimal.h" +#include "LuaCall.generated.h" + +//////////////////////////////////////////////// +// +// This UClass is never instantiated. It exists to +// expose certain static functions to the blueprint +// library. +// +//////////////////////////////////////////////// + +UCLASS() +class INTEGRATION_API UlxLuaCallLibrary : public UObject +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallBegin(UObject *context, const FString &cname, const FString &fname); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallAddStringParameter(UObject *context, const FString &pstring); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallAddFloatParameter(UObject *context, double pfloat); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallAddVectorParameter(UObject *context, const FVector &pvector); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallAddBooleanParameter(UObject *context, bool pbool); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallInvoke(UObject *context, bool background); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void InvokeEngioMove(UObject *context, const FString &action, const FVector &xyz, double facing); +}; + diff --git a/Source/Integration/StringDecoder.h b/Source/Integration/StringDecoder.h index 6ddec598..3e2523d3 100644 --- a/Source/Integration/StringDecoder.h +++ b/Source/Integration/StringDecoder.h @@ -29,6 +29,16 @@ protected: class FlxStreamBuffer : public BaseBuffer { public: using BaseBuffer::BaseBuffer; + using BaseBuffer::write_string; + + void write_string(const FString &str) { + FTCHARToUTF8 utf8str(str); + write_string(std::string_view(utf8str.Get(), utf8str.Length())); + } + + void write_string(const char *s) { + write_string(std::string_view(s)); + } void write_fvector(const FVector &xyz) { write_double(xyz.X);