Add Unreal Blackholio (#3260)

# Description of Changes

Closes: https://github.com/clockworklabs/SpacetimeDBPrivate/issues/1925

This adds Unreal Blackholio to the demo/Blackholio folder matching the
Unity version using server-rust as the default. Includes:
- Leaderboard
- Circle Material - wavy border
- Split/Sucide/Input Lock
- Parallax Background
- Camera movement based on total mass

# API and ABI breaking changes

No changes

# Expected complexity level and risk

1 - Only adds the demo has no impact elsewise

# Testing

I've tested this backwards and forwards against the server-rust version
and played alongside the Unity client.

- [ ] Run it locally for review

---------

Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
This commit is contained in:
Jason Larabie
2025-09-22 13:16:33 -07:00
committed by GitHub
parent 34d8cd4dd4
commit 20ef7cfbaa
113 changed files with 7086 additions and 0 deletions
+31
View File
@@ -36,3 +36,34 @@ Temporary Items
*.icloud
# End of https://www.toptal.com/developers/gitignore/api/macos
# Unreal plugin build artifacts
Binaries/
Intermediate/
DerivedDataCache/
Saved/
.vs/
.idea/
*.VC.db
*.VC.opendb
*.sln
*.opensdf
*.sdf
*.suo
*.user
*.userprefs
*.log
*.tlog
*.ipch
*.obj
*.pch
*.pdb
*.idb
*.aps
*.ncb
*.cache
*.sbr
*.db
*.xcodeproj
xcuserdata/
/sdks/unreal/tests/TestClient/TestResults
@@ -0,0 +1,95 @@
[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/Blackholio.Blackholio
EditorStartupMap=/Game/Blackholio.Blackholio
[/Script/Engine.RendererSettings]
r.AllowStaticLighting=False
r.GenerateMeshDistanceFields=True
r.DynamicGlobalIlluminationMethod=1
r.ReflectionMethod=1
r.SkinCache.CompileShaders=True
r.RayTracing=True
r.RayTracing.RayTracingProxies.ProjectEnabled=True
r.Shadow.Virtual.Enable=1
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8
r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
-D3D12TargetedShaderFormats=PCD3D_SM5
+D3D12TargetedShaderFormats=PCD3D_SM6
-D3D11TargetedShaderFormats=PCD3D_SM5
+D3D11TargetedShaderFormats=PCD3D_SM5
Compiler=Default
AudioSampleRate=48000
AudioCallbackBufferFrameSize=1024
AudioNumBuffersToEnqueue=1
AudioMaxChannels=0
AudioNumSourceWorkers=4
SpatializationPlugin=
SourceDataOverridePlugin=
ReverbPlugin=
OcclusionPlugin=
CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0)
CacheSizeKB=65536
MaxChunkSizeOverrideKB=0
bResampleForDevice=False
MaxSampleRate=48000.000000
HighSampleRate=32000.000000
MedSampleRate=24000.000000
LowSampleRate=12000.000000
MinSampleRate=8000.000000
CompressionQualityModifier=1.000000
AutoStreamingThreshold=0.000000
SoundCueCookQualityIndex=-1
[/Script/LinuxTargetPlatform.LinuxTargetSettings]
-TargetedRHIs=SF_VULKAN_SM5
+TargetedRHIs=SF_VULKAN_SM6
[/Script/HardwareTargeting.HardwareTargetingSettings]
TargetedHardwareClass=Desktop
AppliedTargetedHardwareClass=Desktop
DefaultGraphicsPerformance=Maximum
AppliedDefaultGraphicsPerformance=Maximum
[/Script/WorldPartitionEditor.WorldPartitionEditorSettings]
CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet'
[/Script/Engine.UserInterfaceSettings]
bAuthorizeAutomaticWidgetVariableCreation=False
FontDPIPreset=Standard
FontDPI=72
[/Script/Engine.Engine]
+ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/client_unreal")
+ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/client_unreal")
[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings]
bEnablePlugin=True
bAllowNetworkConnection=True
SecurityToken=44F0FBC34B5D09A59F02A0AA6395FF14
bIncludeInShipping=False
bAllowExternalStartInShipping=False
bCompileAFSProject=False
bUseCompression=False
bLogFiles=False
bReportStats=False
ConnectionType=USBOnly
bUseManualIPAddress=False
ManualIPAddress=
@@ -0,0 +1,6 @@
[/Script/CommonUI.CommonUISettings]
CommonButtonAcceptKeyHandling=TriggerClick
[/Script/EngineSettings.GeneralProjectSettings]
ProjectID=1CB09ED64584D03E3ED8AA86458B2D83
@@ -0,0 +1,84 @@
[/Script/Engine.InputSettings]
-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
-AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
+AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
bAltEnterTogglesFullscreen=True
bF11TogglesFullscreen=True
bUseMouseForTouch=False
bEnableMouseSmoothing=True
bEnableFOVScaling=True
bCaptureMouseOnLaunch=True
bEnableLegacyInputScales=True
bEnableMotionControls=True
bFilterInputByPlatformUser=False
bShouldFlushPressedKeysOnViewportFocusLost=True
bAlwaysShowTouchInterface=False
bShowConsoleOnFourFingerTap=True
bEnableGestureRecognizer=False
bUseAutocorrect=False
DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown
DefaultViewportMouseLockMode=LockOnCapture
FOVScale=0.011110
DoubleClickTime=0.200000
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks
-ConsoleKeys=Tilde
+ConsoleKeys=Tilde
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,15 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
using System.Collections.Generic;
public class client_unrealTarget : TargetRules
{
public client_unrealTarget(TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V5;
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_6;
ExtraModuleNames.Add("client_unreal");
}
}
@@ -0,0 +1,2 @@
#include "BlackholioGameMode.h"
@@ -0,0 +1,196 @@
#include "BlackholioPlayerController.h"
#include "DbVector2.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameManager.h"
#include "PlayerPawn.h"
#include "Blueprint/UserWidget.h"
#include "Gameplay/LeaderboardWidget.h"
#include "Gameplay/RespawnWidget.h"
#include "Gameplay/UsernameChooserWidget.h"
ABlackholioPlayerController::ABlackholioPlayerController()
{
bShowMouseCursor = true;
bEnableClickEvents = true;
bEnableMouseOverEvents = true;
PrimaryActorTick.bCanEverTick = true;
}
void ABlackholioPlayerController::ShowDeathScreen()
{
if (!IsLocalController() || !RespawnClass) return;
if (!RespawnWidget)
{
RespawnWidget = CreateWidget<URespawnWidget>(this, RespawnClass);
RespawnWidget->AddToViewport(100);
}
else if (!RespawnWidget->IsInViewport())
{
RespawnWidget->AddToViewport(100);
}
RespawnWidget->SetVisibility(ESlateVisibility::Visible);
FInputModeUIOnly InputMode;
InputMode.SetWidgetToFocus(RespawnWidget->TakeWidget());
InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
SetInputMode(InputMode);
bShowMouseCursor = true;
//RespawnWidget->SetKeyboardFocus();
}
void ABlackholioPlayerController::BeginPlay()
{
Super::BeginPlay();
if (!LeaderboardWidget && LeaderboardClass)
{
LeaderboardWidget = CreateWidget<ULeaderboardWidget>(this, LeaderboardClass);
LeaderboardWidget->AddToViewport(100);
LeaderboardWidget->SetVisibility(ESlateVisibility::Visible);
}
SetInputMode(FInputModeGameOnly());
}
void ABlackholioPlayerController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (!AGameManager::Instance || !AGameManager::Instance->IsConnected())
{
return;
}
const float Now = GetWorld() ? GetWorld()->GetTimeSeconds() : 0.f;
if ((Now - LastMovementSendTimestamp) >= SendUpdatesFrequency)
{
LastMovementSendTimestamp = Now;
FVector2D LatestDesiredDirection = ComputeDesiredDirection();
if ((LatestDesiredDirection.X != 0 && LatestDesiredDirection.Y != 0))
{
const FVector2D ConvertDirection = FVector2D(LatestDesiredDirection.X, LatestDesiredDirection.Y*-1);
AGameManager::Instance->Conn->Reducers->UpdatePlayerInput(ToDbVector(ConvertDirection));
}
}
if (!AGameManager::Instance->bSubscriptionsApplied) return;
if (AGameManager::Instance->PlayerNameAtStart.IsEmpty() && !bShowedUsernameChooser)
{
bShowedUsernameChooser = true;
if (IsLocalController() && UsernameChooserClass)
{
this->UsernameChooserWidget = CreateWidget<UUsernameChooserWidget>(this, UsernameChooserClass);
if (this->UsernameChooserWidget)
{
this->UsernameChooserWidget->AddToViewport(100);
SetInputMode(FInputModeUIOnly()); // should focus the textbox
bShowMouseCursor = true;
}
}
//this->UsernameChooserWidget->Hide();
}
}
void ABlackholioPlayerController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
LocalPlayer = Cast<APlayerPawn>(InPawn);
EnsureMappingContext();
}
void ABlackholioPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
if (UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent))
{
if (SplitAction)
{
EIC->BindAction(SplitAction, ETriggerEvent::Triggered, this, &ABlackholioPlayerController::OnSplitTriggered);
}
if (SuicideAction)
{
EIC->BindAction(SuicideAction, ETriggerEvent::Triggered, this, &ABlackholioPlayerController::OnSuicideTriggered);
}
if (ToggleInputLockAction)
{
EIC->BindAction(ToggleInputLockAction, ETriggerEvent::Triggered, this, &ABlackholioPlayerController::OnToggleInputLockTriggered);
}
}
}
FVector2D ABlackholioPlayerController::ComputeDesiredDirection() const
{
int32 SizeX = 0, SizeY = 0;
GetViewportSize(SizeX, SizeY);
if (SizeX <= 0 || SizeY <= 0)
{
return FVector2D::ZeroVector;
}
const FVector2D ViewportCenter(static_cast<float>(SizeX) * 0.5f, static_cast<float>(SizeY) * 0.5f);
FVector2D MousePos = ViewportCenter;
if (!LockInputPosition.IsSet())
{
float MouseX = 0.f, MouseY = 0.f;
if (!GetMousePosition(MouseX, MouseY))
{
return FVector2D::ZeroVector;
}
MousePos = FVector2D(MouseX, MouseY);
}
else
{
MousePos = LockInputPosition.GetValue();
}
if (MousePos.X < 0.f || MousePos.X >= SizeX || MousePos.Y < 0.f || MousePos.Y >= SizeY)
{
return FVector2D::ZeroVector;
}
const float Denominator = FMath::Max(1.f, static_cast<float>(SizeY) / 3.f);
const FVector2D DesiredDir = (MousePos - ViewportCenter) / Denominator;
return DesiredDir;
}
void ABlackholioPlayerController::EnsureMappingContext() const
{
if (!PlayerMappingContext) return;
if (ULocalPlayer* LP = GetLocalPlayer())
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LP))
{
Subsystem->AddMappingContext(PlayerMappingContext, 0);
}
}
}
void ABlackholioPlayerController::OnSplitTriggered(const FInputActionValue& Value)
{
LocalPlayer->Split();
}
void ABlackholioPlayerController::OnSuicideTriggered(const FInputActionValue& Value)
{
LocalPlayer->Suicide();
}
void ABlackholioPlayerController::OnToggleInputLockTriggered(const FInputActionValue& Value)
{
if (LockInputPosition.IsSet())
{
LockInputPosition.Reset();
}
else
{
float X, Y;
if (GetMousePosition(X, Y))
{
LockInputPosition = FVector2D(X, Y);
}
}
}
@@ -0,0 +1,53 @@
#include "Circle.h"
#include "PlayerPawn.h"
#include "ModuleBindings/Types/CircleType.g.h"
ACircle::ACircle()
{
ColorPalette = {
// Yellow
FLinearColor::FromSRGBColor(FColor(175, 159, 49, 255)),
FLinearColor::FromSRGBColor(FColor(175, 116, 49, 255)),
// Purple
FLinearColor::FromSRGBColor(FColor(112, 47, 252, 255)),
FLinearColor::FromSRGBColor(FColor(51, 91, 252, 255)),
// Red
FLinearColor::FromSRGBColor(FColor(176, 54, 54, 255)),
FLinearColor::FromSRGBColor(FColor(176, 109, 54, 255)),
FLinearColor::FromSRGBColor(FColor(141, 43, 99, 255)),
// Blue
FLinearColor::FromSRGBColor(FColor(2, 188, 250, 255)),
FLinearColor::FromSRGBColor(FColor(7, 50, 251, 255)),
FLinearColor::FromSRGBColor(FColor(2, 28, 146, 255)),
};
}
void ACircle::Spawn(const FCircleType& Circle, APlayerPawn* InOwner)
{
Super::Spawn(Circle.EntityId);
const int32 Index = ColorPalette.Num() ? static_cast<int32>(InOwner->PlayerId % ColorPalette.Num()) : 0;
const FLinearColor Color = ColorPalette.IsValidIndex(Index) ? ColorPalette[Index] : FLinearColor::Green;
SetColor(Color);
this->Owner = InOwner;
SetUsername(InOwner->GetUsername());
}
void ACircle::OnDelete(const FEventContext& Context)
{
Super::OnDelete(Context);
Owner->OnCircleDeleted(this);
}
void ACircle::SetUsername(const FString& InUsername)
{
if (Username.Equals(InUsername, ESearchCase::CaseSensitive))
return;
Username = InUsername;
OnUsernameChanged.Broadcast(Username);
}
@@ -0,0 +1,110 @@
#include "Entity.h"
#include "DbVector2.h"
#include "GameManager.h"
#include "PaperSpriteComponent.h"
#include "ModuleBindings/Tables/EntityTable.g.h"
AEntity::AEntity()
{
PrimaryActorTick.bCanEverTick = true;
LerpTime = 0.f;
}
void AEntity::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bIsDespawning)
{
ConsumeDespawn(DeltaTime);
return;
}
// Interpolate the position and scale
LerpTime = FMath::Min(LerpTime + DeltaTime, LerpDuration);
const float Alpha = (LerpDuration > 0.f) ? (LerpTime / LerpDuration) : 1.f;
SetActorLocation(FMath::Lerp(LerpStartPosition, LerpTargetPosition, Alpha));
const float NewScale = FMath::FInterpTo(GetActorScale3D().X, TargetScale, DeltaTime, 8.f);
SetActorScale3D(FVector(NewScale));
}
void AEntity::ConsumeDespawn(float DeltaTime)
{
if (!bIsDespawning || !ConsumingEntity)
return;
DespawnElapsed = FMath::Min(DespawnElapsed + DeltaTime, DespawnTime);
const float T = (DespawnTime > 0.f) ? (DespawnElapsed / DespawnTime) : 1.f;
const FVector CurrentTargetPos = ConsumingEntity->GetActorLocation();
SetActorLocation(FMath::Lerp(ConsumeStartPosition, CurrentTargetPos, T));
SetActorScale3D(FMath::Lerp(ConsumeStartScale, FVector::ZeroVector, T));
if (DespawnElapsed >= DespawnTime)
{
bIsDespawning = false;
ConsumingEntity = nullptr;
Destroy();
}
}
void AEntity::Spawn(uint32 InEntityId)
{
EntityId = InEntityId;
const FEntityType EntityRow = AGameManager::Instance->Conn->Db->Entity->EntityId->Find(InEntityId);
LerpStartPosition = LerpTargetPosition = ToFVector(EntityRow.Position);
SetActorLocation(LerpStartPosition);
TargetScale = MassToDiameter(EntityRow.Mass);
SetActorScale3D(FVector::OneVector);
LerpTime = 0.f;
}
void AEntity::OnEntityUpdated(const FEntityType& NewVal)
{
LerpStartPosition = GetActorLocation();
LerpTargetPosition = ToFVector(NewVal.Position);
TargetScale = MassToDiameter(NewVal.Mass);
LerpTime = 0.f;
}
void AEntity::OnDelete(const FEventContext& Context)
{
if (ConsumeDelete(Context))
return;
Destroy();
}
bool AEntity::ConsumeDelete(const FEventContext& Context)
{
if (!Context.Event.IsReducer())
return false;
const FReducer Reducer = Context.Event.GetAsReducer();
if (!Reducer.IsConsumeEntity())
return false;
const FConsumeEntityArgs Args = Reducer.GetAsConsumeEntity();
const uint32 ConsumerId = Args.Request.ConsumerEntityId;
ConsumingEntity = AGameManager::Instance->GetEntity(ConsumerId);
if (!ConsumingEntity)
return false;
bIsDespawning = true;
DespawnElapsed = 0.f;
ConsumeStartPosition = GetActorLocation();
ConsumeStartScale = GetActorScale3D();
return true;
}
void AEntity::SetColor(const FLinearColor& Color) const
{
if (UPaperSpriteComponent* SpriteComponent = FindComponentByClass<UPaperSpriteComponent>())
{
SpriteComponent->SetSpriteColor(Color);
}
}
@@ -0,0 +1,26 @@
#include "Food.h"
#include "ModuleBindings/Types/FoodType.g.h"
AFood::AFood()
{
ColorPalette = {
// Greenish
FLinearColor::FromSRGBColor(FColor(119, 252, 173, 255)),
FLinearColor::FromSRGBColor(FColor(76, 250, 146, 255)),
FLinearColor::FromSRGBColor(FColor(35, 246, 120, 255)),
// Aqua / Teal
FLinearColor::FromSRGBColor(FColor(119, 251, 201, 255)),
FLinearColor::FromSRGBColor(FColor(76, 249, 184, 255)),
FLinearColor::FromSRGBColor(FColor(35, 245, 165, 255)),
};
}
void AFood::Spawn(const FFoodType& FoodEntity)
{
Super::Spawn(FoodEntity.EntityId);
const int32 Index = ColorPalette.Num() ? static_cast<int32>(EntityId % ColorPalette.Num()) : 0;
const FLinearColor Color = ColorPalette.IsValidIndex(Index) ? ColorPalette[Index] : FLinearColor::Green;
SetColor(Color);
}
@@ -0,0 +1,341 @@
#include "GameManager.h"
#include "Circle.h"
#include "Entity.h"
#include "Food.h"
#include "PlayerPawn.h"
#include "Components/InstancedStaticMeshComponent.h"
#include "Connection/Credentials.h"
#include "ModuleBindings/Tables/CircleTable.g.h"
#include "ModuleBindings/Tables/ConfigTable.g.h"
#include "ModuleBindings/Tables/EntityTable.g.h"
#include "ModuleBindings/Tables/FoodTable.g.h"
#include "ModuleBindings/Tables/PlayerTable.g.h"
AGameManager* AGameManager::Instance = nullptr;
AGameManager::AGameManager()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
BorderISM = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("BorderISM"));
SetRootComponent(BorderISM);
if (CubeMesh != nullptr)
return;
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeAsset(TEXT("/Engine/BasicShapes/Cube.Cube"));
if (CubeAsset.Succeeded())
{
CubeMesh = CubeAsset.Object;
}
}
AEntity* AGameManager::GetEntity(uint32 EntityId) const
{
if (const TWeakObjectPtr<AEntity>* WeakEntity = EntityMap.Find(EntityId))
{
if (!WeakEntity->IsValid())
{
return nullptr;
}
if (AEntity* Entity = WeakEntity->Get())
{
return Entity;
}
}
return nullptr;
}
void AGameManager::BeginPlay()
{
Super::BeginPlay();
Instance = this;
FOnConnectDelegate ConnectDelegate;
BIND_DELEGATE_SAFE(ConnectDelegate, this, AGameManager, HandleConnect);
FOnDisconnectDelegate DisconnectDelegate;
BIND_DELEGATE_SAFE(DisconnectDelegate, this, AGameManager, HandleDisconnect);
FOnConnectErrorDelegate ConnectErrorDelegate;
BIND_DELEGATE_SAFE(ConnectErrorDelegate, this, AGameManager, HandleConnect);
UCredentials::Init(FString::Printf(TEXT("%s-%s"), *TokenFilePath, *ServerUri));
FString Token = UCredentials::LoadToken();
UDbConnectionBuilder* Builder = UDbConnection::Builder()
->WithUri(ServerUri)
->WithModuleName(ModuleName)
->OnConnect(ConnectDelegate)
->OnDisconnect(DisconnectDelegate)
->OnConnectError(ConnectErrorDelegate);
if (!Token.IsEmpty())
{
Builder->WithToken(Token);
}
Conn = Builder->Build();
}
void AGameManager::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Disconnect();
if (Instance == this)
{
Instance = nullptr;
}
Super::EndPlay(EndPlayReason);
}
void AGameManager::Tick(float DeltaTime)
{
if (IsConnected())
{
Conn->FrameTick();
}
}
void AGameManager::HandleConnect(UDbConnection* InConn, FSpacetimeDBIdentity Identity, const FString& Token)
{
UE_LOG(LogTemp, Log, TEXT("Connected."));
UCredentials::SaveToken(Token);
LocalIdentity = Identity;
Conn->Db->Circle->OnInsert.AddDynamic(this, &AGameManager::OnCircleInsert);
Conn->Db->Entity->OnUpdate.AddDynamic(this, &AGameManager::OnEntityUpdate);
Conn->Db->Entity->OnDelete.AddDynamic(this, &AGameManager::OnEntityDelete);
Conn->Db->Food->OnInsert.AddDynamic(this, &AGameManager::OnFoodInsert);
Conn->Db->Player->OnInsert.AddDynamic(this, &AGameManager::OnPlayerInsert);
Conn->Db->Player->OnDelete.AddDynamic(this, &AGameManager::OnPlayerDelete);
FOnSubscriptionApplied AppliedDelegate;
BIND_DELEGATE_SAFE(AppliedDelegate, this, AGameManager, HandleSubscriptionApplied);
Conn->SubscriptionBuilder()
->OnApplied(AppliedDelegate)
->SubscribeToAllTables();
}
void AGameManager::HandleConnectError(const FString& Error)
{
UE_LOG(LogTemp, Log, TEXT("Connection error %s"), *Error);
}
void AGameManager::HandleDisconnect(UDbConnection* InConn, const FString& Error)
{
UE_LOG(LogTemp, Log, TEXT("Disconnected."));
if (!Error.IsEmpty())
{
UE_LOG(LogTemp, Log, TEXT("Disconnect error %s"), *Error);
}
}
void AGameManager::HandleSubscriptionApplied(FSubscriptionEventContext& Context)
{
UE_LOG(LogTemp, Log, TEXT("Subscription applied!"));
this->bSubscriptionsApplied = true;
// Once we have the initial subscription sync'd to the client cache
// Get the world size from the config table and set up the arena
uint64 WorldSize = Conn->Db->Config->Id->Find(0).WorldSize;
SetupArena(WorldSize);
FPlayerType Player = Context.Db->Player->Identity->Find(LocalIdentity);
if (!Player.Name.IsEmpty())
{
this->PlayerNameAtStart = Player.Name;
if (Context.Db->Circle->PlayerId->Filter(Player.PlayerId).Num() == 0)
{
Context.Reducers->EnterGame(Player.Name);
}
}
}
void AGameManager::SetupArena(uint64 WorldSizeMeters)
{
if (!BorderISM || !CubeMesh) return;
BorderISM->ClearInstances();
BorderISM->SetStaticMesh(CubeMesh);
if (BorderMaterial)
{
BorderISM->SetMaterial(0, BorderMaterial);
}
// Convert from meters (uint64) → centimeters (double for precision)
const double worldSizeCmDouble = static_cast<double>(WorldSizeMeters) * 100.0;
// Clamp to avoid float overflow in transforms
const double clampedWorldSizeCmDouble = FMath::Clamp(
worldSizeCmDouble,
0.0,
FLT_MAX * 0.25 // safe margin
);
// Convert to float for actual Unreal math
const float worldSizeCm = static_cast<float>(clampedWorldSizeCmDouble);
const float borderThicknessCm = BorderThickness; // already cm
// Create four borders
CreateBorderCube(
FVector2f(worldSizeCm * 0.5f, worldSizeCm + borderThicknessCm * 0.5f), // North
FVector2f(worldSizeCm + borderThicknessCm * 2.0f, borderThicknessCm)
);
CreateBorderCube(
FVector2f(worldSizeCm * 0.5f, -borderThicknessCm * 0.5f), // South
FVector2f(worldSizeCm + borderThicknessCm * 2.0f, borderThicknessCm)
);
CreateBorderCube(
FVector2f(worldSizeCm + borderThicknessCm * 0.5f, worldSizeCm * 0.5f), // East
FVector2f(borderThicknessCm, worldSizeCm + borderThicknessCm * 2.0f)
);
CreateBorderCube(
FVector2f(-borderThicknessCm * 0.5f, worldSizeCm * 0.5f), // West
FVector2f(borderThicknessCm, worldSizeCm + borderThicknessCm * 2.0f)
);
}
void AGameManager::CreateBorderCube(const FVector2f Position, const FVector2f Size) const
{
// Scale from the 100cm default cube to desired size (in cm)
const FVector Scale(Size.X / 100.0f, BorderHeight / 100.0f, Size.Y / 100.0f);
// Place so the bottom sits on Z=0 (cube is centered)
const FVector Location(Position.X, BorderHeight * 0.5f, Position.Y);
const FTransform Transform(FRotator::ZeroRotator, Location, Scale);
BorderISM->AddInstance(Transform);
}
void AGameManager::OnCircleInsert(const FEventContext& Context, const FCircleType& NewRow)
{
if (EntityMap.Contains(NewRow.EntityId)) return;
SpawnCircle(NewRow);
}
void AGameManager::OnEntityUpdate(const FEventContext& Context, const FEntityType& OldRow, const FEntityType& NewRow)
{
if (TWeakObjectPtr<AEntity>* WeakEntity = EntityMap.Find(NewRow.EntityId))
{
if (!WeakEntity->IsValid())
{
return;
}
if (AEntity* Entity = WeakEntity->Get())
{
Entity->OnEntityUpdated(NewRow);
}
}
}
void AGameManager::OnEntityDelete(const FEventContext& Context, const FEntityType& RemovedRow)
{
TWeakObjectPtr<AEntity> EntityPtr;
const bool bHadEntry = EntityMap.RemoveAndCopyValue(RemovedRow.EntityId, EntityPtr);
const bool bIsValid =EntityPtr.IsValid();
if (!bHadEntry || !bIsValid)
{
return;
}
if (AEntity* Entity = EntityPtr.Get())
{
Entity->OnDelete(Context);
}
}
void AGameManager::OnFoodInsert(const FEventContext& Context, const FFoodType& NewRow)
{
if (EntityMap.Contains(NewRow.EntityId)) return;
SpawnFood(NewRow);
}
void AGameManager::OnPlayerInsert(const FEventContext& Context, const FPlayerType& NewRow)
{
SpawnOrGetPlayer(NewRow);
}
void AGameManager::OnPlayerDelete(const FEventContext& Context, const FPlayerType& RemovedRow)
{
TWeakObjectPtr<APlayerPawn> PlayerPtr;
const bool bHadEntry = PlayerMap.RemoveAndCopyValue(RemovedRow.PlayerId, PlayerPtr);
if (!bHadEntry || !PlayerPtr.IsValid())
{
return;
}
if (APlayerPawn* Player = PlayerPtr.Get())
{
Player->Destroy();
}
}
APlayerPawn* AGameManager::SpawnOrGetPlayer(const FPlayerType& PlayerRow)
{
TWeakObjectPtr<APlayerPawn> WeakPlayer = PlayerMap.FindRef(PlayerRow.PlayerId);
if (WeakPlayer.IsValid())
{
return WeakPlayer.Get();
}
if (!PlayerClass)
{
UE_LOG(LogTemp, Error, TEXT("GameManager - PlayerClass not set."));
return nullptr;
}
FActorSpawnParameters Params;
Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
APlayerPawn* Player = GetWorld()->SpawnActor<APlayerPawn>(PlayerClass, FVector::ZeroVector, FRotator::ZeroRotator, Params);
if (Player)
{
Player->Initialize(PlayerRow);
PlayerMap.Add(PlayerRow.PlayerId, Player);
}
return Player;
}
ACircle* AGameManager::SpawnCircle(const FCircleType& CircleRow)
{
if (!CircleClass)
{
UE_LOG(LogTemp, Error, TEXT("GameManager - CircleClass not set."));
return nullptr;
}
// Need player row for username
const FPlayerType PlayerRow = Conn->Db->Player->PlayerId->Find(CircleRow.PlayerId);
APlayerPawn* OwningPlayer = SpawnOrGetPlayer(PlayerRow);
FActorSpawnParameters Params;
auto* Circle = GetWorld()->SpawnActor<ACircle>(CircleClass, FVector::ZeroVector, FRotator::ZeroRotator, Params);
if (Circle)
{
Circle->Spawn(CircleRow, OwningPlayer);
EntityMap.Add(CircleRow.EntityId, Circle);
if (OwningPlayer)
OwningPlayer->OnCircleSpawned(Circle);
}
return Circle;
}
AFood* AGameManager::SpawnFood(const FFoodType& FoodEntity)
{
if (!FoodClass)
{
UE_LOG(LogTemp, Error, TEXT("GameManager - FoodClass not set."));
return nullptr;
}
FActorSpawnParameters Params;
AFood* Food = GetWorld()->SpawnActor<AFood>(FoodClass, FVector::ZeroVector, FRotator::ZeroRotator, Params);
if (Food)
{
Food->Spawn(FoodEntity);
EntityMap.Add(FoodEntity.EntityId, Food);
}
return Food;
}
@@ -0,0 +1,15 @@
#include "Gameplay/LeaderboardRowWidget.h"
#include "Components/TextBlock.h"
void ULeaderboardRowWidget::SetData(const FString& Username, int32 Mass)
{
if (UsernameText)
{
UsernameText->SetText(FText::FromString(Username));
}
if (MassText)
{
MassText->SetText(FText::AsNumber(Mass));
}
}
@@ -0,0 +1,134 @@
#include "Gameplay/LeaderboardWidget.h"
#include "GameManager.h"
#include "PlayerPawn.h"
#include "Components/VerticalBox.h"
#include "Gameplay/LeaderboardRowWidget.h"
void ULeaderboardWidget::NativeConstruct()
{
Super::NativeConstruct();
BuildRowPool();
if (UpdatePeriod > 0.f)
{
GetWorld()->GetTimerManager().SetTimer(
UpdateTimer, this, &ULeaderboardWidget::UpdateLeaderboard, UpdatePeriod, true, 0.0f);
}
UpdateLeaderboard();
}
void ULeaderboardWidget::NativeDestruct()
{
if (UWorld* World = GetWorld())
{
World->GetTimerManager().ClearTimer(UpdateTimer);
}
Super::NativeDestruct();
}
void ULeaderboardWidget::BuildRowPool()
{
if (!Root || !RowClass) { return; }
Rows.Reset();
for (int32 i = 0; i < MaxRowCount; ++i)
{
ULeaderboardRowWidget* Row = CreateWidget<ULeaderboardRowWidget>(this, RowClass);
if (!Row) { continue; }
Root->AddChild(Row);
Row->SetVisibility(ESlateVisibility::Collapsed);
Rows.Add(Row);
}
}
void ULeaderboardWidget::CollectPlayers(TArray<FLeaderboardEntry>& Out) const
{
Out.Reset();
const AGameManager* GM = AGameManager::Instance;
if (!GM) return;
TMap<uint32, TWeakObjectPtr<APlayerPawn>> PlayerMap = GM->GetPlayerMap();
if (PlayerMap.Num() == 0) return;
// 2) Build entries: mass > 0 only
for (const TPair<uint32, TWeakObjectPtr<APlayerPawn>>& Pair : PlayerMap)
{
APlayerPawn* Pawn = Pair.Value.Get();
if (!Pawn) continue;
const int32 Mass = static_cast<int32>(Pawn->TotalMass());
if (Mass == 0) continue;
FLeaderboardEntry E;
E.Username = Pawn->GetUsername();
E.Mass = Mass;
E.Pawn = Pawn;
Out.Add(MoveTemp(E));
}
// 3) Sort by mass desc (stable by Username as a tiebreaker for consistent ordering)
Out.Sort([](const FLeaderboardEntry& A, const FLeaderboardEntry& B)
{
if (A.Mass != B.Mass) return A.Mass > B.Mass;
return A.Username < B.Username;
});
// 4) Keep top 10
if (Out.Num() > 10)
{
Out.SetNum(10, /*bAllowShrinking*/ false);
}
// 5) Append local player if not already present and has Mass > 0
APlayerController* PC = GetOwningPlayer();
if (PC)
{
if (APlayerPawn* LocalPawn = Cast<APlayerPawn>(PC->GetPawn()))
{
const bool AlreadyIn = Out.ContainsByPredicate(
[LocalPawn](const FLeaderboardEntry& E){ return E.Pawn.Get() == LocalPawn; });
const int32 LocalMass = static_cast<int32>(LocalPawn->TotalMass());
if (!AlreadyIn && LocalMass > 0)
{
FLeaderboardEntry Local;
Local.Username = LocalPawn->GetUsername();
Local.Mass = LocalMass;
Local.Pawn = LocalPawn;
Out.Add(MoveTemp(Local));
}
}
}
}
void ULeaderboardWidget::UpdateLeaderboard()
{
if (Rows.Num() == 0) return;
TArray<FLeaderboardEntry> Players;
CollectPlayers(Players);
int32 i = 0;
for (; i < Players.Num() && i < Rows.Num(); ++i)
{
if (ULeaderboardRowWidget* Row = Rows[i])
{
Row->SetData(Players[i].Username, Players[i].Mass);
Row->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
}
}
// Hide the rest
for (; i < Rows.Num(); ++i)
{
if (ULeaderboardRowWidget* Row = Rows[i])
{
Row->SetVisibility(ESlateVisibility::Collapsed);
}
}
}
@@ -0,0 +1,31 @@
#include "Gameplay/ParallaxBackground.h"
#include "GameManager.h"
#include "Kismet/GameplayStatics.h"
#include "ModuleBindings/Tables/ConfigTable.g.h"
AParallaxBackground::AParallaxBackground()
{
PrimaryActorTick.bCanEverTick = true;
}
void AParallaxBackground::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
APlayerCameraManager* PCM = UGameplayStatics::GetPlayerCameraManager(this, 0);
if (!PCM) return;
const FVector Cam = PCM->GetCameraLocation();
uint64 WorldSize = AGameManager::Instance->Conn->Db->Config->Id->Find(0).WorldSize;
float WorldCenter = (WorldSize);
const FVector NewLoc(
(Cam.X+WorldCenter) * Multiplier, // plane X
FixedY, // depth constant
(Cam.Z+WorldCenter) * Multiplier // plane Z
);
SetActorLocation(NewLoc);
}
@@ -0,0 +1,23 @@
#include "Gameplay/RespawnWidget.h"
#include "Components/Button.h"
#include "GameManager.h"
void URespawnWidget::NativeConstruct()
{
Super::NativeConstruct();
RespawnButton->OnClicked.AddDynamic(this, &URespawnWidget::OnRespawnPressed);
}
void URespawnWidget::OnRespawnPressed()
{
AGameManager* Manager = AGameManager::Instance;
UE_LOG(LogTemp, Warning, TEXT("Respawn calling reducer"));
Manager->Conn->Reducers->Respawn();
UE_LOG(LogTemp, Warning, TEXT("Respawn reducer called"));
SetVisibility(ESlateVisibility::Collapsed);
if (APlayerController* PC = GetOwningPlayer())
{
PC->SetInputMode(FInputModeGameOnly());
//PC->bShowMouseCursor = false;
}
}
@@ -0,0 +1,56 @@
#include "Gameplay/UsernameChooserWidget.h"
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "ModuleBindings/Tables/PlayerTable.g.h"
#include "GameManager.h"
void UUsernameChooserWidget::Hide()
{
SetVisibility(ESlateVisibility::Collapsed);
if (APlayerController* PC = GetOwningPlayer())
{
PC->SetInputMode(FInputModeGameOnly());
}
}
void UUsernameChooserWidget::NativeConstruct()
{
Super::NativeConstruct();
PlayButton->OnClicked.AddDynamic(this, &UUsernameChooserWidget::OnPlayPressed);
AGameManager* Manager = AGameManager::Instance;
Manager->Conn->Db->Player->OnInsert.AddDynamic(this, &UUsernameChooserWidget::HandlePlayerInserted);
}
void UUsernameChooserWidget::NativeDestruct()
{
Super::NativeDestruct();
AGameManager* Manager = AGameManager::Instance;
Manager->Conn->Db->Player->OnInsert.RemoveDynamic(this, &UUsernameChooserWidget::HandlePlayerInserted);
}
void UUsernameChooserWidget::OnPlayPressed()
{
FString Name = UsernameInputField ? UsernameInputField->GetText().ToString().TrimStartAndEnd() : TEXT("");
if (Name.IsEmpty())
{
Name = TEXT("<No Name>");
}
AGameManager* Manager = AGameManager::Instance;
Manager->Conn->Reducers->EnterGame(Name);
SetVisibility(ESlateVisibility::Collapsed);
if (APlayerController* PC = GetOwningPlayer())
{
PC->SetInputMode(FInputModeGameOnly());
}
}
void UUsernameChooserWidget::HandlePlayerInserted(const FEventContext& Context, const FPlayerType& NewPlayer)
{
AGameManager* Manager = AGameManager::Instance;
if (UsernameInputField && NewPlayer.Identity == Manager->LocalIdentity)
{
UsernameInputField->SetText(FText::FromString(NewPlayer.Name));
}
}
@@ -0,0 +1,927 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/SpacetimeDBClient.g.h"
#include "DBCache/WithBsatn.h"
#include "BSATN/UEBSATNHelpers.h"
#include "ModuleBindings/Tables/EntityTable.g.h"
#include "ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h"
#include "ModuleBindings/Tables/CircleDecayTimerTable.g.h"
#include "ModuleBindings/Tables/EntityTable.g.h"
#include "ModuleBindings/Tables/FoodTable.g.h"
#include "ModuleBindings/Tables/CircleRecombineTimerTable.g.h"
#include "ModuleBindings/Tables/ConfigTable.g.h"
#include "ModuleBindings/Tables/PlayerTable.g.h"
#include "ModuleBindings/Tables/CircleTable.g.h"
#include "ModuleBindings/Tables/PlayerTable.g.h"
#include "ModuleBindings/Tables/ConsumeEntityTimerTable.g.h"
#include "ModuleBindings/Tables/SpawnFoodTimerTable.g.h"
#include "ModuleBindings/Tables/CircleTable.g.h"
static FReducer DecodeReducer(const FReducerEvent& Event)
{
const FString& ReducerName = Event.ReducerCall.ReducerName;
if (ReducerName == TEXT("circle_decay"))
{
FCircleDecayArgs Args = UE::SpacetimeDB::Deserialize<FCircleDecayArgs>(Event.ReducerCall.Args);
return FReducer::CircleDecay(Args);
}
if (ReducerName == TEXT("circle_recombine"))
{
FCircleRecombineArgs Args = UE::SpacetimeDB::Deserialize<FCircleRecombineArgs>(Event.ReducerCall.Args);
return FReducer::CircleRecombine(Args);
}
if (ReducerName == TEXT("connect"))
{
FConnectArgs Args = UE::SpacetimeDB::Deserialize<FConnectArgs>(Event.ReducerCall.Args);
return FReducer::Connect(Args);
}
if (ReducerName == TEXT("consume_entity"))
{
FConsumeEntityArgs Args = UE::SpacetimeDB::Deserialize<FConsumeEntityArgs>(Event.ReducerCall.Args);
return FReducer::ConsumeEntity(Args);
}
if (ReducerName == TEXT("disconnect"))
{
FDisconnectArgs Args = UE::SpacetimeDB::Deserialize<FDisconnectArgs>(Event.ReducerCall.Args);
return FReducer::Disconnect(Args);
}
if (ReducerName == TEXT("enter_game"))
{
FEnterGameArgs Args = UE::SpacetimeDB::Deserialize<FEnterGameArgs>(Event.ReducerCall.Args);
return FReducer::EnterGame(Args);
}
if (ReducerName == TEXT("move_all_players"))
{
FMoveAllPlayersArgs Args = UE::SpacetimeDB::Deserialize<FMoveAllPlayersArgs>(Event.ReducerCall.Args);
return FReducer::MoveAllPlayers(Args);
}
if (ReducerName == TEXT("player_split"))
{
FPlayerSplitArgs Args = UE::SpacetimeDB::Deserialize<FPlayerSplitArgs>(Event.ReducerCall.Args);
return FReducer::PlayerSplit(Args);
}
if (ReducerName == TEXT("respawn"))
{
FRespawnArgs Args = UE::SpacetimeDB::Deserialize<FRespawnArgs>(Event.ReducerCall.Args);
return FReducer::Respawn(Args);
}
if (ReducerName == TEXT("spawn_food"))
{
FSpawnFoodArgs Args = UE::SpacetimeDB::Deserialize<FSpawnFoodArgs>(Event.ReducerCall.Args);
return FReducer::SpawnFood(Args);
}
if (ReducerName == TEXT("suicide"))
{
FSuicideArgs Args = UE::SpacetimeDB::Deserialize<FSuicideArgs>(Event.ReducerCall.Args);
return FReducer::Suicide(Args);
}
if (ReducerName == TEXT("update_player_input"))
{
FUpdatePlayerInputArgs Args = UE::SpacetimeDB::Deserialize<FUpdatePlayerInputArgs>(Event.ReducerCall.Args);
return FReducer::UpdatePlayerInput(Args);
}
return FReducer();
}
UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
SetReducerFlags = ObjectInitializer.CreateDefaultSubobject<USetReducerFlags>(this, TEXT("SetReducerFlags"));
Db = ObjectInitializer.CreateDefaultSubobject<URemoteTables>(this, TEXT("RemoteTables"));
Db->Initialize();
Reducers = ObjectInitializer.CreateDefaultSubobject<URemoteReducers>(this, TEXT("RemoteReducers"));
Reducers->SetCallReducerFlags = SetReducerFlags;
Reducers->Conn = this;
RegisterTable<FEntityType, UEntityTable, FEventContext>(TEXT("logged_out_entity"), Db->LoggedOutEntity);
RegisterTable<FMoveAllPlayersTimerType, UMoveAllPlayersTimerTable, FEventContext>(TEXT("move_all_players_timer"), Db->MoveAllPlayersTimer);
RegisterTable<FCircleDecayTimerType, UCircleDecayTimerTable, FEventContext>(TEXT("circle_decay_timer"), Db->CircleDecayTimer);
RegisterTable<FEntityType, UEntityTable, FEventContext>(TEXT("entity"), Db->Entity);
RegisterTable<FFoodType, UFoodTable, FEventContext>(TEXT("food"), Db->Food);
RegisterTable<FCircleRecombineTimerType, UCircleRecombineTimerTable, FEventContext>(TEXT("circle_recombine_timer"), Db->CircleRecombineTimer);
RegisterTable<FConfigType, UConfigTable, FEventContext>(TEXT("config"), Db->Config);
RegisterTable<FPlayerType, UPlayerTable, FEventContext>(TEXT("logged_out_player"), Db->LoggedOutPlayer);
RegisterTable<FCircleType, UCircleTable, FEventContext>(TEXT("logged_out_circle"), Db->LoggedOutCircle);
RegisterTable<FPlayerType, UPlayerTable, FEventContext>(TEXT("player"), Db->Player);
RegisterTable<FConsumeEntityTimerType, UConsumeEntityTimerTable, FEventContext>(TEXT("consume_entity_timer"), Db->ConsumeEntityTimer);
RegisterTable<FSpawnFoodTimerType, USpawnFoodTimerTable, FEventContext>(TEXT("spawn_food_timer"), Db->SpawnFoodTimer);
RegisterTable<FCircleType, UCircleTable, FEventContext>(TEXT("circle"), Db->Circle);
}
FContextBase::FContextBase(UDbConnection* InConn)
{
Db = InConn->Db;
Reducers = InConn->Reducers;
SetReducerFlags = InConn->SetReducerFlags;
Conn = InConn;
}
bool FContextBase::IsActive() const
{
return Conn->IsActive();
}
void FContextBase::Disconnect()
{
Conn->Disconnect();
}
USubscriptionBuilder* FContextBase::SubscriptionBuilder()
{
return Conn->SubscriptionBuilder();
}
bool FContextBase::TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const
{
return Conn->TryGetIdentity(OutIdentity);
}
FSpacetimeDBConnectionId FContextBase::GetConnectionId() const
{
return Conn->GetConnectionId();
}
void URemoteTables::Initialize()
{
/** Creating tables */
LoggedOutEntity = NewObject<UEntityTable>(this);
MoveAllPlayersTimer = NewObject<UMoveAllPlayersTimerTable>(this);
CircleDecayTimer = NewObject<UCircleDecayTimerTable>(this);
Entity = NewObject<UEntityTable>(this);
Food = NewObject<UFoodTable>(this);
CircleRecombineTimer = NewObject<UCircleRecombineTimerTable>(this);
Config = NewObject<UConfigTable>(this);
LoggedOutPlayer = NewObject<UPlayerTable>(this);
LoggedOutCircle = NewObject<UCircleTable>(this);
Player = NewObject<UPlayerTable>(this);
ConsumeEntityTimer = NewObject<UConsumeEntityTimerTable>(this);
SpawnFoodTimer = NewObject<USpawnFoodTimerTable>(this);
Circle = NewObject<UCircleTable>(this);
/**/
/** Initialization */
LoggedOutEntity->PostInitialize();
MoveAllPlayersTimer->PostInitialize();
CircleDecayTimer->PostInitialize();
Entity->PostInitialize();
Food->PostInitialize();
CircleRecombineTimer->PostInitialize();
Config->PostInitialize();
LoggedOutPlayer->PostInitialize();
LoggedOutCircle->PostInitialize();
Player->PostInitialize();
ConsumeEntityTimer->PostInitialize();
SpawnFoodTimer->PostInitialize();
Circle->PostInitialize();
/**/
}
void USetReducerFlags::CircleDecay(ECallReducerFlags Flag)
{
FlagMap.Add("CircleDecay", Flag);
}
void USetReducerFlags::CircleRecombine(ECallReducerFlags Flag)
{
FlagMap.Add("CircleRecombine", Flag);
}
void USetReducerFlags::Connect(ECallReducerFlags Flag)
{
FlagMap.Add("Connect", Flag);
}
void USetReducerFlags::ConsumeEntity(ECallReducerFlags Flag)
{
FlagMap.Add("ConsumeEntity", Flag);
}
void USetReducerFlags::Disconnect(ECallReducerFlags Flag)
{
FlagMap.Add("Disconnect", Flag);
}
void USetReducerFlags::EnterGame(ECallReducerFlags Flag)
{
FlagMap.Add("EnterGame", Flag);
}
void USetReducerFlags::MoveAllPlayers(ECallReducerFlags Flag)
{
FlagMap.Add("MoveAllPlayers", Flag);
}
void USetReducerFlags::PlayerSplit(ECallReducerFlags Flag)
{
FlagMap.Add("PlayerSplit", Flag);
}
void USetReducerFlags::Respawn(ECallReducerFlags Flag)
{
FlagMap.Add("Respawn", Flag);
}
void USetReducerFlags::SpawnFood(ECallReducerFlags Flag)
{
FlagMap.Add("SpawnFood", Flag);
}
void USetReducerFlags::Suicide(ECallReducerFlags Flag)
{
FlagMap.Add("Suicide", Flag);
}
void USetReducerFlags::UpdatePlayerInput(ECallReducerFlags Flag)
{
FlagMap.Add("UpdatePlayerInput", Flag);
}
void URemoteReducers::CircleDecay(const FCircleDecayTimerType& Timer)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("circle_decay"), FCircleDecayArgs(Timer), SetCallReducerFlags);
}
bool URemoteReducers::InvokeCircleDecay(const FReducerEventContext& Context, const UCircleDecayReducer* Args)
{
if (!OnCircleDecay.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for CircleDecay"));
}
return false;
}
OnCircleDecay.Broadcast(Context, Args->Timer);
return true;
}
void URemoteReducers::CircleRecombine(const FCircleRecombineTimerType& Timer)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("circle_recombine"), FCircleRecombineArgs(Timer), SetCallReducerFlags);
}
bool URemoteReducers::InvokeCircleRecombine(const FReducerEventContext& Context, const UCircleRecombineReducer* Args)
{
if (!OnCircleRecombine.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for CircleRecombine"));
}
return false;
}
OnCircleRecombine.Broadcast(Context, Args->Timer);
return true;
}
void URemoteReducers::Connect()
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("connect"), FConnectArgs(), SetCallReducerFlags);
}
bool URemoteReducers::InvokeConnect(const FReducerEventContext& Context, const UConnectReducer* Args)
{
if (!OnConnect.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Connect"));
}
return false;
}
OnConnect.Broadcast(Context);
return true;
}
void URemoteReducers::ConsumeEntity(const FConsumeEntityTimerType& Request)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("consume_entity"), FConsumeEntityArgs(Request), SetCallReducerFlags);
}
bool URemoteReducers::InvokeConsumeEntity(const FReducerEventContext& Context, const UConsumeEntityReducer* Args)
{
if (!OnConsumeEntity.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for ConsumeEntity"));
}
return false;
}
OnConsumeEntity.Broadcast(Context, Args->Request);
return true;
}
void URemoteReducers::Disconnect()
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("disconnect"), FDisconnectArgs(), SetCallReducerFlags);
}
bool URemoteReducers::InvokeDisconnect(const FReducerEventContext& Context, const UDisconnectReducer* Args)
{
if (!OnDisconnect.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Disconnect"));
}
return false;
}
OnDisconnect.Broadcast(Context);
return true;
}
void URemoteReducers::EnterGame(const FString& Name)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("enter_game"), FEnterGameArgs(Name), SetCallReducerFlags);
}
bool URemoteReducers::InvokeEnterGame(const FReducerEventContext& Context, const UEnterGameReducer* Args)
{
if (!OnEnterGame.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for EnterGame"));
}
return false;
}
OnEnterGame.Broadcast(Context, Args->Name);
return true;
}
void URemoteReducers::MoveAllPlayers(const FMoveAllPlayersTimerType& Timer)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("move_all_players"), FMoveAllPlayersArgs(Timer), SetCallReducerFlags);
}
bool URemoteReducers::InvokeMoveAllPlayers(const FReducerEventContext& Context, const UMoveAllPlayersReducer* Args)
{
if (!OnMoveAllPlayers.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for MoveAllPlayers"));
}
return false;
}
OnMoveAllPlayers.Broadcast(Context, Args->Timer);
return true;
}
void URemoteReducers::PlayerSplit()
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("player_split"), FPlayerSplitArgs(), SetCallReducerFlags);
}
bool URemoteReducers::InvokePlayerSplit(const FReducerEventContext& Context, const UPlayerSplitReducer* Args)
{
if (!OnPlayerSplit.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for PlayerSplit"));
}
return false;
}
OnPlayerSplit.Broadcast(Context);
return true;
}
void URemoteReducers::Respawn()
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("respawn"), FRespawnArgs(), SetCallReducerFlags);
}
bool URemoteReducers::InvokeRespawn(const FReducerEventContext& Context, const URespawnReducer* Args)
{
if (!OnRespawn.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Respawn"));
}
return false;
}
OnRespawn.Broadcast(Context);
return true;
}
void URemoteReducers::SpawnFood(const FSpawnFoodTimerType& Timer)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("spawn_food"), FSpawnFoodArgs(Timer), SetCallReducerFlags);
}
bool URemoteReducers::InvokeSpawnFood(const FReducerEventContext& Context, const USpawnFoodReducer* Args)
{
if (!OnSpawnFood.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for SpawnFood"));
}
return false;
}
OnSpawnFood.Broadcast(Context, Args->Timer);
return true;
}
void URemoteReducers::Suicide()
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("suicide"), FSuicideArgs(), SetCallReducerFlags);
}
bool URemoteReducers::InvokeSuicide(const FReducerEventContext& Context, const USuicideReducer* Args)
{
if (!OnSuicide.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for Suicide"));
}
return false;
}
OnSuicide.Broadcast(Context);
return true;
}
void URemoteReducers::UpdatePlayerInput(const FDbVector2Type& Direction)
{
if (!Conn)
{
UE_LOG(LogTemp, Error, TEXT("SpacetimeDB connection is null"));
return;
}
Conn->CallReducerTyped(TEXT("update_player_input"), FUpdatePlayerInputArgs(Direction), SetCallReducerFlags);
}
bool URemoteReducers::InvokeUpdatePlayerInput(const FReducerEventContext& Context, const UUpdatePlayerInputReducer* Args)
{
if (!OnUpdatePlayerInput.IsBound())
{
// Handle unhandled reducer error
if (InternalOnUnhandledReducerError.IsBound())
{
// TODO: Check Context.Event.Status for Failed/OutOfEnergy cases
// For now, just broadcast any error
InternalOnUnhandledReducerError.Broadcast(Context, TEXT("No handler registered for UpdatePlayerInput"));
}
return false;
}
OnUpdatePlayerInput.Broadcast(Context, Args->Direction);
return true;
}
void UDbConnection::PostInitProperties()
{
Super::PostInitProperties();
// Connect OnUnhandledReducerError to Reducers.InternalOnUnhandledReducerError
if (Reducers)
{
Reducers->InternalOnUnhandledReducerError.AddDynamic(this, &UDbConnection::OnUnhandledReducerErrorHandler);
}
}
UFUNCTION()
void UDbConnection::OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error)
{
if (OnUnhandledReducerError.IsBound())
{
OnUnhandledReducerError.Broadcast(Context, Error);
}
}
void UDbConnection::ReducerEvent(const FReducerEvent& Event)
{
if (!Reducers) { return; }
FReducer DecodedReducer = DecodeReducer(Event);
FClientUnrealReducerEvent ReducerEvent;
ReducerEvent.CallerConnectionId = Event.CallerConnectionId;
ReducerEvent.CallerIdentity = Event.CallerIdentity;
ReducerEvent.EnergyConsumed = Event.EnergyConsumed;
ReducerEvent.Status = Event.Status;
ReducerEvent.Timestamp = Event.Timestamp;
ReducerEvent.Reducer = DecodedReducer;
FReducerEventContext Context(this, ReducerEvent);
// Use hardcoded string matching for reducer dispatching
const FString& ReducerName = Event.ReducerCall.ReducerName;
if (ReducerName == TEXT("circle_decay"))
{
FCircleDecayArgs Args = ReducerEvent.Reducer.GetAsCircleDecay();
UCircleDecayReducer* Reducer = NewObject<UCircleDecayReducer>();
Reducer->Timer = Args.Timer;
Reducers->InvokeCircleDecay(Context, Reducer);
return;
}
if (ReducerName == TEXT("circle_recombine"))
{
FCircleRecombineArgs Args = ReducerEvent.Reducer.GetAsCircleRecombine();
UCircleRecombineReducer* Reducer = NewObject<UCircleRecombineReducer>();
Reducer->Timer = Args.Timer;
Reducers->InvokeCircleRecombine(Context, Reducer);
return;
}
if (ReducerName == TEXT("connect"))
{
FConnectArgs Args = ReducerEvent.Reducer.GetAsConnect();
UConnectReducer* Reducer = NewObject<UConnectReducer>();
Reducers->InvokeConnect(Context, Reducer);
return;
}
if (ReducerName == TEXT("consume_entity"))
{
FConsumeEntityArgs Args = ReducerEvent.Reducer.GetAsConsumeEntity();
UConsumeEntityReducer* Reducer = NewObject<UConsumeEntityReducer>();
Reducer->Request = Args.Request;
Reducers->InvokeConsumeEntity(Context, Reducer);
return;
}
if (ReducerName == TEXT("disconnect"))
{
FDisconnectArgs Args = ReducerEvent.Reducer.GetAsDisconnect();
UDisconnectReducer* Reducer = NewObject<UDisconnectReducer>();
Reducers->InvokeDisconnect(Context, Reducer);
return;
}
if (ReducerName == TEXT("enter_game"))
{
FEnterGameArgs Args = ReducerEvent.Reducer.GetAsEnterGame();
UEnterGameReducer* Reducer = NewObject<UEnterGameReducer>();
Reducer->Name = Args.Name;
Reducers->InvokeEnterGame(Context, Reducer);
return;
}
if (ReducerName == TEXT("move_all_players"))
{
FMoveAllPlayersArgs Args = ReducerEvent.Reducer.GetAsMoveAllPlayers();
UMoveAllPlayersReducer* Reducer = NewObject<UMoveAllPlayersReducer>();
Reducer->Timer = Args.Timer;
Reducers->InvokeMoveAllPlayers(Context, Reducer);
return;
}
if (ReducerName == TEXT("player_split"))
{
FPlayerSplitArgs Args = ReducerEvent.Reducer.GetAsPlayerSplit();
UPlayerSplitReducer* Reducer = NewObject<UPlayerSplitReducer>();
Reducers->InvokePlayerSplit(Context, Reducer);
return;
}
if (ReducerName == TEXT("respawn"))
{
FRespawnArgs Args = ReducerEvent.Reducer.GetAsRespawn();
URespawnReducer* Reducer = NewObject<URespawnReducer>();
Reducers->InvokeRespawn(Context, Reducer);
return;
}
if (ReducerName == TEXT("spawn_food"))
{
FSpawnFoodArgs Args = ReducerEvent.Reducer.GetAsSpawnFood();
USpawnFoodReducer* Reducer = NewObject<USpawnFoodReducer>();
Reducer->Timer = Args.Timer;
Reducers->InvokeSpawnFood(Context, Reducer);
return;
}
if (ReducerName == TEXT("suicide"))
{
FSuicideArgs Args = ReducerEvent.Reducer.GetAsSuicide();
USuicideReducer* Reducer = NewObject<USuicideReducer>();
Reducers->InvokeSuicide(Context, Reducer);
return;
}
if (ReducerName == TEXT("update_player_input"))
{
FUpdatePlayerInputArgs Args = ReducerEvent.Reducer.GetAsUpdatePlayerInput();
UUpdatePlayerInputReducer* Reducer = NewObject<UUpdatePlayerInputReducer>();
Reducer->Direction = Args.Direction;
Reducers->InvokeUpdatePlayerInput(Context, Reducer);
return;
}
UE_LOG(LogTemp, Warning, TEXT("Unknown reducer: %s"), *ReducerName);
}
void UDbConnection::ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage)
{
if (!Reducers) { return; }
FClientUnrealReducerEvent ReducerEvent;
ReducerEvent.CallerConnectionId = Event.CallerConnectionId;
ReducerEvent.CallerIdentity = Event.CallerIdentity;
ReducerEvent.EnergyConsumed = Event.EnergyConsumed;
ReducerEvent.Status = Event.Status;
ReducerEvent.Timestamp = Event.Timestamp;
FReducerEventContext Context(this, ReducerEvent);
if (Reducers->InternalOnUnhandledReducerError.IsBound())
{
Reducers->InternalOnUnhandledReducerError.Broadcast(Context, ErrorMessage);
}
}
UDbConnectionBuilder* UDbConnection::Builder()
{
return NewObject<UDbConnectionBuilder>();
}
// Added for creating subscriptions
USubscriptionBuilder* UDbConnection::SubscriptionBuilder()
{
USubscriptionBuilder* Builder = NewObject<USubscriptionBuilder>(this);
Builder->Conn = this;
return Builder;
}
USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback)
{
OnAppliedDelegateInternal = Callback;
return this;
}
USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callback)
{
OnErrorDelegateInternal = Callback;
return this;
}
USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray<FString>& SQL)
{
USubscriptionHandle* Handle = NewObject<USubscriptionHandle>();
// Store user callbacks on the handle
Handle->Conn = Conn;
Handle->OnAppliedDelegate = OnAppliedDelegateInternal;
Handle->OnErrorDelegate = OnErrorDelegateInternal;
// Bind forwarding functions that will convert base contexts
FSubscriptionEventDelegate BaseApplied;
BaseApplied.BindUFunction(Handle, TEXT("ForwardOnApplied"));
OnAppliedBase(BaseApplied);
FSubscriptionErrorDelegate BaseError;
BaseError.BindUFunction(Handle, TEXT("ForwardOnError"));
OnErrorBase(BaseError);
SubscribeBase(SQL, Handle);
if (Conn)
{
Conn->StartSubscription(Handle);
}
return Handle;
}
USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables()
{
return Subscribe({ "SELECT * FROM * " });
}
USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn)
{
Conn = InConn;
}
void USubscriptionHandle::ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx)
{
if (OnAppliedDelegate.IsBound())
{
FSubscriptionEventContext Ctx(Conn);
OnAppliedDelegate.Execute(Ctx);
}
}
void USubscriptionHandle::ForwardOnError(const FErrorContextBase& BaseCtx)
{
if (OnErrorDelegate.IsBound())
{
FErrorContext Ctx(Conn, BaseCtx.Error);
OnErrorDelegate.Execute(Ctx);
}
}
// Cast from parent to child class
UDbConnectionBuilder* UDbConnectionBuilder::WithUri(const FString& InUri)
{
return Cast<UDbConnectionBuilder>(WithUriBase(InUri));
}
UDbConnectionBuilder* UDbConnectionBuilder::WithModuleName(const FString& InName)
{
return Cast<UDbConnectionBuilder>(WithModuleNameBase(InName));
}
UDbConnectionBuilder* UDbConnectionBuilder::WithToken(const FString& InToken)
{
return Cast<UDbConnectionBuilder>(WithTokenBase(InToken));
}
UDbConnectionBuilder* UDbConnectionBuilder::WithCompression(const ESpacetimeDBCompression& InCompression)
{
return Cast<UDbConnectionBuilder>(WithCompressionBase(InCompression));
}
UDbConnectionBuilder* UDbConnectionBuilder::OnConnect(FOnConnectDelegate Callback)
{
OnConnectDelegateInternal = Callback;
return this;
}
UDbConnectionBuilder* UDbConnectionBuilder::OnConnectError(FOnConnectErrorDelegate Callback)
{
return Cast<UDbConnectionBuilder>(OnConnectErrorBase(Callback));
}
UDbConnectionBuilder* UDbConnectionBuilder::OnDisconnect(FOnDisconnectDelegate Callback)
{
OnDisconnectDelegateInternal = Callback;
return this;
}
UDbConnection* UDbConnectionBuilder::Build()
{
UDbConnection* Connection = NewObject<UDbConnection>();
// Store delegates on the connection for later use
Connection->OnConnectDelegate = OnConnectDelegateInternal;
Connection->OnDisconnectDelegate = OnDisconnectDelegateInternal;
// Wrap delegates so the base builder can bind them
FOnConnectBaseDelegate BaseConnect;
BaseConnect.BindUFunction(Connection, TEXT("ForwardOnConnect"));
Connection->SetOnConnectDelegate(BaseConnect);
OnConnectBase(BaseConnect);
FOnDisconnectBaseDelegate BaseDisconnect;
BaseDisconnect.BindUFunction(Connection, TEXT("ForwardOnDisconnect"));
Connection->SetOnDisconnectDelegate(BaseDisconnect);
OnDisconnectBase(BaseDisconnect);
return Cast<UDbConnection>(BuildConnection(Connection));
}
void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken)
{
if (OnConnectDelegate.IsBound())
{
OnConnectDelegate.Execute(this, Identity, Token);
}
}
void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error)
{
if (OnDisconnectDelegate.IsBound())
{
OnDisconnectDelegate.Execute(this, Error);
}
}
void UDbConnection::DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event)
{
FClientUnrealEvent BaseEvent;
BaseEvent.Tag = Event.Tag;
switch (Event.Tag)
{
case ESpacetimeDBEventTag::Reducer:
{
FReducerEvent ReducerEvent = Event.GetAsReducer();
FReducer Reducer = DecodeReducer(ReducerEvent);
BaseEvent = FClientUnrealEvent::Reducer(Reducer);
break;
}
case ESpacetimeDBEventTag::SubscribeApplied:
BaseEvent = FClientUnrealEvent::SubscribeApplied(Event.GetAsSubscribeApplied());
break;
case ESpacetimeDBEventTag::UnsubscribeApplied:
BaseEvent = FClientUnrealEvent::UnsubscribeApplied(Event.GetAsUnsubscribeApplied());
break;
case ESpacetimeDBEventTag::Disconnected:
BaseEvent = FClientUnrealEvent::Disconnected(Event.GetAsDisconnected());
break;
case ESpacetimeDBEventTag::SubscribeError:
BaseEvent = FClientUnrealEvent::SubscribeError(Event.GetAsSubscribeError());
break;
case ESpacetimeDBEventTag::UnknownTransaction:
BaseEvent = FClientUnrealEvent::UnknownTransaction(Event.GetAsUnknownTransaction());
break;
default:
break;
}
FEventContext Context(this, BaseEvent);
// Populate typed reducer args for convenience in table handlers
ApplyRegisteredTableUpdates(Update, &Context);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/CircleDecayTimerTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UCircleDecayTimerTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FCircleDecayTimerType>>();
TSharedPtr<FTableCache<FCircleDecayTimerType>> CircleDecayTimerTable = Data->GetOrAdd(TableName);
CircleDecayTimerTable->AddUniqueConstraint<uint64>("scheduled_id", [](const FCircleDecayTimerType& Row) -> const uint64& {
return Row.ScheduledId; });
ScheduledId = NewObject<UCircleDecayTimerScheduledIdUniqueIndex>(this);
ScheduledId->SetCache(CircleDecayTimerTable);
/***/
}
FTableAppliedDiff<FCircleDecayTimerType> UCircleDecayTimerTable::Update(TArray<FWithBsatn<FCircleDecayTimerType>> InsertsRef, TArray<FWithBsatn<FCircleDecayTimerType>> DeletesRef)
{
FTableAppliedDiff<FCircleDecayTimerType> Diff = BaseUpdate<FCircleDecayTimerType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint64>(
[](const FCircleDecayTimerType& Row)
{
return Row.ScheduledId;
}
);
return Diff;
}
int32 UCircleDecayTimerTable::Count() const
{
return GetRowCountFromTable<FCircleDecayTimerType>(Data, TableName);
}
TArray<FCircleDecayTimerType> UCircleDecayTimerTable::Iter() const
{
return GetAllRowsFromTable<FCircleDecayTimerType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/CircleRecombineTimerTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UCircleRecombineTimerTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FCircleRecombineTimerType>>();
TSharedPtr<FTableCache<FCircleRecombineTimerType>> CircleRecombineTimerTable = Data->GetOrAdd(TableName);
CircleRecombineTimerTable->AddUniqueConstraint<uint64>("scheduled_id", [](const FCircleRecombineTimerType& Row) -> const uint64& {
return Row.ScheduledId; });
ScheduledId = NewObject<UCircleRecombineTimerScheduledIdUniqueIndex>(this);
ScheduledId->SetCache(CircleRecombineTimerTable);
/***/
}
FTableAppliedDiff<FCircleRecombineTimerType> UCircleRecombineTimerTable::Update(TArray<FWithBsatn<FCircleRecombineTimerType>> InsertsRef, TArray<FWithBsatn<FCircleRecombineTimerType>> DeletesRef)
{
FTableAppliedDiff<FCircleRecombineTimerType> Diff = BaseUpdate<FCircleRecombineTimerType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint64>(
[](const FCircleRecombineTimerType& Row)
{
return Row.ScheduledId;
}
);
return Diff;
}
int32 UCircleRecombineTimerTable::Count() const
{
return GetRowCountFromTable<FCircleRecombineTimerType>(Data, TableName);
}
TArray<FCircleRecombineTimerType> UCircleRecombineTimerTable::Iter() const
{
return GetAllRowsFromTable<FCircleRecombineTimerType>(Data, TableName);
}
@@ -0,0 +1,60 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/CircleTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UCircleTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FCircleType>>();
TSharedPtr<FTableCache<FCircleType>> CircleTable = Data->GetOrAdd(TableName);
CircleTable->AddUniqueConstraint<uint32>("entity_id", [](const FCircleType& Row) -> const uint32& {
return Row.EntityId; });
EntityId = NewObject<UCircleEntityIdUniqueIndex>(this);
EntityId->SetCache(CircleTable);
// Register a new multi-key B-Tree index named "player_id" on the CircleTable.
CircleTable->AddMultiKeyBTreeIndex<TTuple<uint32>>(
TEXT("player_id"),
[](const FCircleType& Row)
{
// This tuple is stored in the B-Tree index for fast composite key lookups.
return MakeTuple(Row.PlayerId);
}
);
PlayerId = NewObject<UCirclePlayerIdIndex>(this);
PlayerId->SetCache(CircleTable);
/***/
}
FTableAppliedDiff<FCircleType> UCircleTable::Update(TArray<FWithBsatn<FCircleType>> InsertsRef, TArray<FWithBsatn<FCircleType>> DeletesRef)
{
FTableAppliedDiff<FCircleType> Diff = BaseUpdate<FCircleType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint32>(
[](const FCircleType& Row)
{
return Row.EntityId;
}
);
return Diff;
}
int32 UCircleTable::Count() const
{
return GetRowCountFromTable<FCircleType>(Data, TableName);
}
TArray<FCircleType> UCircleTable::Iter() const
{
return GetAllRowsFromTable<FCircleType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/ConfigTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UConfigTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FConfigType>>();
TSharedPtr<FTableCache<FConfigType>> ConfigTable = Data->GetOrAdd(TableName);
ConfigTable->AddUniqueConstraint<uint32>("id", [](const FConfigType& Row) -> const uint32& {
return Row.Id; });
Id = NewObject<UConfigIdUniqueIndex>(this);
Id->SetCache(ConfigTable);
/***/
}
FTableAppliedDiff<FConfigType> UConfigTable::Update(TArray<FWithBsatn<FConfigType>> InsertsRef, TArray<FWithBsatn<FConfigType>> DeletesRef)
{
FTableAppliedDiff<FConfigType> Diff = BaseUpdate<FConfigType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint32>(
[](const FConfigType& Row)
{
return Row.Id;
}
);
return Diff;
}
int32 UConfigTable::Count() const
{
return GetRowCountFromTable<FConfigType>(Data, TableName);
}
TArray<FConfigType> UConfigTable::Iter() const
{
return GetAllRowsFromTable<FConfigType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/ConsumeEntityTimerTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UConsumeEntityTimerTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FConsumeEntityTimerType>>();
TSharedPtr<FTableCache<FConsumeEntityTimerType>> ConsumeEntityTimerTable = Data->GetOrAdd(TableName);
ConsumeEntityTimerTable->AddUniqueConstraint<uint64>("scheduled_id", [](const FConsumeEntityTimerType& Row) -> const uint64& {
return Row.ScheduledId; });
ScheduledId = NewObject<UConsumeEntityTimerScheduledIdUniqueIndex>(this);
ScheduledId->SetCache(ConsumeEntityTimerTable);
/***/
}
FTableAppliedDiff<FConsumeEntityTimerType> UConsumeEntityTimerTable::Update(TArray<FWithBsatn<FConsumeEntityTimerType>> InsertsRef, TArray<FWithBsatn<FConsumeEntityTimerType>> DeletesRef)
{
FTableAppliedDiff<FConsumeEntityTimerType> Diff = BaseUpdate<FConsumeEntityTimerType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint64>(
[](const FConsumeEntityTimerType& Row)
{
return Row.ScheduledId;
}
);
return Diff;
}
int32 UConsumeEntityTimerTable::Count() const
{
return GetRowCountFromTable<FConsumeEntityTimerType>(Data, TableName);
}
TArray<FConsumeEntityTimerType> UConsumeEntityTimerTable::Iter() const
{
return GetAllRowsFromTable<FConsumeEntityTimerType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/EntityTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UEntityTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FEntityType>>();
TSharedPtr<FTableCache<FEntityType>> EntityTable = Data->GetOrAdd(TableName);
EntityTable->AddUniqueConstraint<uint32>("entity_id", [](const FEntityType& Row) -> const uint32& {
return Row.EntityId; });
EntityId = NewObject<UEntityEntityIdUniqueIndex>(this);
EntityId->SetCache(EntityTable);
/***/
}
FTableAppliedDiff<FEntityType> UEntityTable::Update(TArray<FWithBsatn<FEntityType>> InsertsRef, TArray<FWithBsatn<FEntityType>> DeletesRef)
{
FTableAppliedDiff<FEntityType> Diff = BaseUpdate<FEntityType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint32>(
[](const FEntityType& Row)
{
return Row.EntityId;
}
);
return Diff;
}
int32 UEntityTable::Count() const
{
return GetRowCountFromTable<FEntityType>(Data, TableName);
}
TArray<FEntityType> UEntityTable::Iter() const
{
return GetAllRowsFromTable<FEntityType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/FoodTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UFoodTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FFoodType>>();
TSharedPtr<FTableCache<FFoodType>> FoodTable = Data->GetOrAdd(TableName);
FoodTable->AddUniqueConstraint<uint32>("entity_id", [](const FFoodType& Row) -> const uint32& {
return Row.EntityId; });
EntityId = NewObject<UFoodEntityIdUniqueIndex>(this);
EntityId->SetCache(FoodTable);
/***/
}
FTableAppliedDiff<FFoodType> UFoodTable::Update(TArray<FWithBsatn<FFoodType>> InsertsRef, TArray<FWithBsatn<FFoodType>> DeletesRef)
{
FTableAppliedDiff<FFoodType> Diff = BaseUpdate<FFoodType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint32>(
[](const FFoodType& Row)
{
return Row.EntityId;
}
);
return Diff;
}
int32 UFoodTable::Count() const
{
return GetRowCountFromTable<FFoodType>(Data, TableName);
}
TArray<FFoodType> UFoodTable::Iter() const
{
return GetAllRowsFromTable<FFoodType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UMoveAllPlayersTimerTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FMoveAllPlayersTimerType>>();
TSharedPtr<FTableCache<FMoveAllPlayersTimerType>> MoveAllPlayersTimerTable = Data->GetOrAdd(TableName);
MoveAllPlayersTimerTable->AddUniqueConstraint<uint64>("scheduled_id", [](const FMoveAllPlayersTimerType& Row) -> const uint64& {
return Row.ScheduledId; });
ScheduledId = NewObject<UMoveAllPlayersTimerScheduledIdUniqueIndex>(this);
ScheduledId->SetCache(MoveAllPlayersTimerTable);
/***/
}
FTableAppliedDiff<FMoveAllPlayersTimerType> UMoveAllPlayersTimerTable::Update(TArray<FWithBsatn<FMoveAllPlayersTimerType>> InsertsRef, TArray<FWithBsatn<FMoveAllPlayersTimerType>> DeletesRef)
{
FTableAppliedDiff<FMoveAllPlayersTimerType> Diff = BaseUpdate<FMoveAllPlayersTimerType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint64>(
[](const FMoveAllPlayersTimerType& Row)
{
return Row.ScheduledId;
}
);
return Diff;
}
int32 UMoveAllPlayersTimerTable::Count() const
{
return GetRowCountFromTable<FMoveAllPlayersTimerType>(Data, TableName);
}
TArray<FMoveAllPlayersTimerType> UMoveAllPlayersTimerTable::Iter() const
{
return GetAllRowsFromTable<FMoveAllPlayersTimerType>(Data, TableName);
}
@@ -0,0 +1,52 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/PlayerTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void UPlayerTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FPlayerType>>();
TSharedPtr<FTableCache<FPlayerType>> PlayerTable = Data->GetOrAdd(TableName);
PlayerTable->AddUniqueConstraint<FSpacetimeDBIdentity>("identity", [](const FPlayerType& Row) -> const FSpacetimeDBIdentity& {
return Row.Identity; });
PlayerTable->AddUniqueConstraint<uint32>("player_id", [](const FPlayerType& Row) -> const uint32& {
return Row.PlayerId; });
Identity = NewObject<UPlayerIdentityUniqueIndex>(this);
Identity->SetCache(PlayerTable);
PlayerId = NewObject<UPlayerPlayerIdUniqueIndex>(this);
PlayerId->SetCache(PlayerTable);
/***/
}
FTableAppliedDiff<FPlayerType> UPlayerTable::Update(TArray<FWithBsatn<FPlayerType>> InsertsRef, TArray<FWithBsatn<FPlayerType>> DeletesRef)
{
FTableAppliedDiff<FPlayerType> Diff = BaseUpdate<FPlayerType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<FSpacetimeDBIdentity>(
[](const FPlayerType& Row)
{
return Row.Identity;
}
);
return Diff;
}
int32 UPlayerTable::Count() const
{
return GetRowCountFromTable<FPlayerType>(Data, TableName);
}
TArray<FPlayerType> UPlayerTable::Iter() const
{
return GetAllRowsFromTable<FPlayerType>(Data, TableName);
}
@@ -0,0 +1,47 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#include "ModuleBindings/Tables/SpawnFoodTimerTable.g.h"
#include "DBCache/UniqueIndex.h"
#include "DBCache/BTreeUniqueIndex.h"
#include "DBCache/ClientCache.h"
#include "DBCache/TableCache.h"
void USpawnFoodTimerTable::PostInitialize()
{
/** Client cache init and setting up indexes*/
Data = MakeShared<UClientCache<FSpawnFoodTimerType>>();
TSharedPtr<FTableCache<FSpawnFoodTimerType>> SpawnFoodTimerTable = Data->GetOrAdd(TableName);
SpawnFoodTimerTable->AddUniqueConstraint<uint64>("scheduled_id", [](const FSpawnFoodTimerType& Row) -> const uint64& {
return Row.ScheduledId; });
ScheduledId = NewObject<USpawnFoodTimerScheduledIdUniqueIndex>(this);
ScheduledId->SetCache(SpawnFoodTimerTable);
/***/
}
FTableAppliedDiff<FSpawnFoodTimerType> USpawnFoodTimerTable::Update(TArray<FWithBsatn<FSpawnFoodTimerType>> InsertsRef, TArray<FWithBsatn<FSpawnFoodTimerType>> DeletesRef)
{
FTableAppliedDiff<FSpawnFoodTimerType> Diff = BaseUpdate<FSpawnFoodTimerType>(InsertsRef, DeletesRef, Data, TableName);
Diff.DeriveUpdatesByPrimaryKey<uint64>(
[](const FSpawnFoodTimerType& Row)
{
return Row.ScheduledId;
}
);
return Diff;
}
int32 USpawnFoodTimerTable::Count() const
{
return GetRowCountFromTable<FSpawnFoodTimerType>(Data, TableName);
}
TArray<FSpawnFoodTimerType> USpawnFoodTimerTable::Iter() const
{
return GetAllRowsFromTable<FSpawnFoodTimerType>(Data, TableName);
}
@@ -0,0 +1,216 @@
#include "PlayerPawn.h"
#include "BlackholioPlayerController.h"
#include "Circle.h"
#include "GameManager.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Kismet/GameplayStatics.h"
#include "ModuleBindings/Tables/EntityTable.g.h"
#include "ModuleBindings/Tables/PlayerTable.g.h"
#include "ModuleBindings/Types/EntityType.g.h"
#include "ModuleBindings/Types/PlayerType.g.h"
APlayerPawn::APlayerPawn()
{
PrimaryActorTick.bCanEverTick = true;
USceneComponent* DefaultRoot = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
RootComponent = DefaultRoot;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(RootComponent);
SpringArm->SetRelativeRotation(FRotator(0.f, -90.f, 0.f));
SpringArm->TargetArmLength = 15000.f;
SpringArm->bUsePawnControlRotation = false;
SpringArm->bDoCollisionTest = false;
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
Camera->SetupAttachment(SpringArm);
Camera->SetProjectionMode(ECameraProjectionMode::Perspective);
Camera->FieldOfView = 90.f; // top-down 90° FOV
}
void APlayerPawn::Initialize(FPlayerType Player)
{
PlayerId = Player.PlayerId;
if (Player.Identity == AGameManager::Instance->LocalIdentity)
{
bIsLocalPlayer = true;
if (APlayerController* PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{
PC->Possess(this);
}
}
}
FString APlayerPawn::GetUsername() const
{
FPlayerType Player = AGameManager::Instance->Conn->Db->Player->PlayerId->Find(PlayerId);
return Player.Name;
}
void APlayerPawn::OnCircleSpawned(ACircle* Circle)
{
if (ensure(Circle))
{
OwnedCircles.AddUnique(Circle);
}
}
void APlayerPawn::OnCircleDeleted(ACircle* Circle)
{
if (Circle)
{
for (int32 i = OwnedCircles.Num() - 1; i >= 0; --i)
{
if (!OwnedCircles[i].IsValid() || OwnedCircles[i].Get() == Circle)
{
OwnedCircles.RemoveAt(i);
}
}
}
else
{
for (int32 i = OwnedCircles.Num() - 1; i >= 0; --i)
{
if (!OwnedCircles[i].IsValid())
{
OwnedCircles.RemoveAt(i);
}
}
}
if (OwnedCircles.Num() == 0 && bIsLocalPlayer)
{
if (ABlackholioPlayerController* PlayerController = Cast<ABlackholioPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0)))
{
PlayerController->ShowDeathScreen();
}
}
}
void APlayerPawn::Split()
{
AGameManager::Instance->Conn->Reducers->PlayerSplit();
}
void APlayerPawn::Suicide()
{
AGameManager::Instance->Conn->Reducers->Suicide();
}
uint32 APlayerPawn::TotalMass() const
{
uint32 Total = 0;
for (int32 Index = 0; Index < OwnedCircles.Num(); ++Index)
{
const TWeakObjectPtr<ACircle>& Weak = OwnedCircles[Index];
if (!Weak.IsValid()) continue;
const ACircle* Circle = Weak.Get();
const uint32 Id = Circle->EntityId;
const FEntityType Entity = AGameManager::Instance->Conn->Db->Entity->EntityId->Find(Id);
Total += Entity.Mass;
}
return Total;
}
FVector APlayerPawn::CenterOfMass() const
{
if (OwnedCircles.Num() == 0)
{
return FVector::ZeroVector;
}
FVector WeightedPosition = FVector::ZeroVector; // Σ (pos * mass)
double TotalMass = 0.0; // Σ mass
const int32 Count = OwnedCircles.Num();
for (int32 Index = 0; Index < Count; ++Index)
{
const TWeakObjectPtr<ACircle>& Weak = OwnedCircles[Index];
if (!Weak.IsValid()) continue;
const ACircle* Circle = Weak.Get();
const uint32 Id = Circle->EntityId;
const FEntityType Entity = AGameManager::Instance->Conn->Db->Entity->EntityId->Find(Id);
const double Mass = Entity.Mass;
const FVector Loc = Circle->GetActorLocation();
if (Mass <= 0.0) continue;
WeightedPosition += (Loc * Mass);
TotalMass += Mass;
}
const FVector ActorLoc = GetActorLocation();
FVector Result = FVector::ZeroVector;
if (TotalMass > 0.0)
{
const FVector CalculatedCenter = WeightedPosition / TotalMass;
// Keep Z at the player's Z, per your original intent
Result = FVector(CalculatedCenter.X, ActorLoc.Y, CalculatedCenter.Z);
}
return Result;
}
void APlayerPawn::Destroyed()
{
Super::Destroyed();
for (TWeakObjectPtr<ACircle>& CirclePtr : OwnedCircles)
{
if (ACircle* Circle = CirclePtr.Get())
{
Circle->Destroy();
}
}
OwnedCircles.Empty();
}
void APlayerPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!bIsLocalPlayer || OwnedCircles.Num() == 0)
return;
const FVector ArenaCenter(0.f, 1.f, 0.f);
FVector Target = ArenaCenter;
if (AGameManager::Instance->IsConnected())
{
const FVector CoM = CenterOfMass();
if (!CoM.ContainsNaN())
{
Target = { CoM.X, 1.f, CoM.Z };
}
}
const FVector NewLoc = FMath::VInterpTo(GetActorLocation(), Target, DeltaTime, 120.f);
SetActorLocation(NewLoc);
const float FOVDeg = 90.f; // vertical FOV
const float HalfAngleRad = FMath::DegreesToRadians(FOVDeg * 0.5f);
const float TanHalf = FMath::Tan(HalfAngleRad); // = 1.0 at 90°
const float sizeUnity =
BaseSize
+ FMath::Min(MaxMassBonus, TotalMass() / MassToSizeDivisor)
+ FMath::Min(FMath::Max(OwnedCircles.Num() - 1, 0), 1) * SplitBonus;
// If you want ~15000 cm at BaseSize (e.g., 50), use scale = 3.f:
const float Scale = 3.f;
// Distance that matches Unity size at 90° FOV:
const float targetArmCm = (Scale * sizeUnity * 100.f) / TanHalf; // TanHalf==1 at 90°
SpringArm->TargetArmLength = FMath::FInterpTo(
SpringArm->TargetArmLength, targetArmCm, DeltaTime, /*ZoomSpeed*/2.f);
}
@@ -0,0 +1,15 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "BlackholioGameMode.generated.h"
/**
*
*/
UCLASS()
class CLIENT_UNREAL_API ABlackholioGameMode : public AGameModeBase
{
GENERATED_BODY()
};
@@ -0,0 +1,78 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "InputActionValue.h"
#include "BlackholioPlayerController.generated.h"
class APlayerPawn;
class UInputAction;
class UInputMappingContext;
class URespawnWidget;
class UUsernameChooserWidget;
class ULeaderboardWidget;
UCLASS()
class CLIENT_UNREAL_API ABlackholioPlayerController : public APlayerController
{
GENERATED_BODY()
public:
ABlackholioPlayerController();
UFUNCTION(BlueprintCallable, Category = "BH|Functions")
void ShowDeathScreen();
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaSeconds) override;
virtual void OnPossess(APawn* InPawn) override;
virtual void SetupInputComponent() override;
FVector2D ComputeDesiredDirection() const;
UPROPERTY(EditDefaultsOnly, Category="BH|Config")
TSubclassOf<UUserWidget> UsernameChooserClass;
UPROPERTY(EditDefaultsOnly, Category="BH|Config")
TSubclassOf<UUserWidget> RespawnClass;
UPROPERTY(EditDefaultsOnly, Category="BH|Config")
TSubclassOf<UUserWidget> LeaderboardClass;
private:
UFUNCTION()
void EnsureMappingContext() const;
UPROPERTY()
TObjectPtr<APlayerPawn> LocalPlayer;
UPROPERTY()
float SendUpdatesFrequency = 0.0333f;
float LastMovementSendTimestamp = 0.f;
bool bShowedUsernameChooser = false;
TOptional<FVector2D> LockInputPosition;
UPROPERTY(EditDefaultsOnly, Category="BH|Input")
TObjectPtr<UInputMappingContext> PlayerMappingContext = nullptr;
UPROPERTY(EditDefaultsOnly, Category="BH|Input")
TObjectPtr<UInputAction> SplitAction = nullptr;
UPROPERTY(EditDefaultsOnly, Category="BH|Input")
TObjectPtr<UInputAction> SuicideAction = nullptr;
UPROPERTY(EditDefaultsOnly, Category="BH|Input")
TObjectPtr<UInputAction> ToggleInputLockAction = nullptr;
UPROPERTY()
TObjectPtr<URespawnWidget> RespawnWidget = nullptr;
UPROPERTY()
TObjectPtr<UUsernameChooserWidget> UsernameChooserWidget = nullptr;
UPROPERTY()
TObjectPtr<ULeaderboardWidget> LeaderboardWidget = nullptr;
// Input handlers (Enhanced Input)
void OnSplitTriggered(const FInputActionValue& Value);
void OnSuicideTriggered(const FInputActionValue& Value);
void OnToggleInputLockTriggered(const FInputActionValue& Value);
};
@@ -0,0 +1,38 @@
#pragma once
#include "CoreMinimal.h"
#include "Entity.h"
#include "Circle.generated.h"
struct FCircleType;
class APlayerPawn;
UCLASS()
class CLIENT_UNREAL_API ACircle : public AEntity
{
GENERATED_BODY()
public:
ACircle();
uint32 OwnerPlayerId = 0;
UPROPERTY(BlueprintReadOnly, Category="BH|Circle")
FString Username;
void Spawn(const FCircleType& Circle, APlayerPawn* InOwner);
virtual void OnDelete(const FEventContext& Context) override;
UFUNCTION(BlueprintCallable, Category="BH|Circle")
void SetUsername(const FString& InUsername);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnUsernameChanged, const FString&, NewUsername);
UPROPERTY(BlueprintAssignable, Category="BH|Circle")
FOnUsernameChanged OnUsernameChanged;
protected:
UPROPERTY(EditDefaultsOnly, Category="BH|Circle")
TArray<FLinearColor> ColorPalette;
private:
TWeakObjectPtr<APlayerPawn> Owner;
};
@@ -0,0 +1,29 @@
#pragma once
#include "ModuleBindings/Types/DbVector2Type.g.h"
FORCEINLINE FDbVector2Type ToDbVector(const FVector2D& Vec)
{
FDbVector2Type Out;
Out.X = Vec.X;
Out.Y = Vec.Y;
return Out;
}
FORCEINLINE FDbVector2Type ToDbVector(const FVector& Vec)
{
FDbVector2Type Out;
Out.X = Vec.X;
Out.Y = Vec.Y;
return Out;
}
FORCEINLINE FVector2D ToFVector2D(const FDbVector2Type& Vec)
{
return FVector2D(Vec.X * 100.f, Vec.Y * 100.f);
}
FORCEINLINE FVector ToFVector(const FDbVector2Type& Vec, float Z = 0.f)
{
return FVector(Vec.X * 100.f, Z, Vec.Y * 100.f);
}
@@ -0,0 +1,53 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Entity.generated.h"
struct FEventContext;
struct FEntityType;
UCLASS()
class CLIENT_UNREAL_API AEntity : public AActor
{
GENERATED_BODY()
public:
AEntity();
protected:
UPROPERTY(EditDefaultsOnly, Category="BH|Entity")
float LerpTime = 0.f;
UPROPERTY(EditDefaultsOnly, Category="BH|Entity")
float LerpDuration = 0.10f;
UPROPERTY(EditDefaultsOnly, Category="BH|Entity")
float DespawnTime = 0.2f;
FVector LerpStartPosition = FVector::ZeroVector;
FVector LerpTargetPosition = FVector::ZeroVector;
float TargetScale = 1.f;
public:
uint32 EntityId = 0;
virtual void Tick(float DeltaTime) override;
void ConsumeDespawn(float DeltaTime);
void Spawn(uint32 InEntityId);
virtual void OnEntityUpdated(const FEntityType& NewVal);
virtual void OnDelete(const FEventContext& Context);
bool ConsumeDelete(const FEventContext& Context);
void SetColor(const FLinearColor& Color) const;
static float MassToRadius(uint32 Mass) { return FMath::Sqrt(static_cast<float>(Mass)); }
static float MassToDiameter(uint32 Mass) { return MassToRadius(Mass) * 2.f; }
private:
UPROPERTY()
TObjectPtr<AEntity> ConsumingEntity = nullptr;
bool bIsDespawning = false;
float DespawnElapsed = 0.f;
FVector ConsumeStartPosition = FVector::ZeroVector;
FVector ConsumeStartScale = FVector::ZeroVector;
};
@@ -0,0 +1,20 @@
#pragma once
#include "CoreMinimal.h"
#include "Entity.h"
#include "Food.generated.h"
struct FFoodType;
UCLASS()
class CLIENT_UNREAL_API AFood : public AEntity
{
GENERATED_BODY()
public:
AFood();
void Spawn(const FFoodType& FoodEntity);
protected:
UPROPERTY(EditDefaultsOnly, Category="BH|Food")
TArray<FLinearColor> ColorPalette;
};
@@ -0,0 +1,126 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ModuleBindings/SpacetimeDBClient.g.h"
#include "GameManager.generated.h"
class UDbConnection;
class AEntity;
class ACircle;
class AFood;
class APlayerPawn;
UCLASS()
class CLIENT_UNREAL_API AGameManager : public AActor
{
GENERATED_BODY()
public:
AGameManager();
static AGameManager* Instance;
UPROPERTY(EditAnywhere, Category="BH|Connection")
FString ServerUri = TEXT("127.0.0.1:3000");
UPROPERTY(EditAnywhere, Category="BH|Connection")
FString ModuleName = TEXT("blackholio-unreal");
UPROPERTY(EditAnywhere, Category="BH|Connection")
FString TokenFilePath = TEXT(".spacetime_blackholio");
UPROPERTY(EditAnywhere, Category="BH|Classes")
TSubclassOf<ACircle> CircleClass;
UPROPERTY(EditAnywhere, Category="BH|Classes")
TSubclassOf<AFood> FoodClass;
UPROPERTY(EditAnywhere, Category="BH|Classes")
TSubclassOf<APlayerPawn> PlayerClass;
UPROPERTY(BlueprintReadOnly, Category="BH|Connection")
FSpacetimeDBIdentity LocalIdentity;
UPROPERTY(BlueprintReadOnly, Category="BH|Connection")
UDbConnection* Conn = nullptr;
UPROPERTY()
FString PlayerNameAtStart = TEXT("");
UPROPERTY()
bool bSubscriptionsApplied = false;
UFUNCTION(BlueprintPure, Category="BH|Connection")
bool IsConnected() const
{
return Conn != nullptr && Conn->IsActive();
}
UFUNCTION(BlueprintCallable, Category="BH|Connection")
void Disconnect()
{
if (Conn != nullptr)
{
Conn->Disconnect();
Conn = nullptr;
}
}
UFUNCTION()
AEntity* GetEntity(uint32 EntityId) const;
UFUNCTION()
TMap<uint32, TWeakObjectPtr<APlayerPawn>> GetPlayerMap() const { return PlayerMap; };
protected:
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
public:
virtual void Tick(float DeltaTime) override;
private:
UFUNCTION()
void HandleConnect(UDbConnection* InConn, FSpacetimeDBIdentity Identity, const FString& Token);
UFUNCTION()
void HandleConnectError(const FString& Error);
UFUNCTION()
void HandleDisconnect(UDbConnection* InConn, const FString& Error);
UFUNCTION()
void HandleSubscriptionApplied(FSubscriptionEventContext& Context);
/* Border */
UFUNCTION()
void SetupArena(uint64 WorldSizeMeters);
UFUNCTION()
void CreateBorderCube(const FVector2f Position, const FVector2f Size) const;
UPROPERTY(VisibleAnywhere, Category="Arena")
UInstancedStaticMeshComponent* BorderISM;
UPROPERTY(EditDefaultsOnly, Category="Arena", meta=(ClampMin="1.0"))
float BorderThickness = 50.0f;
UPROPERTY(EditDefaultsOnly, Category="Arena", meta=(ClampMin="1.0"))
float BorderHeight = 100.0f;
UPROPERTY(EditDefaultsOnly, Category="Arena")
UMaterialInterface* BorderMaterial = nullptr;
UPROPERTY(EditDefaultsOnly, Category="Arena")
UStaticMesh* CubeMesh = nullptr; // defaults as /Engine/BasicShapes/Cube.Cube
/* Border */
/* Data Bindings */
UPROPERTY()
TMap<uint32, TWeakObjectPtr<AEntity>> EntityMap;
UPROPERTY()
TMap<uint32, TWeakObjectPtr<APlayerPawn>> PlayerMap;
APlayerPawn* SpawnOrGetPlayer(const FPlayerType& PlayerRow);
ACircle* SpawnCircle(const FCircleType& CircleRow);
AFood* SpawnFood(const FFoodType& Food);
UFUNCTION()
void OnCircleInsert(const FEventContext& Context, const FCircleType& NewRow);
UFUNCTION()
void OnEntityUpdate(const FEventContext& Context, const FEntityType& OldRow, const FEntityType& NewRow);
UFUNCTION()
void OnEntityDelete(const FEventContext& Context, const FEntityType& RemovedRow);
UFUNCTION()
void OnFoodInsert(const FEventContext& Context, const FFoodType& NewFood);
UFUNCTION()
void OnPlayerInsert(const FEventContext& Context, const FPlayerType& NewRow);
UFUNCTION()
void OnPlayerDelete(const FEventContext& Context, const FPlayerType& RemovedRow);
/* Data Bindings */
};
@@ -0,0 +1,23 @@
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "LeaderboardRowWidget.generated.h"
class UTextBlock;
UCLASS()
class CLIENT_UNREAL_API ULeaderboardRowWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SetData(const FString& Username, int32 Mass);
protected:
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> UsernameText = nullptr;
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> MassText = nullptr;
};
@@ -0,0 +1,52 @@
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "LeaderboardWidget.generated.h"
class UVerticalBox;
class ULeaderboardRowWidget;
class APlayerPawn;
USTRUCT()
struct FLeaderboardEntry
{
GENERATED_BODY()
UPROPERTY() FString Username;
UPROPERTY() int32 Mass = 0;
UPROPERTY() TWeakObjectPtr<APlayerPawn> Pawn;
};
UCLASS()
class CLIENT_UNREAL_API ULeaderboardWidget : public UUserWidget
{
GENERATED_BODY()
public:
virtual void NativeConstruct() override;
virtual void NativeDestruct() override;
protected:
UPROPERTY(meta=(BindWidget))
UVerticalBox* Root = nullptr;
UPROPERTY(EditDefaultsOnly, Category="BH|Leaderboard")
TSubclassOf<ULeaderboardRowWidget> RowClass;
UPROPERTY(EditDefaultsOnly, Category="BH|Leaderboard")
int32 MaxRowCount = 10;
UPROPERTY(EditDefaultsOnly, Category="BH|Leaderboard")
float UpdatePeriod = 0.25f;
private:
UPROPERTY(Transient)
TArray<ULeaderboardRowWidget*> Rows;
FTimerHandle UpdateTimer;
void BuildRowPool();
void CollectPlayers(TArray<FLeaderboardEntry>& Out) const;
void UpdateLeaderboard();
};
@@ -0,0 +1,23 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ParallaxBackground.generated.h"
class UPaperSpriteComponent;
UCLASS()
class CLIENT_UNREAL_API AParallaxBackground : public AActor
{
GENERATED_BODY()
public:
AParallaxBackground();
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere, Category="BH|Parallax")
float Multiplier = -0.02f;
UPROPERTY(EditAnywhere, Category="BH|Parallax")
float FixedY;
};
@@ -0,0 +1,22 @@
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "RespawnWidget.generated.h"
class UButton;
UCLASS()
class CLIENT_UNREAL_API URespawnWidget : public UUserWidget
{
GENERATED_BODY()
protected:
UPROPERTY(meta=(BindWidget))
TObjectPtr<UButton> RespawnButton;
virtual void NativeConstruct() override;
private:
UFUNCTION()
void OnRespawnPressed();
};
@@ -0,0 +1,32 @@
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "UsernameChooserWidget.generated.h"
class UEditableTextBox;
class UButton;
UCLASS()
class CLIENT_UNREAL_API UUsernameChooserWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION()
void Hide();
protected:
UPROPERTY(meta=(BindWidget))
TObjectPtr<UEditableTextBox> UsernameInputField;
UPROPERTY(meta=(BindWidget))
TObjectPtr<UButton> PlayButton;
virtual void NativeConstruct() override;
virtual void NativeDestruct() override;
private:
UFUNCTION()
void OnPlayPressed();
UFUNCTION()
void HandlePlayerInserted(const FEventContext& Context, const FPlayerType& NewPlayer);
};
@@ -0,0 +1,18 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ReducerBase.g.generated.h"
// Abstract Reducer base class
UCLASS(Abstract, BlueprintType)
class CLIENT_UNREAL_API UReducerBase : public UObject
{
GENERATED_BODY()
public:
virtual ~UReducerBase() = default;
};
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "ModuleBindings/Types/CircleDecayTimerType.g.h"
#include "CircleDecay.g.generated.h"
// Reducer arguments struct for CircleDecay
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FCircleDecayArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FCircleDecayTimerType Timer;
FCircleDecayArgs() = default;
FCircleDecayArgs(const FCircleDecayTimerType& InTimer)
: Timer(InTimer)
{}
FORCEINLINE bool operator==(const FCircleDecayArgs& Other) const
{
return Timer == Other.Timer;
}
FORCEINLINE bool operator!=(const FCircleDecayArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FCircleDecayArgs, Timer);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UCircleDecayReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FCircleDecayTimerType Timer;
};
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "ModuleBindings/Types/CircleRecombineTimerType.g.h"
#include "CircleRecombine.g.generated.h"
// Reducer arguments struct for CircleRecombine
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FCircleRecombineArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FCircleRecombineTimerType Timer;
FCircleRecombineArgs() = default;
FCircleRecombineArgs(const FCircleRecombineTimerType& InTimer)
: Timer(InTimer)
{}
FORCEINLINE bool operator==(const FCircleRecombineArgs& Other) const
{
return Timer == Other.Timer;
}
FORCEINLINE bool operator!=(const FCircleRecombineArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FCircleRecombineArgs, Timer);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UCircleRecombineReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FCircleRecombineTimerType Timer;
};
@@ -0,0 +1,43 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "Connect.g.generated.h"
// Reducer arguments struct for Connect
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FConnectArgs
{
GENERATED_BODY()
FConnectArgs() = default;
FORCEINLINE bool operator==(const FConnectArgs& Other) const
{
return true;
}
FORCEINLINE bool operator!=(const FConnectArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT_EMPTY(FConnectArgs);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UConnectReducer : public UReducerBase
{
GENERATED_BODY()
public:
};
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "ModuleBindings/Types/ConsumeEntityTimerType.g.h"
#include "ConsumeEntity.g.generated.h"
// Reducer arguments struct for ConsumeEntity
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FConsumeEntityArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FConsumeEntityTimerType Request;
FConsumeEntityArgs() = default;
FConsumeEntityArgs(const FConsumeEntityTimerType& InRequest)
: Request(InRequest)
{}
FORCEINLINE bool operator==(const FConsumeEntityArgs& Other) const
{
return Request == Other.Request;
}
FORCEINLINE bool operator!=(const FConsumeEntityArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FConsumeEntityArgs, Request);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UConsumeEntityReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FConsumeEntityTimerType Request;
};
@@ -0,0 +1,43 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "Disconnect.g.generated.h"
// Reducer arguments struct for Disconnect
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FDisconnectArgs
{
GENERATED_BODY()
FDisconnectArgs() = default;
FORCEINLINE bool operator==(const FDisconnectArgs& Other) const
{
return true;
}
FORCEINLINE bool operator!=(const FDisconnectArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT_EMPTY(FDisconnectArgs);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UDisconnectReducer : public UReducerBase
{
GENERATED_BODY()
public:
};
@@ -0,0 +1,53 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "EnterGame.g.generated.h"
// Reducer arguments struct for EnterGame
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FEnterGameArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FString Name;
FEnterGameArgs() = default;
FEnterGameArgs(const FString& InName)
: Name(InName)
{}
FORCEINLINE bool operator==(const FEnterGameArgs& Other) const
{
return Name == Other.Name;
}
FORCEINLINE bool operator!=(const FEnterGameArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FEnterGameArgs, Name);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UEnterGameReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FString Name;
};
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "ModuleBindings/Types/MoveAllPlayersTimerType.g.h"
#include "MoveAllPlayers.g.generated.h"
// Reducer arguments struct for MoveAllPlayers
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FMoveAllPlayersArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FMoveAllPlayersTimerType Timer;
FMoveAllPlayersArgs() = default;
FMoveAllPlayersArgs(const FMoveAllPlayersTimerType& InTimer)
: Timer(InTimer)
{}
FORCEINLINE bool operator==(const FMoveAllPlayersArgs& Other) const
{
return Timer == Other.Timer;
}
FORCEINLINE bool operator!=(const FMoveAllPlayersArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FMoveAllPlayersArgs, Timer);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UMoveAllPlayersReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FMoveAllPlayersTimerType Timer;
};
@@ -0,0 +1,43 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "PlayerSplit.g.generated.h"
// Reducer arguments struct for PlayerSplit
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FPlayerSplitArgs
{
GENERATED_BODY()
FPlayerSplitArgs() = default;
FORCEINLINE bool operator==(const FPlayerSplitArgs& Other) const
{
return true;
}
FORCEINLINE bool operator!=(const FPlayerSplitArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT_EMPTY(FPlayerSplitArgs);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UPlayerSplitReducer : public UReducerBase
{
GENERATED_BODY()
public:
};
@@ -0,0 +1,43 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "Respawn.g.generated.h"
// Reducer arguments struct for Respawn
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FRespawnArgs
{
GENERATED_BODY()
FRespawnArgs() = default;
FORCEINLINE bool operator==(const FRespawnArgs& Other) const
{
return true;
}
FORCEINLINE bool operator!=(const FRespawnArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT_EMPTY(FRespawnArgs);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API URespawnReducer : public UReducerBase
{
GENERATED_BODY()
public:
};
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "ModuleBindings/Types/SpawnFoodTimerType.g.h"
#include "SpawnFood.g.generated.h"
// Reducer arguments struct for SpawnFood
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FSpawnFoodArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FSpawnFoodTimerType Timer;
FSpawnFoodArgs() = default;
FSpawnFoodArgs(const FSpawnFoodTimerType& InTimer)
: Timer(InTimer)
{}
FORCEINLINE bool operator==(const FSpawnFoodArgs& Other) const
{
return Timer == Other.Timer;
}
FORCEINLINE bool operator!=(const FSpawnFoodArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FSpawnFoodArgs, Timer);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API USpawnFoodReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FSpawnFoodTimerType Timer;
};
@@ -0,0 +1,43 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "Suicide.g.generated.h"
// Reducer arguments struct for Suicide
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FSuicideArgs
{
GENERATED_BODY()
FSuicideArgs() = default;
FORCEINLINE bool operator==(const FSuicideArgs& Other) const
{
return true;
}
FORCEINLINE bool operator!=(const FSuicideArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT_EMPTY(FSuicideArgs);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API USuicideReducer : public UReducerBase
{
GENERATED_BODY()
public:
};
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/ReducerBase.g.h"
#include "ModuleBindings/Types/DbVector2Type.g.h"
#include "UpdatePlayerInput.g.generated.h"
// Reducer arguments struct for UpdatePlayerInput
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FUpdatePlayerInputArgs
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="SpacetimeDB")
FDbVector2Type Direction;
FUpdatePlayerInputArgs() = default;
FUpdatePlayerInputArgs(const FDbVector2Type& InDirection)
: Direction(InDirection)
{}
FORCEINLINE bool operator==(const FUpdatePlayerInputArgs& Other) const
{
return Direction == Other.Direction;
}
FORCEINLINE bool operator!=(const FUpdatePlayerInputArgs& Other) const
{
return !(*this == Other);
}
};
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_STRUCT(FUpdatePlayerInputArgs, Direction);
}
// Reducer class for internal dispatching
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UUpdatePlayerInputReducer : public UReducerBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
FDbVector2Type Direction;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/CircleDecayTimerType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "CircleDecayTimerTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UCircleDecayTimerScheduledIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FCircleDecayTimerType, uint64, FTableCache<FCircleDecayTimerType>> ScheduledIdIndexHelper;
public:
UCircleDecayTimerScheduledIdUniqueIndex()
// Initialize the helper with the specific unique index name
: ScheduledIdIndexHelper("scheduled_id") {
}
/**
* Finds a CircleDecayTimer by their unique scheduledid.
* @param Key The scheduledid to search for.
* @return The found FCircleDecayTimerType, or a default-constructed FCircleDecayTimerType if not found.
*/
// NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible
FCircleDecayTimerType Find(uint64 Key)
{
// Simply delegate the call to the internal helper
return ScheduledIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FCircleDecayTimerType>> InCircleDecayTimerCache)
{
ScheduledIdIndexHelper.Cache = InCircleDecayTimerCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UCircleDecayTimerTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UCircleDecayTimerScheduledIdUniqueIndex* ScheduledId;
void PostInitialize();
/** Update function for circle_decay_timer table*/
FTableAppliedDiff<FCircleDecayTimerType> Update(TArray<FWithBsatn<FCircleDecayTimerType>> InsertsRef, TArray<FWithBsatn<FCircleDecayTimerType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FCircleDecayTimerType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnCircleDecayTimerInsert,
const FEventContext&, Context,
const FCircleDecayTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnCircleDecayTimerUpdate,
const FEventContext&, Context,
const FCircleDecayTimerType&, OldRow,
const FCircleDecayTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnCircleDecayTimerDelete,
const FEventContext&, Context,
const FCircleDecayTimerType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleDecayTimerInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleDecayTimerUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleDecayTimerDelete OnDelete;
private:
const FString TableName = TEXT("circle_decay_timer");
TSharedPtr<UClientCache<FCircleDecayTimerType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/CircleRecombineTimerType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "CircleRecombineTimerTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UCircleRecombineTimerScheduledIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FCircleRecombineTimerType, uint64, FTableCache<FCircleRecombineTimerType>> ScheduledIdIndexHelper;
public:
UCircleRecombineTimerScheduledIdUniqueIndex()
// Initialize the helper with the specific unique index name
: ScheduledIdIndexHelper("scheduled_id") {
}
/**
* Finds a CircleRecombineTimer by their unique scheduledid.
* @param Key The scheduledid to search for.
* @return The found FCircleRecombineTimerType, or a default-constructed FCircleRecombineTimerType if not found.
*/
// NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible
FCircleRecombineTimerType Find(uint64 Key)
{
// Simply delegate the call to the internal helper
return ScheduledIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FCircleRecombineTimerType>> InCircleRecombineTimerCache)
{
ScheduledIdIndexHelper.Cache = InCircleRecombineTimerCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UCircleRecombineTimerTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UCircleRecombineTimerScheduledIdUniqueIndex* ScheduledId;
void PostInitialize();
/** Update function for circle_recombine_timer table*/
FTableAppliedDiff<FCircleRecombineTimerType> Update(TArray<FWithBsatn<FCircleRecombineTimerType>> InsertsRef, TArray<FWithBsatn<FCircleRecombineTimerType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FCircleRecombineTimerType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnCircleRecombineTimerInsert,
const FEventContext&, Context,
const FCircleRecombineTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnCircleRecombineTimerUpdate,
const FEventContext&, Context,
const FCircleRecombineTimerType&, OldRow,
const FCircleRecombineTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnCircleRecombineTimerDelete,
const FEventContext&, Context,
const FCircleRecombineTimerType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleRecombineTimerInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleRecombineTimerUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleRecombineTimerDelete OnDelete;
private:
const FString TableName = TEXT("circle_recombine_timer");
TSharedPtr<UClientCache<FCircleRecombineTimerType>> Data;
};
@@ -0,0 +1,141 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/CircleType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "CircleTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UCircleEntityIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FCircleType, uint32, FTableCache<FCircleType>> EntityIdIndexHelper;
public:
UCircleEntityIdUniqueIndex()
// Initialize the helper with the specific unique index name
: EntityIdIndexHelper("entity_id") {
}
/**
* Finds a Circle by their unique entityid.
* @param Key The entityid to search for.
* @return The found FCircleType, or a default-constructed FCircleType if not found.
*/
// NOTE: Not exposed to Blueprint because uint32 types are not Blueprint-compatible
FCircleType Find(uint32 Key)
{
// Simply delegate the call to the internal helper
return EntityIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FCircleType>> InCircleCache)
{
EntityIdIndexHelper.Cache = InCircleCache;
}
};
/***/
UCLASS(Blueprintable)
class UCirclePlayerIdIndex : public UObject
{
GENERATED_BODY()
public:
TArray<FCircleType> Filter(const uint32& PlayerId) const
{
TArray<FCircleType> OutResults;
LocalCache->FindByMultiKeyBTreeIndex<TTuple<uint32>>(
OutResults,
TEXT("player_id"),
MakeTuple(PlayerId)
);
return OutResults;
}
void SetCache(TSharedPtr<FTableCache<FCircleType>> InCache)
{
LocalCache = InCache;
}
private:
// NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible
void FilterPlayerId(TArray<FCircleType>& OutResults, const uint32& PlayerId)
{
OutResults = Filter(PlayerId);
}
TSharedPtr<FTableCache<FCircleType>> LocalCache;
};
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UCircleTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UCircleEntityIdUniqueIndex* EntityId;
UPROPERTY(BlueprintReadOnly)
UCirclePlayerIdIndex* PlayerId;
void PostInitialize();
/** Update function for circle table*/
FTableAppliedDiff<FCircleType> Update(TArray<FWithBsatn<FCircleType>> InsertsRef, TArray<FWithBsatn<FCircleType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FCircleType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnCircleInsert,
const FEventContext&, Context,
const FCircleType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnCircleUpdate,
const FEventContext&, Context,
const FCircleType&, OldRow,
const FCircleType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnCircleDelete,
const FEventContext&, Context,
const FCircleType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnCircleDelete OnDelete;
private:
const FString TableName = TEXT("circle");
TSharedPtr<UClientCache<FCircleType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/ConfigType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "ConfigTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UConfigIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FConfigType, uint32, FTableCache<FConfigType>> IdIndexHelper;
public:
UConfigIdUniqueIndex()
// Initialize the helper with the specific unique index name
: IdIndexHelper("id") {
}
/**
* Finds a Config by their unique id.
* @param Key The id to search for.
* @return The found FConfigType, or a default-constructed FConfigType if not found.
*/
// NOTE: Not exposed to Blueprint because uint32 types are not Blueprint-compatible
FConfigType Find(uint32 Key)
{
// Simply delegate the call to the internal helper
return IdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FConfigType>> InConfigCache)
{
IdIndexHelper.Cache = InConfigCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UConfigTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UConfigIdUniqueIndex* Id;
void PostInitialize();
/** Update function for config table*/
FTableAppliedDiff<FConfigType> Update(TArray<FWithBsatn<FConfigType>> InsertsRef, TArray<FWithBsatn<FConfigType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FConfigType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnConfigInsert,
const FEventContext&, Context,
const FConfigType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnConfigUpdate,
const FEventContext&, Context,
const FConfigType&, OldRow,
const FConfigType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnConfigDelete,
const FEventContext&, Context,
const FConfigType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnConfigInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnConfigUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnConfigDelete OnDelete;
private:
const FString TableName = TEXT("config");
TSharedPtr<UClientCache<FConfigType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/ConsumeEntityTimerType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "ConsumeEntityTimerTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UConsumeEntityTimerScheduledIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FConsumeEntityTimerType, uint64, FTableCache<FConsumeEntityTimerType>> ScheduledIdIndexHelper;
public:
UConsumeEntityTimerScheduledIdUniqueIndex()
// Initialize the helper with the specific unique index name
: ScheduledIdIndexHelper("scheduled_id") {
}
/**
* Finds a ConsumeEntityTimer by their unique scheduledid.
* @param Key The scheduledid to search for.
* @return The found FConsumeEntityTimerType, or a default-constructed FConsumeEntityTimerType if not found.
*/
// NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible
FConsumeEntityTimerType Find(uint64 Key)
{
// Simply delegate the call to the internal helper
return ScheduledIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FConsumeEntityTimerType>> InConsumeEntityTimerCache)
{
ScheduledIdIndexHelper.Cache = InConsumeEntityTimerCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UConsumeEntityTimerTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UConsumeEntityTimerScheduledIdUniqueIndex* ScheduledId;
void PostInitialize();
/** Update function for consume_entity_timer table*/
FTableAppliedDiff<FConsumeEntityTimerType> Update(TArray<FWithBsatn<FConsumeEntityTimerType>> InsertsRef, TArray<FWithBsatn<FConsumeEntityTimerType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FConsumeEntityTimerType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnConsumeEntityTimerInsert,
const FEventContext&, Context,
const FConsumeEntityTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnConsumeEntityTimerUpdate,
const FEventContext&, Context,
const FConsumeEntityTimerType&, OldRow,
const FConsumeEntityTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnConsumeEntityTimerDelete,
const FEventContext&, Context,
const FConsumeEntityTimerType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnConsumeEntityTimerInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnConsumeEntityTimerUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnConsumeEntityTimerDelete OnDelete;
private:
const FString TableName = TEXT("consume_entity_timer");
TSharedPtr<UClientCache<FConsumeEntityTimerType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/EntityType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "EntityTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UEntityEntityIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FEntityType, uint32, FTableCache<FEntityType>> EntityIdIndexHelper;
public:
UEntityEntityIdUniqueIndex()
// Initialize the helper with the specific unique index name
: EntityIdIndexHelper("entity_id") {
}
/**
* Finds a Entity by their unique entityid.
* @param Key The entityid to search for.
* @return The found FEntityType, or a default-constructed FEntityType if not found.
*/
// NOTE: Not exposed to Blueprint because uint32 types are not Blueprint-compatible
FEntityType Find(uint32 Key)
{
// Simply delegate the call to the internal helper
return EntityIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FEntityType>> InEntityCache)
{
EntityIdIndexHelper.Cache = InEntityCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UEntityTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UEntityEntityIdUniqueIndex* EntityId;
void PostInitialize();
/** Update function for entity table*/
FTableAppliedDiff<FEntityType> Update(TArray<FWithBsatn<FEntityType>> InsertsRef, TArray<FWithBsatn<FEntityType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FEntityType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnEntityInsert,
const FEventContext&, Context,
const FEntityType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnEntityUpdate,
const FEventContext&, Context,
const FEntityType&, OldRow,
const FEntityType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnEntityDelete,
const FEventContext&, Context,
const FEntityType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnEntityInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnEntityUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnEntityDelete OnDelete;
private:
const FString TableName = TEXT("entity");
TSharedPtr<UClientCache<FEntityType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/FoodType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "FoodTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UFoodEntityIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FFoodType, uint32, FTableCache<FFoodType>> EntityIdIndexHelper;
public:
UFoodEntityIdUniqueIndex()
// Initialize the helper with the specific unique index name
: EntityIdIndexHelper("entity_id") {
}
/**
* Finds a Food by their unique entityid.
* @param Key The entityid to search for.
* @return The found FFoodType, or a default-constructed FFoodType if not found.
*/
// NOTE: Not exposed to Blueprint because uint32 types are not Blueprint-compatible
FFoodType Find(uint32 Key)
{
// Simply delegate the call to the internal helper
return EntityIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FFoodType>> InFoodCache)
{
EntityIdIndexHelper.Cache = InFoodCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UFoodTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UFoodEntityIdUniqueIndex* EntityId;
void PostInitialize();
/** Update function for food table*/
FTableAppliedDiff<FFoodType> Update(TArray<FWithBsatn<FFoodType>> InsertsRef, TArray<FWithBsatn<FFoodType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FFoodType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnFoodInsert,
const FEventContext&, Context,
const FFoodType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnFoodUpdate,
const FEventContext&, Context,
const FFoodType&, OldRow,
const FFoodType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnFoodDelete,
const FEventContext&, Context,
const FFoodType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnFoodInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnFoodUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnFoodDelete OnDelete;
private:
const FString TableName = TEXT("food");
TSharedPtr<UClientCache<FFoodType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/MoveAllPlayersTimerType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "MoveAllPlayersTimerTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UMoveAllPlayersTimerScheduledIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FMoveAllPlayersTimerType, uint64, FTableCache<FMoveAllPlayersTimerType>> ScheduledIdIndexHelper;
public:
UMoveAllPlayersTimerScheduledIdUniqueIndex()
// Initialize the helper with the specific unique index name
: ScheduledIdIndexHelper("scheduled_id") {
}
/**
* Finds a MoveAllPlayersTimer by their unique scheduledid.
* @param Key The scheduledid to search for.
* @return The found FMoveAllPlayersTimerType, or a default-constructed FMoveAllPlayersTimerType if not found.
*/
// NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible
FMoveAllPlayersTimerType Find(uint64 Key)
{
// Simply delegate the call to the internal helper
return ScheduledIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FMoveAllPlayersTimerType>> InMoveAllPlayersTimerCache)
{
ScheduledIdIndexHelper.Cache = InMoveAllPlayersTimerCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UMoveAllPlayersTimerTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UMoveAllPlayersTimerScheduledIdUniqueIndex* ScheduledId;
void PostInitialize();
/** Update function for move_all_players_timer table*/
FTableAppliedDiff<FMoveAllPlayersTimerType> Update(TArray<FWithBsatn<FMoveAllPlayersTimerType>> InsertsRef, TArray<FWithBsatn<FMoveAllPlayersTimerType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FMoveAllPlayersTimerType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnMoveAllPlayersTimerInsert,
const FEventContext&, Context,
const FMoveAllPlayersTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnMoveAllPlayersTimerUpdate,
const FEventContext&, Context,
const FMoveAllPlayersTimerType&, OldRow,
const FMoveAllPlayersTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnMoveAllPlayersTimerDelete,
const FEventContext&, Context,
const FMoveAllPlayersTimerType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnMoveAllPlayersTimerInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnMoveAllPlayersTimerUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnMoveAllPlayersTimerDelete OnDelete;
private:
const FString TableName = TEXT("move_all_players_timer");
TSharedPtr<UClientCache<FMoveAllPlayersTimerType>> Data;
};
@@ -0,0 +1,144 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/PlayerType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "PlayerTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UPlayerIdentityUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FPlayerType, FSpacetimeDBIdentity, FTableCache<FPlayerType>> IdentityIndexHelper;
public:
UPlayerIdentityUniqueIndex()
// Initialize the helper with the specific unique index name
: IdentityIndexHelper("identity") {
}
/**
* Finds a Player by their unique identity.
* @param Key The identity to search for.
* @return The found FPlayerType, or a default-constructed FPlayerType if not found.
*/
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|PlayerIndex")
FPlayerType Find(FSpacetimeDBIdentity Key)
{
// Simply delegate the call to the internal helper
return IdentityIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FPlayerType>> InPlayerCache)
{
IdentityIndexHelper.Cache = InPlayerCache;
}
};
/***/
UCLASS(Blueprintable)
class CLIENT_UNREAL_API UPlayerPlayerIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FPlayerType, uint32, FTableCache<FPlayerType>> PlayerIdIndexHelper;
public:
UPlayerPlayerIdUniqueIndex()
// Initialize the helper with the specific unique index name
: PlayerIdIndexHelper("player_id") {
}
/**
* Finds a Player by their unique playerid.
* @param Key The playerid to search for.
* @return The found FPlayerType, or a default-constructed FPlayerType if not found.
*/
// NOTE: Not exposed to Blueprint because uint32 types are not Blueprint-compatible
FPlayerType Find(uint32 Key)
{
// Simply delegate the call to the internal helper
return PlayerIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FPlayerType>> InPlayerCache)
{
PlayerIdIndexHelper.Cache = InPlayerCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API UPlayerTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
UPlayerIdentityUniqueIndex* Identity;
UPROPERTY(BlueprintReadOnly)
UPlayerPlayerIdUniqueIndex* PlayerId;
void PostInitialize();
/** Update function for player table*/
FTableAppliedDiff<FPlayerType> Update(TArray<FWithBsatn<FPlayerType>> InsertsRef, TArray<FWithBsatn<FPlayerType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FPlayerType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnPlayerInsert,
const FEventContext&, Context,
const FPlayerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnPlayerUpdate,
const FEventContext&, Context,
const FPlayerType&, OldRow,
const FPlayerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnPlayerDelete,
const FEventContext&, Context,
const FPlayerType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnPlayerInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnPlayerUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnPlayerDelete OnDelete;
private:
const FString TableName = TEXT("player");
TSharedPtr<UClientCache<FPlayerType>> Data;
};
@@ -0,0 +1,104 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ModuleBindings/Types/SpawnFoodTimerType.g.h"
#include "Tables/RemoteTable.h"
#include "DBCache/WithBsatn.h"
#include "DBCache/TableHandle.h"
#include "DBCache/TableCache.h"
#include "SpawnFoodTimerTable.g.generated.h"
UCLASS(Blueprintable)
class CLIENT_UNREAL_API USpawnFoodTimerScheduledIdUniqueIndex : public UObject
{
GENERATED_BODY()
private:
// Declare an instance of your templated helper.
// It's private because the UObject wrapper will expose its functionality.
FUniqueIndexHelper<FSpawnFoodTimerType, uint64, FTableCache<FSpawnFoodTimerType>> ScheduledIdIndexHelper;
public:
USpawnFoodTimerScheduledIdUniqueIndex()
// Initialize the helper with the specific unique index name
: ScheduledIdIndexHelper("scheduled_id") {
}
/**
* Finds a SpawnFoodTimer by their unique scheduledid.
* @param Key The scheduledid to search for.
* @return The found FSpawnFoodTimerType, or a default-constructed FSpawnFoodTimerType if not found.
*/
// NOTE: Not exposed to Blueprint because uint64 types are not Blueprint-compatible
FSpawnFoodTimerType Find(uint64 Key)
{
// Simply delegate the call to the internal helper
return ScheduledIdIndexHelper.FindUniqueIndex(Key);
}
// A public setter to provide the cache to the helper after construction
// This is a common pattern when the cache might be created or provided by another system.
void SetCache(TSharedPtr<const FTableCache<FSpawnFoodTimerType>> InSpawnFoodTimerCache)
{
ScheduledIdIndexHelper.Cache = InSpawnFoodTimerCache;
}
};
/***/
UCLASS(BlueprintType)
class CLIENT_UNREAL_API USpawnFoodTimerTable : public URemoteTable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
USpawnFoodTimerScheduledIdUniqueIndex* ScheduledId;
void PostInitialize();
/** Update function for spawn_food_timer table*/
FTableAppliedDiff<FSpawnFoodTimerType> Update(TArray<FWithBsatn<FSpawnFoodTimerType>> InsertsRef, TArray<FWithBsatn<FSpawnFoodTimerType>> DeletesRef);
/** Number of subscribed rows currently in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
int32 Count() const;
/** Return all subscribed rows in the cache */
UFUNCTION(BlueprintCallable, Category = "SpacetimeDB")
TArray<FSpawnFoodTimerType> Iter() const;
// Table Events
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnSpawnFoodTimerInsert,
const FEventContext&, Context,
const FSpawnFoodTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
FOnSpawnFoodTimerUpdate,
const FEventContext&, Context,
const FSpawnFoodTimerType&, OldRow,
const FSpawnFoodTimerType&, NewRow);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnSpawnFoodTimerDelete,
const FEventContext&, Context,
const FSpawnFoodTimerType&, DeletedRow);
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnSpawnFoodTimerInsert OnInsert;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnSpawnFoodTimerUpdate OnUpdate;
UPROPERTY(BlueprintAssignable, Category = "SpacetimeDB Events")
FOnSpawnFoodTimerDelete OnDelete;
private:
const FString TableName = TEXT("spawn_food_timer");
TSharedPtr<UClientCache<FSpawnFoodTimerType>> Data;
};
@@ -0,0 +1,50 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "CircleDecayTimerType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FCircleDecayTimerType
{
GENERATED_BODY()
// NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements
uint64 ScheduledId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FSpacetimeDBScheduleAt ScheduledAt;
FORCEINLINE bool operator==(const FCircleDecayTimerType& Other) const
{
return ScheduledId == Other.ScheduledId && ScheduledAt == Other.ScheduledAt;
}
FORCEINLINE bool operator!=(const FCircleDecayTimerType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FCircleDecayTimerType.
* Combines the hashes of all fields that are compared in operator==.
* @param CircleDecayTimerType The FCircleDecayTimerType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FCircleDecayTimerType& CircleDecayTimerType)
{
uint32 Hash = GetTypeHash(CircleDecayTimerType.ScheduledId);
Hash = HashCombine(Hash, GetTypeHash(CircleDecayTimerType.ScheduledAt));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FCircleDecayTimerType);
UE_SPACETIMEDB_STRUCT(FCircleDecayTimerType, ScheduledId, ScheduledAt);
}
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "CircleRecombineTimerType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FCircleRecombineTimerType
{
GENERATED_BODY()
// NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements
uint64 ScheduledId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FSpacetimeDBScheduleAt ScheduledAt;
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 PlayerId;
FORCEINLINE bool operator==(const FCircleRecombineTimerType& Other) const
{
return ScheduledId == Other.ScheduledId && ScheduledAt == Other.ScheduledAt && PlayerId == Other.PlayerId;
}
FORCEINLINE bool operator!=(const FCircleRecombineTimerType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FCircleRecombineTimerType.
* Combines the hashes of all fields that are compared in operator==.
* @param CircleRecombineTimerType The FCircleRecombineTimerType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FCircleRecombineTimerType& CircleRecombineTimerType)
{
uint32 Hash = GetTypeHash(CircleRecombineTimerType.ScheduledId);
Hash = HashCombine(Hash, GetTypeHash(CircleRecombineTimerType.ScheduledAt));
Hash = HashCombine(Hash, GetTypeHash(CircleRecombineTimerType.PlayerId));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FCircleRecombineTimerType);
UE_SPACETIMEDB_STRUCT(FCircleRecombineTimerType, ScheduledId, ScheduledAt, PlayerId);
}
@@ -0,0 +1,63 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/Types/DbVector2Type.g.h"
#include "Types/Builtins.h"
#include "CircleType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FCircleType
{
GENERATED_BODY()
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 EntityId;
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 PlayerId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FDbVector2Type Direction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
float Speed;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FSpacetimeDBTimestamp LastSplitTime;
FORCEINLINE bool operator==(const FCircleType& Other) const
{
return EntityId == Other.EntityId && PlayerId == Other.PlayerId && Direction == Other.Direction && Speed == Other.Speed && LastSplitTime == Other.LastSplitTime;
}
FORCEINLINE bool operator!=(const FCircleType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FCircleType.
* Combines the hashes of all fields that are compared in operator==.
* @param CircleType The FCircleType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FCircleType& CircleType)
{
uint32 Hash = GetTypeHash(CircleType.EntityId);
Hash = HashCombine(Hash, GetTypeHash(CircleType.PlayerId));
Hash = HashCombine(Hash, GetTypeHash(CircleType.Direction));
Hash = HashCombine(Hash, GetTypeHash(CircleType.Speed));
Hash = HashCombine(Hash, GetTypeHash(CircleType.LastSplitTime));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FCircleType);
UE_SPACETIMEDB_STRUCT(FCircleType, EntityId, PlayerId, Direction, Speed, LastSplitTime);
}
@@ -0,0 +1,49 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ConfigType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FConfigType
{
GENERATED_BODY()
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 Id;
// NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements
uint64 WorldSize;
FORCEINLINE bool operator==(const FConfigType& Other) const
{
return Id == Other.Id && WorldSize == Other.WorldSize;
}
FORCEINLINE bool operator!=(const FConfigType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FConfigType.
* Combines the hashes of all fields that are compared in operator==.
* @param ConfigType The FConfigType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FConfigType& ConfigType)
{
uint32 Hash = GetTypeHash(ConfigType.Id);
Hash = HashCombine(Hash, GetTypeHash(ConfigType.WorldSize));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FConfigType);
UE_SPACETIMEDB_STRUCT(FConfigType, Id, WorldSize);
}
@@ -0,0 +1,58 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "ConsumeEntityTimerType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FConsumeEntityTimerType
{
GENERATED_BODY()
// NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements
uint64 ScheduledId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FSpacetimeDBScheduleAt ScheduledAt;
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 ConsumedEntityId;
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 ConsumerEntityId;
FORCEINLINE bool operator==(const FConsumeEntityTimerType& Other) const
{
return ScheduledId == Other.ScheduledId && ScheduledAt == Other.ScheduledAt && ConsumedEntityId == Other.ConsumedEntityId && ConsumerEntityId == Other.ConsumerEntityId;
}
FORCEINLINE bool operator!=(const FConsumeEntityTimerType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FConsumeEntityTimerType.
* Combines the hashes of all fields that are compared in operator==.
* @param ConsumeEntityTimerType The FConsumeEntityTimerType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FConsumeEntityTimerType& ConsumeEntityTimerType)
{
uint32 Hash = GetTypeHash(ConsumeEntityTimerType.ScheduledId);
Hash = HashCombine(Hash, GetTypeHash(ConsumeEntityTimerType.ScheduledAt));
Hash = HashCombine(Hash, GetTypeHash(ConsumeEntityTimerType.ConsumedEntityId));
Hash = HashCombine(Hash, GetTypeHash(ConsumeEntityTimerType.ConsumerEntityId));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FConsumeEntityTimerType);
UE_SPACETIMEDB_STRUCT(FConsumeEntityTimerType, ScheduledId, ScheduledAt, ConsumedEntityId, ConsumerEntityId);
}
@@ -0,0 +1,49 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "DbVector2Type.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FDbVector2Type
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
float X;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
float Y;
FORCEINLINE bool operator==(const FDbVector2Type& Other) const
{
return X == Other.X && Y == Other.Y;
}
FORCEINLINE bool operator!=(const FDbVector2Type& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FDbVector2Type.
* Combines the hashes of all fields that are compared in operator==.
* @param DbVector2Type The FDbVector2Type instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FDbVector2Type& DbVector2Type)
{
uint32 Hash = GetTypeHash(DbVector2Type.X);
Hash = HashCombine(Hash, GetTypeHash(DbVector2Type.Y));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FDbVector2Type);
UE_SPACETIMEDB_STRUCT(FDbVector2Type, X, Y);
}
@@ -0,0 +1,54 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "ModuleBindings/Types/DbVector2Type.g.h"
#include "EntityType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FEntityType
{
GENERATED_BODY()
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 EntityId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FDbVector2Type Position;
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 Mass;
FORCEINLINE bool operator==(const FEntityType& Other) const
{
return EntityId == Other.EntityId && Position == Other.Position && Mass == Other.Mass;
}
FORCEINLINE bool operator!=(const FEntityType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FEntityType.
* Combines the hashes of all fields that are compared in operator==.
* @param EntityType The FEntityType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FEntityType& EntityType)
{
uint32 Hash = GetTypeHash(EntityType.EntityId);
Hash = HashCombine(Hash, GetTypeHash(EntityType.Position));
Hash = HashCombine(Hash, GetTypeHash(EntityType.Mass));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FEntityType);
UE_SPACETIMEDB_STRUCT(FEntityType, EntityId, Position, Mass);
}
@@ -0,0 +1,45 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "FoodType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FFoodType
{
GENERATED_BODY()
// NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements
uint32 EntityId;
FORCEINLINE bool operator==(const FFoodType& Other) const
{
return EntityId == Other.EntityId;
}
FORCEINLINE bool operator!=(const FFoodType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FFoodType.
* Combines the hashes of all fields that are compared in operator==.
* @param FoodType The FFoodType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FFoodType& FoodType)
{
uint32 Hash = GetTypeHash(FoodType.EntityId);
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FFoodType);
UE_SPACETIMEDB_STRUCT(FFoodType, EntityId);
}
@@ -0,0 +1,50 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#pragma once
#include "CoreMinimal.h"
#include "BSATN/UESpacetimeDB.h"
#include "Types/Builtins.h"
#include "MoveAllPlayersTimerType.g.generated.h"
USTRUCT(BlueprintType)
struct CLIENT_UNREAL_API FMoveAllPlayersTimerType
{
GENERATED_BODY()
// NOTE: uint64 field not exposed to Blueprint due to non-blueprintable elements
uint64 ScheduledId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB")
FSpacetimeDBScheduleAt ScheduledAt;
FORCEINLINE bool operator==(const FMoveAllPlayersTimerType& Other) const
{
return ScheduledId == Other.ScheduledId && ScheduledAt == Other.ScheduledAt;
}
FORCEINLINE bool operator!=(const FMoveAllPlayersTimerType& Other) const
{
return !(*this == Other);
}
};
/**
* Custom hash function for FMoveAllPlayersTimerType.
* Combines the hashes of all fields that are compared in operator==.
* @param MoveAllPlayersTimerType The FMoveAllPlayersTimerType instance to hash.
* @return The combined hash value.
*/
FORCEINLINE uint32 GetTypeHash(const FMoveAllPlayersTimerType& MoveAllPlayersTimerType)
{
uint32 Hash = GetTypeHash(MoveAllPlayersTimerType.ScheduledId);
Hash = HashCombine(Hash, GetTypeHash(MoveAllPlayersTimerType.ScheduledAt));
return Hash;
}
namespace UE::SpacetimeDB
{
UE_SPACETIMEDB_ENABLE_TARRAY(FMoveAllPlayersTimerType);
UE_SPACETIMEDB_STRUCT(FMoveAllPlayersTimerType, ScheduledId, ScheduledAt);
}

Some files were not shown because too many files have changed in this diff Show More