Fix bugs in animation queue handling, and add animation timeouts

This commit is contained in:
2025-07-02 16:01:18 -04:00
parent c0307b970b
commit fd453e6b30
9 changed files with 251 additions and 106 deletions

Binary file not shown.

View File

@@ -94,7 +94,7 @@
"body": { "body": {
"name": "Server=[SERVER]", "name": "Server=[SERVER]",
"request": "launch", "request": "launch",
"program": "[UNREALENGINE]/Engine/Binaries/Linux/UnrealEditor-Linux-DebugGame", "program": "[UNREALENGINE]/Engine/Binaries/Linux/UnrealEditor-Linux-[DEBUG]",
"preLaunchTask": "python3 build.py c++", "preLaunchTask": "python3 build.py c++",
"args": [ "args": [
"[INTEGRATION]/Integration.uproject", "[INTEGRATION]/Integration.uproject",
@@ -103,6 +103,7 @@
], ],
"cwd": "[INTEGRATION]", "cwd": "[INTEGRATION]",
"type": "lldb", "type": "lldb",
"console": "integratedTerminal",
"initCommands": [ "initCommands": [
"command script import [UNREALENGINE]/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py", "command script import [UNREALENGINE]/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py",
"settings set target.inline-breakpoint-strategy always", "settings set target.inline-breakpoint-strategy always",

View File

@@ -2,6 +2,7 @@
#include "AnimQueue.h" #include "AnimQueue.h"
#include "UtilityLibrary.h" #include "UtilityLibrary.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include <iostream>
FlxAnimationStep::FlxAnimationStep(uint64 hash, std::string_view body) { FlxAnimationStep::FlxAnimationStep(uint64 hash, std::string_view body) {
Finished = false; Finished = false;
@@ -140,7 +141,7 @@ void UlxAnimationStepLibrary::UnpackAnimationStep(bool &bChanged, FString &Actio
FString UlxAnimationStepLibrary::AnimationStepDebugString(const FlxAnimationStep& step) { FString UlxAnimationStepLibrary::AnimationStepDebugString(const FlxAnimationStep& step) {
std::string_view body((const char*)(step.Body.GetData()), step.Body.Num()); std::string_view body((const char*)(step.Body.GetData()), step.Body.Num());
return FlxAnimationStepDecoder::DebugString(step.Finished, step.Finished, step.Hash, body); return FlxAnimationStepDecoder::DebugString(step.Finished, step.Hash, body);
} }
static FlxAnimationField FindAnimationFieldLL(const FlxAnimationStep& step, std::string_view name) { static FlxAnimationField FindAnimationFieldLL(const FlxAnimationStep& step, std::string_view name) {
@@ -264,16 +265,15 @@ FlxAnimationField FlxAnimationStepDecoder::ReadField() {
return result; return result;
} }
FString FlxAnimationStepDecoder::DebugString(bool injectidle, bool persistentonly, uint64 hash, std::string_view body) { FString FlxAnimationStepDecoder::DebugString(bool finished, uint64 hash, std::string_view body) {
FString result; FString result;
FlxAnimationStepDecoder decoder(body); FlxAnimationStepDecoder decoder(body);
result.Appendf(TEXT("Hash=%016llx"), hash); result.Appendf(TEXT("Hash=%016llx"), hash);
if (injectidle) { if (finished) {
result.Appendf(TEXT(" action=idle")); result.Appendf(TEXT(" finished"));
} }
while (!decoder.AtEOF()) { while (!decoder.AtEOF()) {
FlxAnimationField field = decoder.ReadField(); FlxAnimationField field = decoder.ReadField();
if (persistentonly && !field.Persistent) continue;
result.Append(TEXT(" ")); result.Append(TEXT(" "));
result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data())); result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data()));
result.Append(field.Persistent ? TEXT("=") : TEXT(":")); result.Append(field.Persistent ? TEXT("=") : TEXT(":"));
@@ -317,16 +317,16 @@ FlxAnimQueueDecoder::FlxAnimQueueDecoder(std::string_view queue) : Decoder(queue
ActualSize = Decoder.read_uint8(); ActualSize = Decoder.read_uint8();
} }
FString FlxAnimQueueDecoder::DebugString(std::string_view queue) { // FString FlxAnimQueueDecoder::DebugString(std::string_view queue) {
FString result; // FString result;
FlxAnimQueueDecoder decoder(queue); // FlxAnimQueueDecoder decoder(queue);
while (!decoder.AtEOF()) { // while (!decoder.AtEOF()) {
FlxAnimationStepView step = decoder.ReadStep(); // FlxAnimationStepView step = decoder.ReadStep();
FString stepdebug = FlxAnimationStepDecoder::DebugString(false, false, step.Hash, step.Body); // FString stepdebug = FlxAnimationStepDecoder::DebugString(false, step.Hash, step.Body);
result.Appendf(TEXT("%s\n"), *stepdebug); // result.Appendf(TEXT("%s\n"), *stepdebug);
} // }
return result; // return result;
} // }
FlxAnimTracker::FlxAnimTracker() { FlxAnimTracker::FlxAnimTracker() {
Clear(); Clear();
@@ -358,6 +358,30 @@ void FlxAnimTracker::SkipToEnd() {
} }
} }
const FlxAnimationStep *FlxAnimTracker::FirstUnfinished() const
{
for (int i = 0; i < AQ.Num(); i++) {
if (!AQ[i].Finished) return &AQ[i];
}
return nullptr;
}
const FlxAnimationStep *FlxAnimTracker::LastFinished() const
{
for (int i = AQ.Num() - 1; i >= 0; i--) {
if (AQ[i].Finished) return &AQ[i];
}
return nullptr;
}
const FlxAnimationStep *FlxAnimTracker::FindAnimation(uint64 hash) const
{
for (int i = 0; i < AQ.Num(); i++) {
if (AQ[i].Hash == hash) return &AQ[i];
}
return nullptr;
}
void FlxAnimTracker::Update(std::string_view encqueue) { void FlxAnimTracker::Update(std::string_view encqueue) {
check(!encqueue.empty()); check(!encqueue.empty());
@@ -409,14 +433,14 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
int32 nremove = (AQ.Num() - (matchingindex + 1)); int32 nremove = (AQ.Num() - (matchingindex + 1));
check((nremove >= 0) && (nremove <= AQ.Num())); check((nremove >= 0) && (nremove <= AQ.Num()));
for (int32 i = 0; i < nremove; i++) { for (int32 i = 0; i < nremove; i++) {
AQ.PopLast(); AQ.Pop();
} }
// Transfer the new animations onto the queue. // Transfer the new animations onto the queue.
// //
while (!newsteps.IsEmpty()) { while (!newsteps.IsEmpty()) {
FlxAnimationStepView step = newsteps.Pop(); FlxAnimationStepView step = newsteps.Pop();
AQ.EmplaceLast(step.Hash, step.Body); AQ.Emplace(step.Hash, step.Body);
} }
// If there are too many animations in AQ, discard // If there are too many animations in AQ, discard
@@ -425,12 +449,15 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
// TODO: this is hardwired to keep 10. Instead, we // TODO: this is hardwired to keep 10. Instead, we
// should keep the number specified in the queue. // should keep the number specified in the queue.
// //
int limit = 10; const int limit = 10;
int ndiscard = AQ.Num() - limit; if (AQ.Num() > limit)
if (ndiscard > 0) { {
for (int i = 0; i < ndiscard; i++) { int offset = AQ.Num() - limit;
AQ.PopFirst(); for (int i = 0; i < limit; i++)
{
AQ[i] = AQ[i + offset];
} }
AQ.SetNum(limit);
} }
// Autofinish up to one animation. // Autofinish up to one animation.
@@ -450,6 +477,34 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
} }
} }
FString FlxAnimTracker::DebugString() const
{
FString Result;
if (Changed)
{
Result += TEXT("changed=true ");
}
else
{
Result += TEXT("changed=false ");
}
if (AutoFinish)
{
Result += TEXT("autofinish=true");
}
else
{
Result += TEXT("autofinish=false");
}
Result += TEXT("\n");
for (int i = 0; i < AQ.Num(); i++)
{
Result += UlxAnimationStepLibrary::AnimationStepDebugString(AQ[i]);
Result += TEXT("\n");
}
return Result;
}
void FlxAnimTracker::SetAutoFinish(const FString &action, const FVector &xyz) { void FlxAnimTracker::SetAutoFinish(const FString &action, const FVector &xyz) {
AutoFinish = true; AutoFinish = true;
AutoFinishAction = action; AutoFinishAction = action;
@@ -486,3 +541,4 @@ FlxAnimationStep FlxAnimTracker::GetCurrentAnimation() {
result.Hash += 1; result.Hash += 1;
return result; return result;
} }

View File

@@ -197,7 +197,7 @@ public:
// Convert an AnimQueue to an FString. // Convert an AnimQueue to an FString.
// //
static FString DebugString(std::string_view s); // static FString DebugString(std::string_view s);
}; };
//////////////////////////////////////////////// ////////////////////////////////////////////////
@@ -230,7 +230,7 @@ public:
// Convert an AnimStep to an FString. // Convert an AnimStep to an FString.
// //
static FString DebugString(bool injectidle, bool persistentonly, uint64 hash, std::string_view body); static FString DebugString(bool finished, uint64 hash, std::string_view body);
}; };
//////////////////////////////////////////////// ////////////////////////////////////////////////
@@ -251,7 +251,7 @@ public:
// store the hashes, not the steps. The First element // store the hashes, not the steps. The First element
// of the queue is the oldest item. // of the queue is the oldest item.
// //
TDeque<FlxAnimationStep> AQ; TArray<FlxAnimationStep> AQ;
// True if something has recently changed. // True if something has recently changed.
// //
@@ -319,6 +319,18 @@ public:
// //
void SkipToEnd(); void SkipToEnd();
// Return the first unfinished animation.
//
const FlxAnimationStep *FirstUnfinished() const;
// Return the last finished animation.
//
const FlxAnimationStep *LastFinished() const;
// Return the first animation with the specified hash.
//
const FlxAnimationStep *FindAnimation(uint64 hash) const;
// Clear the 'Changed' flag. // Clear the 'Changed' flag.
// //
void ClearChanged() { Changed = false; } void ClearChanged() { Changed = false; }
@@ -331,4 +343,8 @@ public:
// The changed flag can only be set to false by 'ClearChanged,' above. // The changed flag can only be set to false by 'ClearChanged,' above.
// //
bool IsChanged() const { return Changed; } bool IsChanged() const { return Changed; }
// Return a debug string for the entire animation tracker.
//
FString DebugString() const;
}; };

View File

@@ -155,6 +155,13 @@ void ALuprexGameModeBase::UpdateTangibles() {
for (int i = 0; i < alltans.Num(); i++) { for (int i = 0; i < alltans.Num(); i++) {
alltans[i]->UpdateAnimationQueue(allqueues[i]); alltans[i]->UpdateAnimationQueue(allqueues[i]);
} }
// Debugging hook.
volatile bool printaqs = false;
if (printaqs) {
for (int i = 0; i < alltans.Num(); i++) {
UE_LOG(LogLuprex, Display, TEXT("\n--- AQ of %ld ---\n%s\n"), allids[i], *(alltans[i]->AnimTracker.DebugString()));
}
}
} }
// This is where we run the blueprint code that updates animation // This is where we run the blueprint code that updates animation
// states. Be aware that the blueprint code could call back // states. Be aware that the blueprint code could call back

View File

@@ -23,7 +23,32 @@ void UlxTangible::Init(UlxTangibleManager* tm, int64 id)
TangibleId = id; TangibleId = id;
} }
#pragma optimize("", off) void UlxTangible::DeleteCurrentActor()
{
if (CurrentActor == nullptr) return;
// Remove the tangible component. This is probably
// unnecessary, but it makes it more likely that we'll
// catch bugs early.
UlxTangibleComponent* comp = CurrentActor->GetComponentByClass<UlxTangibleComponent>();
if (comp != nullptr) {
comp->DestroyComponent();
}
// Now destroy the actor itself. According to various
// documents I've read online, it may be necessary to take
// further steps to delete the object. Not clear.
CurrentActor->Destroy();
// If this actor previously was posessed by a player controller,
// then it's not posessed anymore, because there is no actor any more.
if (Manager->PossessedTangible == this) {
Manager->PossessedTangible = nullptr;
};
CurrentActor = nullptr;
}
void UlxTangible::SetActorBlueprint(const FString &XName) { void UlxTangible::SetActorBlueprint(const FString &XName) {
FString Name = XName.ToLower(); FString Name = XName.ToLower();
@@ -32,7 +57,6 @@ void UlxTangible::SetActorBlueprint(const FString &XName) {
return; return;
} }
// Get the blueprint.
UClass *blueprint = UlxAssetLookup::LoadTangibleBlueprintAsset(this, Name); UClass *blueprint = UlxAssetLookup::LoadTangibleBlueprintAsset(this, Name);
if (blueprint == nullptr) if (blueprint == nullptr)
{ {
@@ -40,71 +64,50 @@ void UlxTangible::SetActorBlueprint(const FString &XName) {
check(blueprint != nullptr); check(blueprint != nullptr);
} }
// If there's already an actor, delete it.
if (CurrentActor != nullptr) {
// Remove the tangible component. This is probably
// unnecessary, but it makes it more likely that we'll
// catch bugs early.
UlxTangibleComponent* comp = CurrentActor->GetComponentByClass<UlxTangibleComponent>();
if (comp != nullptr) {
comp->DestroyComponent();
}
// Now destroy the actor itself. According to various
// documents I've read online, it may be necessary to take
// further steps to delete the object. Not clear.
CurrentActor->Destroy();
// If this actor previously was posessed by a player controller,
// then it's not posessed anymore, because there is no actor any more.
if (Manager->PossessedTangible == this) {
Manager->PossessedTangible = nullptr;
};
}
// Update the blueprint name // Update the blueprint name
ActorBlueprintName = Name; ActorBlueprintName = Name;
// Now create a new actor, unless the BP is nullptr. // If there's already an actor, delete it.
if (blueprint != nullptr) { DeleteCurrentActor();
UWorld* w = Manager->GetWorld();
FActorSpawnParameters params;
// Give the new actor a reasonable name. // Now create a new actor.
params.Name = FName(*FString::Printf(TEXT("%s_%ld"), *Name, TangibleId)); UWorld* w = Manager->GetWorld();
FActorSpawnParameters params;
// Currently, the actor is spawned at (0,0,0), which is not good. // Give the new actor a reasonable name.
// We should spawn at the actor's current location. I'll get to it params.Name = FName(*FString::Printf(TEXT("%s_%ld"), *Name, TangibleId));
// eventually.
FTransform transform;
transform.SetLocation(FVector(0,0,0));
transform.SetRotation(FQuat(FRotator(0,0,0)));
// Create the actor at the specified location even if there's something in the way. // Currently, the actor is spawned at (0,0,0), which is not good.
params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; // We should spawn at the actor's current location. I'll get to it
// eventually.
// Normally, SpawnActor runs the BeginPlay entry point. We FTransform transform;
// want to delay that until after we've had a chance to set transform.SetLocation(FVector(0,0,0));
// up the TangibleComponent. transform.SetRotation(FQuat(FRotator(0,0,0)));
params.bDeferConstruction = true;
AActor* a = w->SpawnActor(blueprint, &transform, params);
check(a != nullptr);
// Make sure the label and the name are the same. // Create the actor at the specified location even if there's something in the way.
a->SetActorLabel(params.Name.ToString()); params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
// Normally, SpawnActor runs the BeginPlay entry point. We
// want to delay that until after we've had a chance to set
// up the TangibleComponent.
params.bDeferConstruction = true;
AActor* a = w->SpawnActor(blueprint, &transform, params);
check(a != nullptr);
// Insert a TangibleComponent into the actor. // Make sure the label and the name are the same.
// Link the actor to its tangible, and the tangible to its actor. a->SetActorLabel(params.Name.ToString());
UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false);
UlxTangibleComponent* tc = Cast<UlxTangibleComponent>(ac);
check(tc != nullptr);
tc->Tangible = this;
CurrentActor = a;
// This executes the BeginPlay entry point. We have to do this here // Insert a TangibleComponent into the actor.
// because we deferred it in SpawnActor. // Link the actor to its tangible, and the tangible to its actor.
a->FinishSpawning(transform, true); UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false);
} UlxTangibleComponent* tc = Cast<UlxTangibleComponent>(ac);
check(tc != nullptr);
tc->Tangible = this;
CurrentActor = a;
// This executes the BeginPlay entry point. We have to do this here
// because we deferred it in SpawnActor.
a->FinishSpawning(transform, true);
} }
void UlxTangible::UpdateAnimationQueue(std::string_view aq) { void UlxTangible::UpdateAnimationQueue(std::string_view aq) {
@@ -113,6 +116,9 @@ void UlxTangible::UpdateAnimationQueue(std::string_view aq) {
void UlxTangible::MaybeExecuteAnimStateChanged() { void UlxTangible::MaybeExecuteAnimStateChanged() {
int limit = 3; int limit = 3;
bool AnyChange = AnimTracker.IsChanged();
while (AnimTracker.IsChanged()) { while (AnimTracker.IsChanged()) {
if (limit == 0) break; if (limit == 0) break;
limit -= 1; limit -= 1;
@@ -122,13 +128,47 @@ void UlxTangible::MaybeExecuteAnimStateChanged() {
SetActorBlueprint(blueprint); SetActorBlueprint(blueprint);
AActor *actor = GetActor(); AActor *actor = GetActor();
UFunction *aqchanged = actor->GetClass()->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); UFunction *aqchanged = actor->GetClass()->FindFunctionByName(FName(TEXT("Animation Queue Changed")));
if (aqchanged != nullptr) { if (aqchanged != nullptr)
{
actor->ProcessEvent(aqchanged, nullptr); actor->ProcessEvent(aqchanged, nullptr);
} }
} }
// Refresh the pending animation state.
double Now = GetWorld()->GetTimeSeconds();
if (AnyChange)
{
const FlxAnimationStep *Unfinished = AnimTracker.FirstUnfinished();
if (Unfinished == nullptr)
{
PendingAnimationHash = 0;
PendingAnimationTimeout = 0.0;
}
else if (Unfinished->Hash != PendingAnimationHash)
{
PendingAnimationHash = Unfinished->Hash;
PendingAnimationTimeout = Now + 10.0;
}
}
// Implement the animation timeout.
if ((PendingAnimationHash != 0) && (Now > PendingAnimationTimeout))
{
const FlxAnimationStep *Step = AnimTracker.FindAnimation(PendingAnimationHash);
if (Step != nullptr)
{
FString DS = UlxAnimationStepLibrary::AnimationStepDebugString(*Step);
UE_LOG(LogLuprex, Warning, TEXT("Timeout - blueprint didn't finish animation: %s"), *DS);
AnimTracker.FinishedAnimation(PendingAnimationHash);
}
AutoUpdatePosition();
PendingAnimationHash = 0;
PendingAnimationTimeout = 0.0;
}
} }
FVector UlxTangible::GetLocation() const { FVector UlxTangible::GetLocation() const
{
if (CurrentActor == nullptr) { if (CurrentActor == nullptr) {
return FVector(0,0,0); return FVector(0,0,0);
} else { } else {
@@ -136,8 +176,9 @@ FVector UlxTangible::GetLocation() const {
} }
} }
void UlxTangible::Destroy() { void UlxTangible::Destroy()
SetActorBlueprint(""); {
DeleteCurrentActor();
Manager = nullptr; Manager = nullptr;
TangibleId = -1; TangibleId = -1;
CurrentActor = nullptr; CurrentActor = nullptr;
@@ -147,14 +188,16 @@ void UlxTangible::Destroy() {
NearAccordingToUnreal = false; NearAccordingToUnreal = false;
} }
UlxTangible *UlxTangible::GetActorTangibleQuiet(AActor *actor) { UlxTangible *UlxTangible::GetActorTangibleQuiet(AActor *actor)
{
if (actor == nullptr) return nullptr; if (actor == nullptr) return nullptr;
UlxTangibleComponent* comp = actor->GetComponentByClass<UlxTangibleComponent>(); UlxTangibleComponent* comp = actor->GetComponentByClass<UlxTangibleComponent>();
if (comp == nullptr) return nullptr; if (comp == nullptr) return nullptr;
return comp->Tangible.Get(); return comp->Tangible.Get();
} }
UlxTangible *UlxTangible::GetActorTangibleOrLog(AActor *actor) { UlxTangible *UlxTangible::GetActorTangibleOrLog(AActor *actor)
{
UlxTangible *tan = GetActorTangibleQuiet(actor); UlxTangible *tan = GetActorTangibleQuiet(actor);
if (tan == nullptr) { if (tan == nullptr) {
if (actor == nullptr) { if (actor == nullptr) {
@@ -175,18 +218,24 @@ void UlxTangible::GetCurrentAnimation(AActor *target, FlxAnimationStep &step) {
step = tan->AnimTracker.GetCurrentAnimation(); step = tan->AnimTracker.GetCurrentAnimation();
} }
void UlxTangible::AutoUpdatePosition()
{
const FlxAnimationStep *Step = AnimTracker.LastFinished();
if (Step != nullptr)
{
Step->AutoUpdateXYZ(GetActor());
Step->AutoUpdateFacing(GetActor());
Step->AutoUpdatePlane(&(this->Plane));
}
}
void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool AutoUpdate) { void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool AutoUpdate) {
UlxTangible *tan = GetActorTangibleOrLog(target); UlxTangible *tan = GetActorTangibleOrLog(target);
if (tan == nullptr) return; if (tan == nullptr) return;
if (AutoUpdate)
{
step.AutoUpdateXYZ(target);
step.AutoUpdateFacing(target);
step.AutoUpdatePlane(&(tan->Plane));
}
tan->AnimTracker.FinishedAnimation(step.Hash); tan->AnimTracker.FinishedAnimation(step.Hash);
if (AutoUpdate) tan->AutoUpdatePosition();
FString DebugString = UlxAnimationStepLibrary::AnimationStepDebugString(step); FString DebugString = UlxAnimationStepLibrary::AnimationStepDebugString(step);
UE_LOG(LogBlueprint, Display, TEXT("Animation Finished: %s"), *DebugString); UE_LOG(LogLuprex, Display, TEXT("Animation Finished: %s"), *DebugString);
} }
FString UlxTangible::GetTangiblePlane(AActor* target) { FString UlxTangible::GetTangiblePlane(AActor* target) {

View File

@@ -57,6 +57,12 @@ public:
// Animation tracker // Animation tracker
FlxAnimTracker AnimTracker; FlxAnimTracker AnimTracker;
// Animation that is waiting to be finished.
uint64 PendingAnimationHash;
// When do we timeout the pending animation.
double PendingAnimationTimeout;
// Current Plane. // Current Plane.
FName Plane; FName Plane;
@@ -66,6 +72,10 @@ public:
// True if unreal thinks this object is Near the player. // True if unreal thinks this object is Near the player.
bool NearAccordingToUnreal; bool NearAccordingToUnreal;
// Delete the current actor.
//
void DeleteCurrentActor();
public: public:
// Initialize a new tangible. // Initialize a new tangible.
// //
@@ -122,6 +132,9 @@ public:
static UlxTangible *GetActorTangibleQuiet(AActor *actor); static UlxTangible *GetActorTangibleQuiet(AActor *actor);
static UlxTangible *GetActorTangibleOrLog(AActor *actor); static UlxTangible *GetActorTangibleOrLog(AActor *actor);
// Automatically update the tangible's XYZ, Plane, Facing.
//
void AutoUpdatePosition();
private: private:

View File

@@ -156,6 +156,7 @@ def autodetect_system_config():
config.DOT_EXE = ".exe" config.DOT_EXE = ".exe"
config.USER = "Unknown" config.USER = "Unknown"
config.BUILD_BAT = "Build.bat" config.BUILD_BAT = "Build.bat"
config.DEBUG = "DebugGame"
else: else:
config.OS = "Linux" config.OS = "Linux"
config.DLL = "so" config.DLL = "so"
@@ -163,6 +164,7 @@ def autodetect_system_config():
config.DOT_EXE = "" config.DOT_EXE = ""
config.USER = os.environ["USER"] config.USER = os.environ["USER"]
config.BUILD_BAT = "Linux/Build.sh" config.BUILD_BAT = "Linux/Build.sh"
config.DEBUG = "DebugGame"
return config return config
@@ -170,13 +172,14 @@ def store_system_config_in_globals(config):
""" """
Copy all the config data from the config object into global variables. Copy all the config data from the config object into global variables.
""" """
global OS,DLL,BAT,DOT_EXE,USER,BUILD_BAT,INTEGRATION,UNREALENGINE global OS,DLL,BAT,DOT_EXE,USER,BUILD_BAT,DEBUG,INTEGRATION,UNREALENGINE
OS = config.OS OS = config.OS
DLL = config.DLL DLL = config.DLL
BAT = config.BAT BAT = config.BAT
DOT_EXE = config.DOT_EXE DOT_EXE = config.DOT_EXE
USER = config.USER USER = config.USER
BUILD_BAT = config.BUILD_BAT BUILD_BAT = config.BUILD_BAT
DEBUG = config.DEBUG
INTEGRATION = config.INTEGRATION INTEGRATION = config.INTEGRATION
UNREALENGINE = config.UNREALENGINE UNREALENGINE = config.UNREALENGINE
@@ -278,7 +281,7 @@ def build_luprex_and_integration():
This builds our C++ code, and also UnrealEngine's C++ code. This builds our C++ code, and also UnrealEngine's C++ code.
""" """
shell(f"{INTEGRATION}/luprex", "make all") shell(f"{INTEGRATION}/luprex", "make all")
shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} DebugGame {INTEGRATION}/Integration.uproject") shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} {DEBUG} {INTEGRATION}/Integration.uproject")
# #
@@ -291,7 +294,7 @@ def build_intellisense_database_for_clangd():
based on clangd how to compile each source file. based on clangd how to compile each source file.
This also installs a .clangd file in the UnrealEngine directory. This also installs a .clangd file in the UnrealEngine directory.
""" """
mods1 = Path(f"{INTEGRATION}/Intermediate/Build/{OS}").rglob("UnrealEditor/DebugGame/**/Module.*.o.rsp") mods1 = Path(f"{INTEGRATION}/Intermediate/Build/{OS}").rglob("UnrealEditor/{DEBUG}/**/Module.*.o.rsp")
mods2 = Path(f"{UNREALENGINE}/Engine/Intermediate/Build/{OS}").rglob("UnrealEditor/Development/**/Module.*.o.rsp") mods2 = Path(f"{UNREALENGINE}/Engine/Intermediate/Build/{OS}").rglob("UnrealEditor/Development/**/Module.*.o.rsp")
mods = list(mods1) + list(mods2) mods = list(mods1) + list(mods2)
clangs = list(Path(f"{UNREALENGINE}/Engine/Extras/ThirdPartyNotUE/SDKs").rglob("*-linux-gnu/bin/clang++")) clangs = list(Path(f"{UNREALENGINE}/Engine/Extras/ThirdPartyNotUE/SDKs").rglob("*-linux-gnu/bin/clang++"))
@@ -333,7 +336,7 @@ def build_clean():
This code is underdeveloped. This code is underdeveloped.
""" """
shell(f"{INTEGRATION}/luprex", "make clean") shell(f"{INTEGRATION}/luprex", "make clean")
shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} DebugGame {INTEGRATION}/Integration.uproject -clean") shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} {DEBUG} {INTEGRATION}/Integration.uproject -clean")
Path(f"{INTEGRATION}/.vscode/compile_commands.json").unlink(missing_ok = True) Path(f"{INTEGRATION}/.vscode/compile_commands.json").unlink(missing_ok = True)
# #

View File

@@ -179,7 +179,7 @@ public:
} }
void change_actor_id(int64_t actor_id) { void change_actor_id(int64_t actor_id) {
stdostream() << "Actor ID changing: " << actor_id << std::endl; util::dprint("Actor ID changing: ", actor_id);
print_channeler_.reset(); print_channeler_.reset();
actor_id_ = actor_id; actor_id_ = actor_id;
set_visible_world_and_actor(world_.get(), actor_id_); set_visible_world_and_actor(world_.get(), actor_id_);
@@ -257,7 +257,7 @@ public:
break; break;
} }
default: { default: {
stdostream() << "Invalid event_access: " << int(kind) << std::endl; util::dprint("Invalid event_access: ", int(kind));
} }
} }
} }
@@ -281,7 +281,7 @@ public:
// Check for communication from server.. // Check for communication from server..
if (channel_ != nullptr) { if (channel_ != nullptr) {
if (channel_->closed()) { if (channel_->closed()) {
stdostream() << "server closed connection: " << channel_->error() << std::endl; util::dprint("server closed connection: ", channel_->error());
abandon_server(); abandon_server();
} else { } else {
while (true) { while (true) {