// Copyright Epic Games, Inc. All Rights Reserved. #include "IntegrationGameModeBase.h" #include "drvutil.hpp" #include "engineutil.hpp" #include "WorkerRunnable.hpp" #include #include EngineWrapper AIntegrationGameModeBase::Luprex; //// Main loop. //while (!engw.get_stop_driver(&engw)) { // handle_lua_source(); // handle_console_output(); // handle_new_outgoing_sockets(); // handle_socket_input_output(); // handle_console_input(); // handle_console_output(); // engw.play_invoke_event_update(&engw, drvutil::get_monotonic_clock()); //} AIntegrationGameModeBase::AIntegrationGameModeBase() { Thread = nullptr; ThreadStopRequested = false; //PrimaryActorTick.bCanEverTick = true; // Probably wrong //PrimaryActorTick.bTickEvenWhenPaused = true; // Probably wrong //PrimaryActorTick.TickGroup = TG_PrePhysics; // Probably wrong SetActorTickEnabled(true); SetActorTickInterval(1.0f); } AIntegrationGameModeBase::~AIntegrationGameModeBase() { WaitForThread(); } void AIntegrationGameModeBase::HandleConsoleOutput() { uint32_t ndata; const char* data; Luprex.get_outgoing(&Luprex, 0, &ndata, &data); if (ndata == 0) return; std::string_view src(data, ndata); int consumed; std::u16string cps = drvutil::utf8_to_ucs2(src, &consumed); Luprex.play_sent_outgoing(&Luprex, 0, consumed); FString fs(cps.size(), (const UCS2CHAR*)(&cps[0])); ConsoleOutput.Append(fs); } void AIntegrationGameModeBase::LaunchThread() { if (Thread == nullptr) { ThreadStopRequested = false; Thread = FRunnableThread::Create(this, TEXT("Worker Thread")); } } // Init routine called by the worker thread. bool AIntegrationGameModeBase::Init() { engineutil::DPrint("WorkerRunnable::Init"); return true; } // Run routine called by the worker thread. uint32 AIntegrationGameModeBase::Run() { while (!ThreadStopRequested) { engineutil::DPrint("WorkerRunnable::Run"); FPlatformProcess::Sleep(1.0); } engineutil::DPrint("WorkerRunnable Done"); return 0; } void AIntegrationGameModeBase::Stop() { ThreadStopRequested = true; } #pragma optimize( "", off ) void AIntegrationGameModeBase::WaitForThread() { if (Thread == nullptr) return; Stop(); // Notifies the thread to clean up and exit. delete Thread; // This waits for the thread to complete. Thread = nullptr; } void AIntegrationGameModeBase::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); if (!luprex_initialized()) { return; } HandleConsoleOutput(); if (Luprex.engine) { EngineSeconds += DeltaSeconds; Luprex.play_invoke_event_update(&Luprex, EngineSeconds); } TArray prints = engineutil::DPrintGetStored(); for (const FString& fs : prints) { ConsoleOutput.AppendLine(fs); } if (ConsoleOutput.IsDirty()) { ConsoleSetOutput(ConsoleOutput.Get()); ConsoleOutput.ClearDirty(); } } void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs) { if (Luprex.engine) { const TCHAR* fstchar = *fs; if (sizeof(TCHAR) == 2) { ConsoleOutput.AppendLine(FString("> ") + fs); std::u16string_view fsview((const char16_t*)fstchar, fs.Len()); std::string utf8 = drvutil::utf16_to_utf8(fsview); utf8 = utf8 + "\n"; Luprex.play_recv_incoming(&Luprex, 0, utf8.size(), utf8.c_str()); } } } void AIntegrationGameModeBase::BeginPlay() { engineutil::DPrint("In BeginPlay"); Super::BeginPlay(); if (!luprex_initialized()) { engineutil::init_wrapper(&Luprex); if (!luprex_initialized()) { engineutil::DPrint("Luprex wrapper initialization failed"); return; } } Luprex.release(&Luprex); Luprex.hook_dprint(engineutil::DPrintHook); drvutil::ostringstream srcpak; std::string srcpakerr = drvutil::package_lua_source("c:\\Luprex", &srcpak); if (!srcpakerr.empty()) { engineutil::DPrint(srcpakerr.c_str()); } std::string_view srcpakv = srcpak.view(); char* argv[1]; argv[0] = const_cast("lpxserver"); Luprex.play_initialize(&Luprex, 1, argv, srcpakv.size(), srcpakv.data(), ""); if (Luprex.error[0]) { ConsoleOutput.AppendLine(FString(Luprex.error)); } else { ConsoleOutput.AppendLine(FString("Initialize Luprex Success")); } EngineSeconds = 0; LaunchThread(); } void AIntegrationGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) { engineutil::DPrint("In EndPlay"); WaitForThread(); }