diff --git a/Content/Tangibles/TangibleCharacter.uasset b/Content/Tangibles/TangibleCharacter.uasset index 73d17e43..fdfc10b6 100644 --- a/Content/Tangibles/TangibleCharacter.uasset +++ b/Content/Tangibles/TangibleCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d75f9895c1d64c10cd20b3ec83597bc1099c9042df77a220fb08768d1dd4141f -size 495852 +oid sha256:a6103472ea4290df2384bb46e667187ec0ee6413dcbb17a699c0abae2265e7b5 +size 479813 diff --git a/Source/Integration/LuaCall.cpp b/Source/Integration/LuaCall.cpp index ea1e4f62..fa0d0467 100644 --- a/Source/Integration/LuaCall.cpp +++ b/Source/Integration/LuaCall.cpp @@ -2,9 +2,14 @@ #include "LuaCall.h" #include "IntegrationGameModeBase.h" +static void FatalBlueprintError(const TCHAR *message) { + FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::FatalError, FText::FromString(FString(message))); + FBlueprintCoreDelegates::ThrowScriptException(FFrame::GetThreadLocalTopStackFrame()->Object, *FFrame::GetThreadLocalTopStackFrame(), ExceptionInfo); +} + static void CheckNotEmpty(const FlxStreamBuffer &sb) { if (sb.empty()) { - UE_LOG(LogBlueprint, Fatal, TEXT("Must use LuaCallBegin before other LuaCall steps")); + FatalBlueprintError(TEXT("Must use LuaCallBegin before other LuaCall steps")); } } @@ -61,6 +66,14 @@ void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place) { } +void UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetBuffer(); + CheckNotEmpty(sb); + mode->LuaCallEnd(InvocationKind::LUA_PROBE, place); +} + + void UlxLuaCallLibrary::InvokeEngioMove(UObject *context, const FString &action, const FVector &xyz, double facing) { AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); FlxStreamBuffer &sb = mode->LuaCallBegin(); @@ -74,3 +87,53 @@ void UlxLuaCallLibrary::InvokeEngioMove(UObject *context, const FString &action, sb.write_double(facing); mode->LuaCallEnd(InvocationKind::LUA_INVOKE); } + + +ELpxSimpleDynamicTag UlxLuaCallLibrary::LuaCallNextResultType(UObject *context) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetResult(); + if (sb.empty()) return ELpxSimpleDynamicTag::None; + int64_t total_reads = sb.total_reads(); + SimpleDynamicTag tag = sb.read_simple_dynamic_tag(); + sb.unread_to(total_reads); + switch (tag) { + case SimpleDynamicTag::STRING: return ELpxSimpleDynamicTag::String; + case SimpleDynamicTag::NUMBER: return ELpxSimpleDynamicTag::Float; + case SimpleDynamicTag::VECTOR: return ELpxSimpleDynamicTag::Vector; + case SimpleDynamicTag::BOOLEAN: return ELpxSimpleDynamicTag::Boolean; + default: return ELpxSimpleDynamicTag::None; + } +} + +FString UlxLuaCallLibrary::LuaCallGetStringResult(UObject *context) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetResult(); + SimpleDynamicTag tag = sb.read_simple_dynamic_tag(); + if (tag != SimpleDynamicTag::STRING) FatalBlueprintError(TEXT("expected lua to return a string")); + std::string_view s = sb.read_string_view(); + return FString(s.size(), (const UTF8CHAR *)s.data()); +} + +double UlxLuaCallLibrary::LuaCallGetFloatResult(UObject *context) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetResult(); + SimpleDynamicTag tag = sb.read_simple_dynamic_tag(); + if (tag != SimpleDynamicTag::NUMBER) FatalBlueprintError(TEXT("expected lua to return a float")); + return sb.read_double(); +} + +FVector UlxLuaCallLibrary::LuaCallGetVectorResult(UObject *context) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetResult(); + SimpleDynamicTag tag = sb.read_simple_dynamic_tag(); + if (tag != SimpleDynamicTag::VECTOR) FatalBlueprintError(TEXT("expected lua to return a vector")); + return sb.read_fvector(); +} + +bool UlxLuaCallLibrary::LuaCallGetBooleanResult(UObject *context) { + AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context); + FlxStreamBuffer &sb = mode->LuaCallGetResult(); + SimpleDynamicTag tag = sb.read_simple_dynamic_tag(); + if (tag != SimpleDynamicTag::BOOLEAN) FatalBlueprintError(TEXT("expected lua to return a boolean")); + return sb.read_bool(); +} diff --git a/Source/Integration/LuaCall.h b/Source/Integration/LuaCall.h index b3560ce0..01ffb1cc 100644 --- a/Source/Integration/LuaCall.h +++ b/Source/Integration/LuaCall.h @@ -3,6 +3,15 @@ #include "CoreMinimal.h" #include "LuaCall.generated.h" +UENUM(BlueprintType) +enum class ELpxSimpleDynamicTag : uint8 { + None, + String, + Float, + Boolean, + Vector +}; + //////////////////////////////////////////////// // // This UClass is never instantiated. It exists to @@ -35,7 +44,25 @@ public: UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) static void LuaCallInvoke(UObject *context, AActor *place); + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static void LuaCallProbe(UObject *context, AActor *place); + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) static void InvokeEngioMove(UObject *context, const FString &action, const FVector &xyz, double facing); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static ELpxSimpleDynamicTag LuaCallNextResultType(UObject *context); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static FString LuaCallGetStringResult(UObject *context); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static double LuaCallGetFloatResult(UObject *context); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static FVector LuaCallGetVectorResult(UObject *context); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = Luprex) + static bool LuaCallGetBooleanResult(UObject *context); }; diff --git a/Source/Integration/StringDecoder.h b/Source/Integration/StringDecoder.h index 3e2523d3..5cea30e9 100644 --- a/Source/Integration/StringDecoder.h +++ b/Source/Integration/StringDecoder.h @@ -19,7 +19,8 @@ protected: void raise_eof_on_read() { err_eof_on_read_ = true; } void raise_string_too_long() { err_string_too_long_ = true; } void raise_integer_truncated() { err_integer_truncated_ = true; } - + +public: bool get_err_eof_on_read() const { return err_eof_on_read_; } bool get_err_string_too_long() const { return err_string_too_long_; } bool get_err_integer_truncated() const { return err_integer_truncated_; }