diff --git a/demo/Blackholio/.gitignore b/demo/Blackholio/.gitignore index ffa6ae370..104ec592e 100644 --- a/demo/Blackholio/.gitignore +++ b/demo/Blackholio/.gitignore @@ -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 \ No newline at end of file diff --git a/demo/Blackholio/client-unreal/Config/DefaultEditor.ini b/demo/Blackholio/client-unreal/Config/DefaultEditor.ini new file mode 100644 index 000000000..e69de29bb diff --git a/demo/Blackholio/client-unreal/Config/DefaultEngine.ini b/demo/Blackholio/client-unreal/Config/DefaultEngine.ini new file mode 100644 index 000000000..edd23f942 --- /dev/null +++ b/demo/Blackholio/client-unreal/Config/DefaultEngine.ini @@ -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= + diff --git a/demo/Blackholio/client-unreal/Config/DefaultGame.ini b/demo/Blackholio/client-unreal/Config/DefaultGame.ini new file mode 100644 index 000000000..2e8bc0d95 --- /dev/null +++ b/demo/Blackholio/client-unreal/Config/DefaultGame.ini @@ -0,0 +1,6 @@ + +[/Script/CommonUI.CommonUISettings] +CommonButtonAcceptKeyHandling=TriggerClick + +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=1CB09ED64584D03E3ED8AA86458B2D83 diff --git a/demo/Blackholio/client-unreal/Config/DefaultInput.ini b/demo/Blackholio/client-unreal/Config/DefaultInput.ini new file mode 100644 index 000000000..a919105de --- /dev/null +++ b/demo/Blackholio/client-unreal/Config/DefaultInput.ini @@ -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 + diff --git a/demo/Blackholio/client-unreal/Content/BP_BlackholioGameMode.uasset b/demo/Blackholio/client-unreal/Content/BP_BlackholioGameMode.uasset new file mode 100644 index 000000000..0a1dfd117 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/BP_BlackholioGameMode.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/BP_Circle.uasset b/demo/Blackholio/client-unreal/Content/BP_Circle.uasset new file mode 100644 index 000000000..bc3cb9285 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/BP_Circle.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/BP_Food.uasset b/demo/Blackholio/client-unreal/Content/BP_Food.uasset new file mode 100644 index 000000000..8e9e591f8 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/BP_Food.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/BP_GameManager.uasset b/demo/Blackholio/client-unreal/Content/BP_GameManager.uasset new file mode 100644 index 000000000..cbf4de166 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/BP_GameManager.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/BP_PlayerController.uasset b/demo/Blackholio/client-unreal/Content/BP_PlayerController.uasset new file mode 100644 index 000000000..5b509f27f Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/BP_PlayerController.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/BP_PlayerPawn.uasset b/demo/Blackholio/client-unreal/Content/BP_PlayerPawn.uasset new file mode 100644 index 000000000..358b9a764 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/BP_PlayerPawn.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Blackholio.umap b/demo/Blackholio/client-unreal/Content/Blackholio.umap new file mode 100644 index 000000000..bb7bd7420 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Blackholio.umap differ diff --git a/demo/Blackholio/client-unreal/Content/Circle.uasset b/demo/Blackholio/client-unreal/Content/Circle.uasset new file mode 100644 index 000000000..607587dfe Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Circle.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Circle_Sprite.uasset b/demo/Blackholio/client-unreal/Content/Circle_Sprite.uasset new file mode 100644 index 000000000..53f4da29f Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Circle_Sprite.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/BP_ParallaxBackground.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/BP_ParallaxBackground.uasset new file mode 100644 index 000000000..1aba9dc83 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/BP_ParallaxBackground.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/StarBackground.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/StarBackground.uasset new file mode 100644 index 000000000..6f0fed52d Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/StarBackground.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/StarBackground_Sprite.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/StarBackground_Sprite.uasset new file mode 100644 index 000000000..723c5d81e Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/StarBackground_Sprite.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/WBP_Leaderboard.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_Leaderboard.uasset new file mode 100644 index 000000000..e4339e5ce Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_Leaderboard.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/WBP_LeaderboardRow.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_LeaderboardRow.uasset new file mode 100644 index 000000000..d5e76729a Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_LeaderboardRow.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/WBP_Respawn.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_Respawn.uasset new file mode 100644 index 000000000..dc3696172 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_Respawn.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Gameplay/WBP_UsernameChooser.uasset b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_UsernameChooser.uasset new file mode 100644 index 000000000..b3e68ddb5 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Gameplay/WBP_UsernameChooser.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Input/IA_InputLock.uasset b/demo/Blackholio/client-unreal/Content/Input/IA_InputLock.uasset new file mode 100644 index 000000000..e0295001c Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Input/IA_InputLock.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Input/IA_Split.uasset b/demo/Blackholio/client-unreal/Content/Input/IA_Split.uasset new file mode 100644 index 000000000..4f60d6c68 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Input/IA_Split.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Input/IA_Suicide.uasset b/demo/Blackholio/client-unreal/Content/Input/IA_Suicide.uasset new file mode 100644 index 000000000..7e3313c45 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Input/IA_Suicide.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/Input/IMC_Main.uasset b/demo/Blackholio/client-unreal/Content/Input/IMC_Main.uasset new file mode 100644 index 000000000..1a1ee806b Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/Input/IMC_Main.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/MFI_WavyOutline_Inst.uasset b/demo/Blackholio/client-unreal/Content/MFI_WavyOutline_Inst.uasset new file mode 100644 index 000000000..e14858f6a Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/MFI_WavyOutline_Inst.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/MF_WavyOutline.uasset b/demo/Blackholio/client-unreal/Content/MF_WavyOutline.uasset new file mode 100644 index 000000000..288c4e7c7 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/MF_WavyOutline.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/MI_Circle.uasset b/demo/Blackholio/client-unreal/Content/MI_Circle.uasset new file mode 100644 index 000000000..10cc504a6 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/MI_Circle.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/MI_Food.uasset b/demo/Blackholio/client-unreal/Content/MI_Food.uasset new file mode 100644 index 000000000..c283ed43f Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/MI_Food.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/M_Circle.uasset b/demo/Blackholio/client-unreal/Content/M_Circle.uasset new file mode 100644 index 000000000..0b4513403 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/M_Circle.uasset differ diff --git a/demo/Blackholio/client-unreal/Content/WBP_Nameplate.uasset b/demo/Blackholio/client-unreal/Content/WBP_Nameplate.uasset new file mode 100644 index 000000000..1bfdff8b9 Binary files /dev/null and b/demo/Blackholio/client-unreal/Content/WBP_Nameplate.uasset differ diff --git a/demo/Blackholio/client-unreal/Source/client_unreal.Target.cs b/demo/Blackholio/client-unreal/Source/client_unreal.Target.cs new file mode 100644 index 000000000..497148bd7 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal.Target.cs @@ -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"); + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/BlackholioGameMode.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/BlackholioGameMode.cpp new file mode 100644 index 000000000..14892c345 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/BlackholioGameMode.cpp @@ -0,0 +1,2 @@ +#include "BlackholioGameMode.h" + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/BlackholioPlayerController.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/BlackholioPlayerController.cpp new file mode 100644 index 000000000..f2dadaba1 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/BlackholioPlayerController.cpp @@ -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(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(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(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(InPawn); + EnsureMappingContext(); +} + +void ABlackholioPlayerController::SetupInputComponent() +{ + Super::SetupInputComponent(); + if (UEnhancedInputComponent* EIC = Cast(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(SizeX) * 0.5f, static_cast(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(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(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); + } + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Circle.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Circle.cpp new file mode 100644 index 000000000..5d0fe7a4c --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Circle.cpp @@ -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(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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Entity.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Entity.cpp new file mode 100644 index 000000000..cfa53f53e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Entity.cpp @@ -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()) + { + SpriteComponent->SetSpriteColor(Color); + } +} \ No newline at end of file diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Food.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Food.cpp new file mode 100644 index 000000000..41c0d51f6 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Food.cpp @@ -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(EntityId % ColorPalette.Num()) : 0; + const FLinearColor Color = ColorPalette.IsValidIndex(Index) ? ColorPalette[Index] : FLinearColor::Green; + SetColor(Color); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/GameManager.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/GameManager.cpp new file mode 100644 index 000000000..2e0ff7626 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/GameManager.cpp @@ -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(TEXT("BorderISM")); + SetRootComponent(BorderISM); + + if (CubeMesh != nullptr) + return; + + static ConstructorHelpers::FObjectFinder CubeAsset(TEXT("/Engine/BasicShapes/Cube.Cube")); + if (CubeAsset.Succeeded()) + { + CubeMesh = CubeAsset.Object; + } +} + +AEntity* AGameManager::GetEntity(uint32 EntityId) const +{ + if (const TWeakObjectPtr* 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(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(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* 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 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 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 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(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(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(FoodClass, FVector::ZeroVector, FRotator::ZeroRotator, Params); + if (Food) + { + Food->Spawn(FoodEntity); + EntityMap.Add(FoodEntity.EntityId, Food); + } + return Food; +} \ No newline at end of file diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/LeaderboardRowWidget.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/LeaderboardRowWidget.cpp new file mode 100644 index 000000000..f2873553c --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/LeaderboardRowWidget.cpp @@ -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)); + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/LeaderboardWidget.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/LeaderboardWidget.cpp new file mode 100644 index 000000000..0be83e45a --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/LeaderboardWidget.cpp @@ -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(this, RowClass); + if (!Row) { continue; } + + Root->AddChild(Row); + Row->SetVisibility(ESlateVisibility::Collapsed); + Rows.Add(Row); + } +} + +void ULeaderboardWidget::CollectPlayers(TArray& Out) const +{ + Out.Reset(); + + const AGameManager* GM = AGameManager::Instance; + if (!GM) return; + + TMap> PlayerMap = GM->GetPlayerMap(); + if (PlayerMap.Num() == 0) return; + + // 2) Build entries: mass > 0 only + for (const TPair>& Pair : PlayerMap) + { + APlayerPawn* Pawn = Pair.Value.Get(); + if (!Pawn) continue; + + const int32 Mass = static_cast(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(PC->GetPawn())) + { + const bool AlreadyIn = Out.ContainsByPredicate( + [LocalPawn](const FLeaderboardEntry& E){ return E.Pawn.Get() == LocalPawn; }); + + const int32 LocalMass = static_cast(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 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); + } + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/ParallaxBackground.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/ParallaxBackground.cpp new file mode 100644 index 000000000..cdd6a75f9 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/ParallaxBackground.cpp @@ -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); +} + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/RespawnWidget.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/RespawnWidget.cpp new file mode 100644 index 000000000..287c7fc5e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/RespawnWidget.cpp @@ -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; + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/UsernameChooserWidget.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/UsernameChooserWidget.cpp new file mode 100644 index 000000000..12f6a1f03 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/Gameplay/UsernameChooserWidget.cpp @@ -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(""); + } + 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)); + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp new file mode 100644 index 000000000..85039015e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -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(Event.ReducerCall.Args); + return FReducer::CircleDecay(Args); + } + + if (ReducerName == TEXT("circle_recombine")) + { + FCircleRecombineArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::CircleRecombine(Args); + } + + if (ReducerName == TEXT("connect")) + { + FConnectArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::Connect(Args); + } + + if (ReducerName == TEXT("consume_entity")) + { + FConsumeEntityArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::ConsumeEntity(Args); + } + + if (ReducerName == TEXT("disconnect")) + { + FDisconnectArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::Disconnect(Args); + } + + if (ReducerName == TEXT("enter_game")) + { + FEnterGameArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::EnterGame(Args); + } + + if (ReducerName == TEXT("move_all_players")) + { + FMoveAllPlayersArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::MoveAllPlayers(Args); + } + + if (ReducerName == TEXT("player_split")) + { + FPlayerSplitArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::PlayerSplit(Args); + } + + if (ReducerName == TEXT("respawn")) + { + FRespawnArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::Respawn(Args); + } + + if (ReducerName == TEXT("spawn_food")) + { + FSpawnFoodArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::SpawnFood(Args); + } + + if (ReducerName == TEXT("suicide")) + { + FSuicideArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::Suicide(Args); + } + + if (ReducerName == TEXT("update_player_input")) + { + FUpdatePlayerInputArgs Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args); + return FReducer::UpdatePlayerInput(Args); + } + + return FReducer(); +} + +UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +{ + SetReducerFlags = ObjectInitializer.CreateDefaultSubobject(this, TEXT("SetReducerFlags")); + + Db = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteTables")); + Db->Initialize(); + + Reducers = ObjectInitializer.CreateDefaultSubobject(this, TEXT("RemoteReducers")); + Reducers->SetCallReducerFlags = SetReducerFlags; + Reducers->Conn = this; + + RegisterTable(TEXT("logged_out_entity"), Db->LoggedOutEntity); + RegisterTable(TEXT("move_all_players_timer"), Db->MoveAllPlayersTimer); + RegisterTable(TEXT("circle_decay_timer"), Db->CircleDecayTimer); + RegisterTable(TEXT("entity"), Db->Entity); + RegisterTable(TEXT("food"), Db->Food); + RegisterTable(TEXT("circle_recombine_timer"), Db->CircleRecombineTimer); + RegisterTable(TEXT("config"), Db->Config); + RegisterTable(TEXT("logged_out_player"), Db->LoggedOutPlayer); + RegisterTable(TEXT("logged_out_circle"), Db->LoggedOutCircle); + RegisterTable(TEXT("player"), Db->Player); + RegisterTable(TEXT("consume_entity_timer"), Db->ConsumeEntityTimer); + RegisterTable(TEXT("spawn_food_timer"), Db->SpawnFoodTimer); + RegisterTable(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(this); + MoveAllPlayersTimer = NewObject(this); + CircleDecayTimer = NewObject(this); + Entity = NewObject(this); + Food = NewObject(this); + CircleRecombineTimer = NewObject(this); + Config = NewObject(this); + LoggedOutPlayer = NewObject(this); + LoggedOutCircle = NewObject(this); + Player = NewObject(this); + ConsumeEntityTimer = NewObject(this); + SpawnFoodTimer = NewObject(this); + Circle = NewObject(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(); + Reducer->Timer = Args.Timer; + Reducers->InvokeCircleDecay(Context, Reducer); + return; + } + if (ReducerName == TEXT("circle_recombine")) + { + FCircleRecombineArgs Args = ReducerEvent.Reducer.GetAsCircleRecombine(); + UCircleRecombineReducer* Reducer = NewObject(); + Reducer->Timer = Args.Timer; + Reducers->InvokeCircleRecombine(Context, Reducer); + return; + } + if (ReducerName == TEXT("connect")) + { + FConnectArgs Args = ReducerEvent.Reducer.GetAsConnect(); + UConnectReducer* Reducer = NewObject(); + Reducers->InvokeConnect(Context, Reducer); + return; + } + if (ReducerName == TEXT("consume_entity")) + { + FConsumeEntityArgs Args = ReducerEvent.Reducer.GetAsConsumeEntity(); + UConsumeEntityReducer* Reducer = NewObject(); + Reducer->Request = Args.Request; + Reducers->InvokeConsumeEntity(Context, Reducer); + return; + } + if (ReducerName == TEXT("disconnect")) + { + FDisconnectArgs Args = ReducerEvent.Reducer.GetAsDisconnect(); + UDisconnectReducer* Reducer = NewObject(); + Reducers->InvokeDisconnect(Context, Reducer); + return; + } + if (ReducerName == TEXT("enter_game")) + { + FEnterGameArgs Args = ReducerEvent.Reducer.GetAsEnterGame(); + UEnterGameReducer* Reducer = NewObject(); + Reducer->Name = Args.Name; + Reducers->InvokeEnterGame(Context, Reducer); + return; + } + if (ReducerName == TEXT("move_all_players")) + { + FMoveAllPlayersArgs Args = ReducerEvent.Reducer.GetAsMoveAllPlayers(); + UMoveAllPlayersReducer* Reducer = NewObject(); + Reducer->Timer = Args.Timer; + Reducers->InvokeMoveAllPlayers(Context, Reducer); + return; + } + if (ReducerName == TEXT("player_split")) + { + FPlayerSplitArgs Args = ReducerEvent.Reducer.GetAsPlayerSplit(); + UPlayerSplitReducer* Reducer = NewObject(); + Reducers->InvokePlayerSplit(Context, Reducer); + return; + } + if (ReducerName == TEXT("respawn")) + { + FRespawnArgs Args = ReducerEvent.Reducer.GetAsRespawn(); + URespawnReducer* Reducer = NewObject(); + Reducers->InvokeRespawn(Context, Reducer); + return; + } + if (ReducerName == TEXT("spawn_food")) + { + FSpawnFoodArgs Args = ReducerEvent.Reducer.GetAsSpawnFood(); + USpawnFoodReducer* Reducer = NewObject(); + Reducer->Timer = Args.Timer; + Reducers->InvokeSpawnFood(Context, Reducer); + return; + } + if (ReducerName == TEXT("suicide")) + { + FSuicideArgs Args = ReducerEvent.Reducer.GetAsSuicide(); + USuicideReducer* Reducer = NewObject(); + Reducers->InvokeSuicide(Context, Reducer); + return; + } + if (ReducerName == TEXT("update_player_input")) + { + FUpdatePlayerInputArgs Args = ReducerEvent.Reducer.GetAsUpdatePlayerInput(); + UUpdatePlayerInputReducer* Reducer = NewObject(); + 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(); +} +// Added for creating subscriptions +USubscriptionBuilder* UDbConnection::SubscriptionBuilder() +{ + USubscriptionBuilder* Builder = NewObject(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& SQL) +{ + USubscriptionHandle* Handle = NewObject(); + + // 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(WithUriBase(InUri)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithModuleName(const FString& InName) +{ + return Cast(WithModuleNameBase(InName)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithToken(const FString& InToken) +{ + return Cast(WithTokenBase(InToken)); +} +UDbConnectionBuilder* UDbConnectionBuilder::WithCompression(const ESpacetimeDBCompression& InCompression) +{ + return Cast(WithCompressionBase(InCompression)); +} +UDbConnectionBuilder* UDbConnectionBuilder::OnConnect(FOnConnectDelegate Callback) +{ + OnConnectDelegateInternal = Callback; + return this; +} +UDbConnectionBuilder* UDbConnectionBuilder::OnConnectError(FOnConnectErrorDelegate Callback) +{ + return Cast(OnConnectErrorBase(Callback)); +} +UDbConnectionBuilder* UDbConnectionBuilder::OnDisconnect(FOnDisconnectDelegate Callback) +{ + OnDisconnectDelegateInternal = Callback; + return this; +} +UDbConnection* UDbConnectionBuilder::Build() +{ + UDbConnection* Connection = NewObject(); + + // 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(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); +} + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp new file mode 100644 index 000000000..3f843a102 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleDecayTimerTable.g.cpp @@ -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>(); + + TSharedPtr> CircleDecayTimerTable = Data->GetOrAdd(TableName); + CircleDecayTimerTable->AddUniqueConstraint("scheduled_id", [](const FCircleDecayTimerType& Row) -> const uint64& { + return Row.ScheduledId; }); + + ScheduledId = NewObject(this); + ScheduledId->SetCache(CircleDecayTimerTable); + + /***/ +} + +FTableAppliedDiff UCircleDecayTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FCircleDecayTimerType& Row) + { + return Row.ScheduledId; + } + ); + + return Diff; +} + +int32 UCircleDecayTimerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UCircleDecayTimerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp new file mode 100644 index 000000000..c79d81391 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleRecombineTimerTable.g.cpp @@ -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>(); + + TSharedPtr> CircleRecombineTimerTable = Data->GetOrAdd(TableName); + CircleRecombineTimerTable->AddUniqueConstraint("scheduled_id", [](const FCircleRecombineTimerType& Row) -> const uint64& { + return Row.ScheduledId; }); + + ScheduledId = NewObject(this); + ScheduledId->SetCache(CircleRecombineTimerTable); + + /***/ +} + +FTableAppliedDiff UCircleRecombineTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FCircleRecombineTimerType& Row) + { + return Row.ScheduledId; + } + ); + + return Diff; +} + +int32 UCircleRecombineTimerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UCircleRecombineTimerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleTable.g.cpp new file mode 100644 index 000000000..58f27292a --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/CircleTable.g.cpp @@ -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>(); + + TSharedPtr> CircleTable = Data->GetOrAdd(TableName); + CircleTable->AddUniqueConstraint("entity_id", [](const FCircleType& Row) -> const uint32& { + return Row.EntityId; }); + + EntityId = NewObject(this); + EntityId->SetCache(CircleTable); + + // Register a new multi-key B-Tree index named "player_id" on the CircleTable. + CircleTable->AddMultiKeyBTreeIndex>( + 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(this); + PlayerId->SetCache(CircleTable); + + /***/ +} + +FTableAppliedDiff UCircleTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FCircleType& Row) + { + return Row.EntityId; + } + ); + + return Diff; +} + +int32 UCircleTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UCircleTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConfigTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConfigTable.g.cpp new file mode 100644 index 000000000..95b589d1e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConfigTable.g.cpp @@ -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>(); + + TSharedPtr> ConfigTable = Data->GetOrAdd(TableName); + ConfigTable->AddUniqueConstraint("id", [](const FConfigType& Row) -> const uint32& { + return Row.Id; }); + + Id = NewObject(this); + Id->SetCache(ConfigTable); + + /***/ +} + +FTableAppliedDiff UConfigTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FConfigType& Row) + { + return Row.Id; + } + ); + + return Diff; +} + +int32 UConfigTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UConfigTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp new file mode 100644 index 000000000..398c24bdb --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/ConsumeEntityTimerTable.g.cpp @@ -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>(); + + TSharedPtr> ConsumeEntityTimerTable = Data->GetOrAdd(TableName); + ConsumeEntityTimerTable->AddUniqueConstraint("scheduled_id", [](const FConsumeEntityTimerType& Row) -> const uint64& { + return Row.ScheduledId; }); + + ScheduledId = NewObject(this); + ScheduledId->SetCache(ConsumeEntityTimerTable); + + /***/ +} + +FTableAppliedDiff UConsumeEntityTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FConsumeEntityTimerType& Row) + { + return Row.ScheduledId; + } + ); + + return Diff; +} + +int32 UConsumeEntityTimerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UConsumeEntityTimerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/EntityTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/EntityTable.g.cpp new file mode 100644 index 000000000..ca6f02875 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/EntityTable.g.cpp @@ -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>(); + + TSharedPtr> EntityTable = Data->GetOrAdd(TableName); + EntityTable->AddUniqueConstraint("entity_id", [](const FEntityType& Row) -> const uint32& { + return Row.EntityId; }); + + EntityId = NewObject(this); + EntityId->SetCache(EntityTable); + + /***/ +} + +FTableAppliedDiff UEntityTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FEntityType& Row) + { + return Row.EntityId; + } + ); + + return Diff; +} + +int32 UEntityTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UEntityTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/FoodTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/FoodTable.g.cpp new file mode 100644 index 000000000..6d439a84e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/FoodTable.g.cpp @@ -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>(); + + TSharedPtr> FoodTable = Data->GetOrAdd(TableName); + FoodTable->AddUniqueConstraint("entity_id", [](const FFoodType& Row) -> const uint32& { + return Row.EntityId; }); + + EntityId = NewObject(this); + EntityId->SetCache(FoodTable); + + /***/ +} + +FTableAppliedDiff UFoodTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FFoodType& Row) + { + return Row.EntityId; + } + ); + + return Diff; +} + +int32 UFoodTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UFoodTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp new file mode 100644 index 000000000..ed8b6a847 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.cpp @@ -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>(); + + TSharedPtr> MoveAllPlayersTimerTable = Data->GetOrAdd(TableName); + MoveAllPlayersTimerTable->AddUniqueConstraint("scheduled_id", [](const FMoveAllPlayersTimerType& Row) -> const uint64& { + return Row.ScheduledId; }); + + ScheduledId = NewObject(this); + ScheduledId->SetCache(MoveAllPlayersTimerTable); + + /***/ +} + +FTableAppliedDiff UMoveAllPlayersTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FMoveAllPlayersTimerType& Row) + { + return Row.ScheduledId; + } + ); + + return Diff; +} + +int32 UMoveAllPlayersTimerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UMoveAllPlayersTimerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/PlayerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/PlayerTable.g.cpp new file mode 100644 index 000000000..2a2c29896 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/PlayerTable.g.cpp @@ -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>(); + + TSharedPtr> PlayerTable = Data->GetOrAdd(TableName); + PlayerTable->AddUniqueConstraint("identity", [](const FPlayerType& Row) -> const FSpacetimeDBIdentity& { + return Row.Identity; }); + PlayerTable->AddUniqueConstraint("player_id", [](const FPlayerType& Row) -> const uint32& { + return Row.PlayerId; }); + + Identity = NewObject(this); + Identity->SetCache(PlayerTable); + + PlayerId = NewObject(this); + PlayerId->SetCache(PlayerTable); + + /***/ +} + +FTableAppliedDiff UPlayerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FPlayerType& Row) + { + return Row.Identity; + } + ); + + return Diff; +} + +int32 UPlayerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray UPlayerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp new file mode 100644 index 000000000..f7a36cff7 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/ModuleBindings/Tables/SpawnFoodTimerTable.g.cpp @@ -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>(); + + TSharedPtr> SpawnFoodTimerTable = Data->GetOrAdd(TableName); + SpawnFoodTimerTable->AddUniqueConstraint("scheduled_id", [](const FSpawnFoodTimerType& Row) -> const uint64& { + return Row.ScheduledId; }); + + ScheduledId = NewObject(this); + ScheduledId->SetCache(SpawnFoodTimerTable); + + /***/ +} + +FTableAppliedDiff USpawnFoodTimerTable::Update(TArray> InsertsRef, TArray> DeletesRef) +{ + FTableAppliedDiff Diff = BaseUpdate(InsertsRef, DeletesRef, Data, TableName); + + Diff.DeriveUpdatesByPrimaryKey( + [](const FSpawnFoodTimerType& Row) + { + return Row.ScheduledId; + } + ); + + return Diff; +} + +int32 USpawnFoodTimerTable::Count() const +{ + return GetRowCountFromTable(Data, TableName); +} + +TArray USpawnFoodTimerTable::Iter() const +{ + return GetAllRowsFromTable(Data, TableName); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Private/PlayerPawn.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/Private/PlayerPawn.cpp new file mode 100644 index 000000000..4326e026d --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Private/PlayerPawn.cpp @@ -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(TEXT("Root")); + RootComponent = DefaultRoot; + + SpringArm = CreateDefaultSubobject(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(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(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& 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& 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& 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); +} + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/BlackholioGameMode.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/BlackholioGameMode.h new file mode 100644 index 000000000..38a61e127 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/BlackholioGameMode.h @@ -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() + +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/BlackholioPlayerController.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/BlackholioPlayerController.h new file mode 100644 index 000000000..3e54aaebf --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/BlackholioPlayerController.h @@ -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 UsernameChooserClass; + + UPROPERTY(EditDefaultsOnly, Category="BH|Config") + TSubclassOf RespawnClass; + + UPROPERTY(EditDefaultsOnly, Category="BH|Config") + TSubclassOf LeaderboardClass; +private: + UFUNCTION() + void EnsureMappingContext() const; + + UPROPERTY() + TObjectPtr LocalPlayer; + + UPROPERTY() + float SendUpdatesFrequency = 0.0333f; + float LastMovementSendTimestamp = 0.f; + bool bShowedUsernameChooser = false; + + TOptional LockInputPosition; + + UPROPERTY(EditDefaultsOnly, Category="BH|Input") + TObjectPtr PlayerMappingContext = nullptr; + + UPROPERTY(EditDefaultsOnly, Category="BH|Input") + TObjectPtr SplitAction = nullptr; + + UPROPERTY(EditDefaultsOnly, Category="BH|Input") + TObjectPtr SuicideAction = nullptr; + + UPROPERTY(EditDefaultsOnly, Category="BH|Input") + TObjectPtr ToggleInputLockAction = nullptr; + + UPROPERTY() + TObjectPtr RespawnWidget = nullptr; + UPROPERTY() + TObjectPtr UsernameChooserWidget = nullptr; + UPROPERTY() + TObjectPtr LeaderboardWidget = nullptr; + + // Input handlers (Enhanced Input) + void OnSplitTriggered(const FInputActionValue& Value); + void OnSuicideTriggered(const FInputActionValue& Value); + void OnToggleInputLockTriggered(const FInputActionValue& Value); +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Circle.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Circle.h new file mode 100644 index 000000000..0042f6f03 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Circle.h @@ -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 ColorPalette; + +private: + TWeakObjectPtr Owner; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/DbVector2.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/DbVector2.h new file mode 100644 index 000000000..482c3546d --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/DbVector2.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Entity.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Entity.h new file mode 100644 index 000000000..4fe24883e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Entity.h @@ -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(Mass)); } + static float MassToDiameter(uint32 Mass) { return MassToRadius(Mass) * 2.f; } + +private: + UPROPERTY() + TObjectPtr ConsumingEntity = nullptr; + bool bIsDespawning = false; + float DespawnElapsed = 0.f; + FVector ConsumeStartPosition = FVector::ZeroVector; + FVector ConsumeStartScale = FVector::ZeroVector; + +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Food.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Food.h new file mode 100644 index 000000000..80efd423e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Food.h @@ -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 ColorPalette; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/GameManager.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/GameManager.h new file mode 100644 index 000000000..bdb0347f9 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/GameManager.h @@ -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 CircleClass; + UPROPERTY(EditAnywhere, Category="BH|Classes") + TSubclassOf FoodClass; + UPROPERTY(EditAnywhere, Category="BH|Classes") + TSubclassOf 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> 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> EntityMap; + UPROPERTY() + TMap> 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 */ +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/LeaderboardRowWidget.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/LeaderboardRowWidget.h new file mode 100644 index 000000000..ff73bacbf --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/LeaderboardRowWidget.h @@ -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 UsernameText = nullptr; + + UPROPERTY(meta=(BindWidget)) + TObjectPtr MassText = nullptr; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/LeaderboardWidget.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/LeaderboardWidget.h new file mode 100644 index 000000000..b34857fbe --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/LeaderboardWidget.h @@ -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 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 RowClass; + + UPROPERTY(EditDefaultsOnly, Category="BH|Leaderboard") + int32 MaxRowCount = 10; + + UPROPERTY(EditDefaultsOnly, Category="BH|Leaderboard") + float UpdatePeriod = 0.25f; + +private: + UPROPERTY(Transient) + TArray Rows; + + FTimerHandle UpdateTimer; + + void BuildRowPool(); + void CollectPlayers(TArray& Out) const; + void UpdateLeaderboard(); +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/ParallaxBackground.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/ParallaxBackground.h new file mode 100644 index 000000000..f6712db51 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/ParallaxBackground.h @@ -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; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/RespawnWidget.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/RespawnWidget.h new file mode 100644 index 000000000..2a7ad78f0 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/RespawnWidget.h @@ -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 RespawnButton; + + virtual void NativeConstruct() override; + +private: + UFUNCTION() + void OnRespawnPressed(); +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/UsernameChooserWidget.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/UsernameChooserWidget.h new file mode 100644 index 000000000..ea4f44f4c --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/Gameplay/UsernameChooserWidget.h @@ -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 UsernameInputField; + UPROPERTY(meta=(BindWidget)) + TObjectPtr PlayButton; + + virtual void NativeConstruct() override; + virtual void NativeDestruct() override; + +private: + UFUNCTION() + void OnPlayPressed(); + UFUNCTION() + void HandlePlayerInserted(const FEventContext& Context, const FPlayerType& NewPlayer); +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/ReducerBase.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/ReducerBase.g.h new file mode 100644 index 000000000..a6af9d836 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/ReducerBase.g.h @@ -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; +}; + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleDecay.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleDecay.g.h new file mode 100644 index 000000000..d2f2106c5 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleDecay.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleRecombine.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleRecombine.g.h new file mode 100644 index 000000000..411925d33 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/CircleRecombine.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Connect.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Connect.g.h new file mode 100644 index 000000000..3f4aa4d29 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Connect.g.h @@ -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: +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/ConsumeEntity.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/ConsumeEntity.g.h new file mode 100644 index 000000000..c51fb1909 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/ConsumeEntity.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Disconnect.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Disconnect.g.h new file mode 100644 index 000000000..1149cdb40 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Disconnect.g.h @@ -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: +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/EnterGame.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/EnterGame.g.h new file mode 100644 index 000000000..c595900b1 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/EnterGame.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/MoveAllPlayers.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/MoveAllPlayers.g.h new file mode 100644 index 000000000..421c680f6 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/MoveAllPlayers.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/PlayerSplit.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/PlayerSplit.g.h new file mode 100644 index 000000000..e58443536 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/PlayerSplit.g.h @@ -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: +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Respawn.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Respawn.g.h new file mode 100644 index 000000000..7d5b5c28e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Respawn.g.h @@ -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: +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/SpawnFood.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/SpawnFood.g.h new file mode 100644 index 000000000..f3aaaa6c7 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/SpawnFood.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Suicide.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Suicide.g.h new file mode 100644 index 000000000..953c33bb6 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/Suicide.g.h @@ -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: +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/UpdatePlayerInput.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/UpdatePlayerInput.g.h new file mode 100644 index 000000000..39860c0dc --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Reducers/UpdatePlayerInput.g.h @@ -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; + +}; + + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h new file mode 100644 index 000000000..44531b309 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -0,0 +1,1264 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +// This was generated using spacetimedb cli version 1.4.0 (commit dc59211c1453848981aeb2efce2249c9a07947b2). + +#pragma once +#include "CoreMinimal.h" +#include "BSATN/UESpacetimeDB.h" +#include "Connection/Callback.h" +#include "Connection/DbConnectionBase.h" +#include "Connection/DbConnectionBuilder.h" +#include "Connection/SetReducerFlags.h" +#include "Connection/Subscription.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "ModuleBindings/ReducerBase.g.h" +#include "ModuleBindings/Reducers/CircleDecay.g.h" +#include "ModuleBindings/Reducers/CircleRecombine.g.h" +#include "ModuleBindings/Reducers/Connect.g.h" +#include "ModuleBindings/Reducers/ConsumeEntity.g.h" +#include "ModuleBindings/Reducers/Disconnect.g.h" +#include "ModuleBindings/Reducers/EnterGame.g.h" +#include "ModuleBindings/Reducers/MoveAllPlayers.g.h" +#include "ModuleBindings/Reducers/PlayerSplit.g.h" +#include "ModuleBindings/Reducers/Respawn.g.h" +#include "ModuleBindings/Reducers/SpawnFood.g.h" +#include "ModuleBindings/Reducers/Suicide.g.h" +#include "ModuleBindings/Reducers/UpdatePlayerInput.g.h" +#include "ModuleBindings/Types/CircleDecayTimerType.g.h" +#include "ModuleBindings/Types/CircleRecombineTimerType.g.h" +#include "ModuleBindings/Types/ConsumeEntityTimerType.g.h" +#include "ModuleBindings/Types/DbVector2Type.g.h" +#include "ModuleBindings/Types/MoveAllPlayersTimerType.g.h" +#include "ModuleBindings/Types/SpawnFoodTimerType.g.h" +#include "Types/Builtins.h" +#include "SpacetimeDBClient.g.generated.h" + +// Forward declarations +class UDbConnection; +class URemoteTables; +class URemoteReducers; +class USubscriptionBuilder; +class USubscriptionHandle; + +/** Forward declaration for tables */ +class UCircleTable; +class UCircleDecayTimerTable; +class UCircleRecombineTimerTable; +class UConfigTable; +class UConsumeEntityTimerTable; +class UEntityTable; +class UFoodTable; +class UCircleTable; +class UEntityTable; +class UPlayerTable; +class UMoveAllPlayersTimerTable; +class UPlayerTable; +class USpawnFoodTimerTable; +/***/ + +// Delegates using the generated connection type. These wrap the base +// delegates defined in the SDK so that projects can work directly with +// UDbConnection without manual casting in user code. +DECLARE_DYNAMIC_DELEGATE_ThreeParams( + FOnConnectDelegate, + UDbConnection*, Connection, + FSpacetimeDBIdentity, Identity, + const FString&, Token); + +DECLARE_DYNAMIC_DELEGATE_TwoParams( + FOnDisconnectDelegate, + UDbConnection*, Connection, + const FString&, Error); + + +// Context classes for event handling + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FContextBase +{ + GENERATED_BODY() + + FContextBase() = default; + FContextBase(UDbConnection* InConn); + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteTables* Db; + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + URemoteReducers* Reducers; + + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + USetReducerFlags* SetReducerFlags; + + bool IsActive() const; + void Disconnect(); + bool TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const; + FSpacetimeDBConnectionId GetConnectionId() const; + USubscriptionBuilder* SubscriptionBuilder(); + +protected: + UPROPERTY() + UDbConnection* Conn; + +}; + +UENUM(BlueprintType, Category = "SpacetimeDB") +enum class EReducerTag : uint8 +{ + CircleDecay, + CircleRecombine, + Connect, + ConsumeEntity, + Disconnect, + EnterGame, + MoveAllPlayers, + PlayerSplit, + Respawn, + SpawnFood, + Suicide, + UpdatePlayerInput +}; + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FReducer +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + EReducerTag Tag; + + TVariant Data; + + // Optional metadata + UPROPERTY(BlueprintReadOnly, Category = "SpacetimeDB") + FString ReducerName; + uint32 ReducerId = 0; + uint32 RequestId = 0; + + static FReducer CircleDecay(const FCircleDecayArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::CircleDecay; + Out.Data.Set(Value); + Out.ReducerName = TEXT("circle_decay"); + return Out; + } + + FORCEINLINE bool IsCircleDecay() const { return Tag == EReducerTag::CircleDecay; } + FORCEINLINE FCircleDecayArgs GetAsCircleDecay() const + { + ensureMsgf(IsCircleDecay(), TEXT("Reducer does not hold CircleDecay!")); + return Data.Get(); + } + + static FReducer CircleRecombine(const FCircleRecombineArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::CircleRecombine; + Out.Data.Set(Value); + Out.ReducerName = TEXT("circle_recombine"); + return Out; + } + + FORCEINLINE bool IsCircleRecombine() const { return Tag == EReducerTag::CircleRecombine; } + FORCEINLINE FCircleRecombineArgs GetAsCircleRecombine() const + { + ensureMsgf(IsCircleRecombine(), TEXT("Reducer does not hold CircleRecombine!")); + return Data.Get(); + } + + static FReducer Connect(const FConnectArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::Connect; + Out.Data.Set(Value); + Out.ReducerName = TEXT("connect"); + return Out; + } + + FORCEINLINE bool IsConnect() const { return Tag == EReducerTag::Connect; } + FORCEINLINE FConnectArgs GetAsConnect() const + { + ensureMsgf(IsConnect(), TEXT("Reducer does not hold Connect!")); + return Data.Get(); + } + + static FReducer ConsumeEntity(const FConsumeEntityArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::ConsumeEntity; + Out.Data.Set(Value); + Out.ReducerName = TEXT("consume_entity"); + return Out; + } + + FORCEINLINE bool IsConsumeEntity() const { return Tag == EReducerTag::ConsumeEntity; } + FORCEINLINE FConsumeEntityArgs GetAsConsumeEntity() const + { + ensureMsgf(IsConsumeEntity(), TEXT("Reducer does not hold ConsumeEntity!")); + return Data.Get(); + } + + static FReducer Disconnect(const FDisconnectArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::Disconnect; + Out.Data.Set(Value); + Out.ReducerName = TEXT("disconnect"); + return Out; + } + + FORCEINLINE bool IsDisconnect() const { return Tag == EReducerTag::Disconnect; } + FORCEINLINE FDisconnectArgs GetAsDisconnect() const + { + ensureMsgf(IsDisconnect(), TEXT("Reducer does not hold Disconnect!")); + return Data.Get(); + } + + static FReducer EnterGame(const FEnterGameArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::EnterGame; + Out.Data.Set(Value); + Out.ReducerName = TEXT("enter_game"); + return Out; + } + + FORCEINLINE bool IsEnterGame() const { return Tag == EReducerTag::EnterGame; } + FORCEINLINE FEnterGameArgs GetAsEnterGame() const + { + ensureMsgf(IsEnterGame(), TEXT("Reducer does not hold EnterGame!")); + return Data.Get(); + } + + static FReducer MoveAllPlayers(const FMoveAllPlayersArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::MoveAllPlayers; + Out.Data.Set(Value); + Out.ReducerName = TEXT("move_all_players"); + return Out; + } + + FORCEINLINE bool IsMoveAllPlayers() const { return Tag == EReducerTag::MoveAllPlayers; } + FORCEINLINE FMoveAllPlayersArgs GetAsMoveAllPlayers() const + { + ensureMsgf(IsMoveAllPlayers(), TEXT("Reducer does not hold MoveAllPlayers!")); + return Data.Get(); + } + + static FReducer PlayerSplit(const FPlayerSplitArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::PlayerSplit; + Out.Data.Set(Value); + Out.ReducerName = TEXT("player_split"); + return Out; + } + + FORCEINLINE bool IsPlayerSplit() const { return Tag == EReducerTag::PlayerSplit; } + FORCEINLINE FPlayerSplitArgs GetAsPlayerSplit() const + { + ensureMsgf(IsPlayerSplit(), TEXT("Reducer does not hold PlayerSplit!")); + return Data.Get(); + } + + static FReducer Respawn(const FRespawnArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::Respawn; + Out.Data.Set(Value); + Out.ReducerName = TEXT("respawn"); + return Out; + } + + FORCEINLINE bool IsRespawn() const { return Tag == EReducerTag::Respawn; } + FORCEINLINE FRespawnArgs GetAsRespawn() const + { + ensureMsgf(IsRespawn(), TEXT("Reducer does not hold Respawn!")); + return Data.Get(); + } + + static FReducer SpawnFood(const FSpawnFoodArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::SpawnFood; + Out.Data.Set(Value); + Out.ReducerName = TEXT("spawn_food"); + return Out; + } + + FORCEINLINE bool IsSpawnFood() const { return Tag == EReducerTag::SpawnFood; } + FORCEINLINE FSpawnFoodArgs GetAsSpawnFood() const + { + ensureMsgf(IsSpawnFood(), TEXT("Reducer does not hold SpawnFood!")); + return Data.Get(); + } + + static FReducer Suicide(const FSuicideArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::Suicide; + Out.Data.Set(Value); + Out.ReducerName = TEXT("suicide"); + return Out; + } + + FORCEINLINE bool IsSuicide() const { return Tag == EReducerTag::Suicide; } + FORCEINLINE FSuicideArgs GetAsSuicide() const + { + ensureMsgf(IsSuicide(), TEXT("Reducer does not hold Suicide!")); + return Data.Get(); + } + + static FReducer UpdatePlayerInput(const FUpdatePlayerInputArgs& Value) + { + FReducer Out; + Out.Tag = EReducerTag::UpdatePlayerInput; + Out.Data.Set(Value); + Out.ReducerName = TEXT("update_player_input"); + return Out; + } + + FORCEINLINE bool IsUpdatePlayerInput() const { return Tag == EReducerTag::UpdatePlayerInput; } + FORCEINLINE FUpdatePlayerInputArgs GetAsUpdatePlayerInput() const + { + ensureMsgf(IsUpdatePlayerInput(), TEXT("Reducer does not hold UpdatePlayerInput!")); + return Data.Get(); + } + + FORCEINLINE bool operator==(const FReducer& Other) const + { + if (Tag != Other.Tag || ReducerId != Other.ReducerId || RequestId != Other.RequestId || ReducerName != Other.ReducerName) return false; + switch (Tag) + { + case EReducerTag::CircleDecay: + return GetAsCircleDecay() == Other.GetAsCircleDecay(); + case EReducerTag::CircleRecombine: + return GetAsCircleRecombine() == Other.GetAsCircleRecombine(); + case EReducerTag::Connect: + return GetAsConnect() == Other.GetAsConnect(); + case EReducerTag::ConsumeEntity: + return GetAsConsumeEntity() == Other.GetAsConsumeEntity(); + case EReducerTag::Disconnect: + return GetAsDisconnect() == Other.GetAsDisconnect(); + case EReducerTag::EnterGame: + return GetAsEnterGame() == Other.GetAsEnterGame(); + case EReducerTag::MoveAllPlayers: + return GetAsMoveAllPlayers() == Other.GetAsMoveAllPlayers(); + case EReducerTag::PlayerSplit: + return GetAsPlayerSplit() == Other.GetAsPlayerSplit(); + case EReducerTag::Respawn: + return GetAsRespawn() == Other.GetAsRespawn(); + case EReducerTag::SpawnFood: + return GetAsSpawnFood() == Other.GetAsSpawnFood(); + case EReducerTag::Suicide: + return GetAsSuicide() == Other.GetAsSuicide(); + case EReducerTag::UpdatePlayerInput: + return GetAsUpdatePlayerInput() == Other.GetAsUpdatePlayerInput(); + default: return false; + } + } + FORCEINLINE bool operator!=(const FReducer& Other) const { return !(*this == Other); } +}; + +UCLASS() +class CLIENT_UNREAL_API UReducerBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer CircleDecay(const FCircleDecayArgs& Value) { + return FReducer::CircleDecay(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsCircleDecay(const FReducer& Reducer) { return Reducer.IsCircleDecay(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FCircleDecayArgs GetAsCircleDecay(const FReducer& Reducer) { + return Reducer.GetAsCircleDecay(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer CircleRecombine(const FCircleRecombineArgs& Value) { + return FReducer::CircleRecombine(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsCircleRecombine(const FReducer& Reducer) { return Reducer.IsCircleRecombine(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FCircleRecombineArgs GetAsCircleRecombine(const FReducer& Reducer) { + return Reducer.GetAsCircleRecombine(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer Connect(const FConnectArgs& Value) { + return FReducer::Connect(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsConnect(const FReducer& Reducer) { return Reducer.IsConnect(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FConnectArgs GetAsConnect(const FReducer& Reducer) { + return Reducer.GetAsConnect(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer ConsumeEntity(const FConsumeEntityArgs& Value) { + return FReducer::ConsumeEntity(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsConsumeEntity(const FReducer& Reducer) { return Reducer.IsConsumeEntity(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FConsumeEntityArgs GetAsConsumeEntity(const FReducer& Reducer) { + return Reducer.GetAsConsumeEntity(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer Disconnect(const FDisconnectArgs& Value) { + return FReducer::Disconnect(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsDisconnect(const FReducer& Reducer) { return Reducer.IsDisconnect(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FDisconnectArgs GetAsDisconnect(const FReducer& Reducer) { + return Reducer.GetAsDisconnect(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer EnterGame(const FEnterGameArgs& Value) { + return FReducer::EnterGame(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsEnterGame(const FReducer& Reducer) { return Reducer.IsEnterGame(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FEnterGameArgs GetAsEnterGame(const FReducer& Reducer) { + return Reducer.GetAsEnterGame(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer MoveAllPlayers(const FMoveAllPlayersArgs& Value) { + return FReducer::MoveAllPlayers(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsMoveAllPlayers(const FReducer& Reducer) { return Reducer.IsMoveAllPlayers(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FMoveAllPlayersArgs GetAsMoveAllPlayers(const FReducer& Reducer) { + return Reducer.GetAsMoveAllPlayers(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer PlayerSplit(const FPlayerSplitArgs& Value) { + return FReducer::PlayerSplit(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsPlayerSplit(const FReducer& Reducer) { return Reducer.IsPlayerSplit(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FPlayerSplitArgs GetAsPlayerSplit(const FReducer& Reducer) { + return Reducer.GetAsPlayerSplit(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer Respawn(const FRespawnArgs& Value) { + return FReducer::Respawn(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsRespawn(const FReducer& Reducer) { return Reducer.IsRespawn(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FRespawnArgs GetAsRespawn(const FReducer& Reducer) { + return Reducer.GetAsRespawn(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer SpawnFood(const FSpawnFoodArgs& Value) { + return FReducer::SpawnFood(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsSpawnFood(const FReducer& Reducer) { return Reducer.IsSpawnFood(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FSpawnFoodArgs GetAsSpawnFood(const FReducer& Reducer) { + return Reducer.GetAsSpawnFood(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer Suicide(const FSuicideArgs& Value) { + return FReducer::Suicide(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsSuicide(const FReducer& Reducer) { return Reducer.IsSuicide(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FSuicideArgs GetAsSuicide(const FReducer& Reducer) { + return Reducer.GetAsSuicide(); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|Reducer") + static FReducer UpdatePlayerInput(const FUpdatePlayerInputArgs& Value) { + return FReducer::UpdatePlayerInput(Value); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static bool IsUpdatePlayerInput(const FReducer& Reducer) { return Reducer.IsUpdatePlayerInput(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|Reducer") + static FUpdatePlayerInputArgs GetAsUpdatePlayerInput(const FReducer& Reducer) { + return Reducer.GetAsUpdatePlayerInput(); + } +}; + +/** Metadata describing a reducer run. */ +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FClientUnrealReducerEvent +{ + GENERATED_BODY() + + /** Timestamp for when the reducer executed */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBTimestamp Timestamp; + + /** Result status of the reducer */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBStatus Status; + + /** Identity that initiated the call */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBIdentity CallerIdentity; + + /** Connection ID for the caller */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FSpacetimeDBConnectionId CallerConnectionId; + + /** Energy consumed while executing */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FEnergyQuantaType EnergyConsumed; + + /** Detailed call information */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="SpacetimeDB") + FReducer Reducer; + + FORCEINLINE bool operator==(const FClientUnrealReducerEvent& Other) const + { + return Status == Other.Status && Timestamp == Other.Timestamp && CallerIdentity == Other.CallerIdentity && + CallerConnectionId == Other.CallerConnectionId && EnergyConsumed == Other.EnergyConsumed && + Reducer == Other.Reducer; + } + + FORCEINLINE bool operator!=(const FClientUnrealReducerEvent& Other) const + { + return !(*this == Other); + } +}; + +/** Represents event with variant message data. */ +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FClientUnrealEvent +{ + GENERATED_BODY() + + /** Tagged union holding reducer call, unit events, or error string */ + TVariant MessageData; + + /** Type tag indicating what this event represents */ + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + ESpacetimeDBEventTag Tag = ESpacetimeDBEventTag::UnknownTransaction; + + /** === Static factory methods ===*/ + static FClientUnrealEvent Reducer(const FReducer& Value) + { + FClientUnrealEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Reducer; + Obj.MessageData.Set(Value); + return Obj; + } + + static FClientUnrealEvent SubscribeApplied(const FSpacetimeDBUnit& Value) + { + FClientUnrealEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::SubscribeApplied; + Obj.MessageData.Set(Value); + return Obj; + } + + static FClientUnrealEvent UnsubscribeApplied(const FSpacetimeDBUnit& Value) + { + FClientUnrealEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::UnsubscribeApplied; + Obj.MessageData.Set(Value); + return Obj; + } + + static FClientUnrealEvent Disconnected(const FSpacetimeDBUnit& Value) + { + FClientUnrealEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::Disconnected; + Obj.MessageData.Set(Value); + return Obj; + } + + static FClientUnrealEvent SubscribeError(const FString& Value) + { + FClientUnrealEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::SubscribeError; + Obj.MessageData.Set(Value); + return Obj; + } + + static FClientUnrealEvent UnknownTransaction(const FSpacetimeDBUnit& Value) + { + FClientUnrealEvent Obj; + Obj.Tag = ESpacetimeDBEventTag::UnknownTransaction; + Obj.MessageData.Set(Value); + return Obj; + } + + FORCEINLINE bool IsReducer() const { return Tag == ESpacetimeDBEventTag::Reducer; } + FORCEINLINE FReducer GetAsReducer() const + { + ensureMsgf(IsReducer(), TEXT("MessageData does not hold Reducer!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsSubscribeApplied() const { return Tag == ESpacetimeDBEventTag::SubscribeApplied; } + FORCEINLINE FSpacetimeDBUnit GetAsSubscribeApplied() const + { + ensureMsgf(IsSubscribeApplied(), TEXT("MessageData does not hold SubscribeApplied!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsUnsubscribeApplied() const { return Tag == ESpacetimeDBEventTag::UnsubscribeApplied; } + FORCEINLINE FSpacetimeDBUnit GetAsUnsubscribeApplied() const + { + ensureMsgf(IsUnsubscribeApplied(), TEXT("MessageData does not hold UnsubscribeApplied!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsDisconnected() const { return Tag == ESpacetimeDBEventTag::Disconnected; } + FORCEINLINE FSpacetimeDBUnit GetAsDisconnected() const + { + ensureMsgf(IsDisconnected(), TEXT("MessageData does not hold Disconnected!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsSubscribeError() const { return Tag == ESpacetimeDBEventTag::SubscribeError; } + FORCEINLINE FString GetAsSubscribeError() const + { + ensureMsgf(IsSubscribeError(), TEXT("MessageData does not hold SubscribeError!")); + return MessageData.Get(); + } + + FORCEINLINE bool IsUnknownTransaction() const { return Tag == ESpacetimeDBEventTag::UnknownTransaction; } + FORCEINLINE FSpacetimeDBUnit GetAsUnknownTransaction() const + { + ensureMsgf(IsUnknownTransaction(), TEXT("MessageData does not hold UnknownTransaction!")); + return MessageData.Get(); + } + + FORCEINLINE bool operator==(const FClientUnrealEvent& Other) const + { + if (Tag != Other.Tag) return false; + switch (Tag) + { + case ESpacetimeDBEventTag::Reducer: return GetAsReducer() == Other.GetAsReducer(); + case ESpacetimeDBEventTag::SubscribeApplied: return GetAsSubscribeApplied() == Other.GetAsSubscribeApplied(); + case ESpacetimeDBEventTag::UnsubscribeApplied: return GetAsUnsubscribeApplied() == Other.GetAsUnsubscribeApplied(); + case ESpacetimeDBEventTag::Disconnected: return GetAsDisconnected() == Other.GetAsDisconnected(); + case ESpacetimeDBEventTag::SubscribeError: return GetAsSubscribeError() == Other.GetAsSubscribeError(); + case ESpacetimeDBEventTag::UnknownTransaction: return GetAsUnknownTransaction() == Other.GetAsUnknownTransaction(); + default: return false; + } + } + + FORCEINLINE bool operator!=(const FClientUnrealEvent& Other) const + { + return !(*this == Other); + } +}; + +UCLASS() +class CLIENT_UNREAL_API UClientUnrealEventBpLib : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +private: + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|ClientUnrealEvent") + static FClientUnrealEvent Reducer(const FReducer& InValue) + { + return FClientUnrealEvent::Reducer(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|ClientUnrealEvent") + static FClientUnrealEvent SubscribeApplied(const FSpacetimeDBUnit& InValue) + { + return FClientUnrealEvent::SubscribeApplied(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|ClientUnrealEvent") + static FClientUnrealEvent UnsubscribeApplied(const FSpacetimeDBUnit& InValue) + { + return FClientUnrealEvent::UnsubscribeApplied(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|ClientUnrealEvent") + static FClientUnrealEvent Disconnected(const FSpacetimeDBUnit& InValue) + { + return FClientUnrealEvent::Disconnected(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|ClientUnrealEvent") + static FClientUnrealEvent SubscribeError(const FString& InValue) + { + return FClientUnrealEvent::SubscribeError(InValue); + } + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB|ClientUnrealEvent") + static FClientUnrealEvent UnknownTransaction(const FSpacetimeDBUnit& InValue) + { + return FClientUnrealEvent::UnknownTransaction(InValue); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static bool IsReducer(const FClientUnrealEvent& Event) { return Event.IsReducer(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static bool IsSubscribeApplied(const FClientUnrealEvent& Event) { return Event.IsSubscribeApplied(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static bool IsUnsubscribeApplied(const FClientUnrealEvent& Event) { return Event.IsUnsubscribeApplied(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static bool IsDisconnected(const FClientUnrealEvent& Event) { return Event.IsDisconnected(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static bool IsSubscribeError(const FClientUnrealEvent& Event) { return Event.IsSubscribeError(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static bool IsUnknownTransaction(const FClientUnrealEvent& Event) { return Event.IsUnknownTransaction(); } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static FReducer GetAsReducer(const FClientUnrealEvent& Event) + { + return Event.GetAsReducer(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static FSpacetimeDBUnit GetAsSubscribeApplied(const FClientUnrealEvent& Event) + { + return Event.GetAsSubscribeApplied(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static FSpacetimeDBUnit GetAsUnsubscribeApplied(const FClientUnrealEvent& Event) + { + return Event.GetAsUnsubscribeApplied(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static FSpacetimeDBUnit GetAsDisconnected(const FClientUnrealEvent& Event) + { + return Event.GetAsDisconnected(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static FString GetAsSubscribeError(const FClientUnrealEvent& Event) + { + return Event.GetAsSubscribeError(); + } + + UFUNCTION(BlueprintPure, Category = "SpacetimeDB|ClientUnrealEvent") + static FSpacetimeDBUnit GetAsUnknownTransaction(const FClientUnrealEvent& Event) + { + return Event.GetAsUnknownTransaction(); + } + +}; + + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FEventContext : public FContextBase +{ + GENERATED_BODY() + + FEventContext() = default; + FEventContext(UDbConnection* InConn, const FClientUnrealEvent& InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FClientUnrealEvent Event; +}; + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FReducerEventContext : public FContextBase +{ + GENERATED_BODY() + + FReducerEventContext() = default; + FReducerEventContext(UDbConnection* InConn, FClientUnrealReducerEvent InEvent) : FContextBase(InConn), Event(InEvent) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FClientUnrealReducerEvent Event; +}; + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FErrorContext : public FContextBase +{ + GENERATED_BODY() + + FErrorContext() = default; + FErrorContext(UDbConnection* InConn, const FString& InError) : FContextBase(InConn), Error(InError) {} + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + FString Error; + +}; + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FSubscriptionEventContext : public FContextBase +{ + GENERATED_BODY() + + FSubscriptionEventContext() = default; + FSubscriptionEventContext(UDbConnection* InConn) : FContextBase(InConn) {} + +}; + +DECLARE_DYNAMIC_DELEGATE_OneParam( + FOnSubscriptionApplied, + FSubscriptionEventContext, Context); + +DECLARE_DYNAMIC_DELEGATE_OneParam( + FOnSubscriptionError, + FErrorContext, Context); + +UCLASS(BlueprintType) +class CLIENT_UNREAL_API USetReducerFlags : public USetReducerFlagsBase +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void CircleDecay(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void CircleRecombine(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void Connect(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void ConsumeEntity(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void Disconnect(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void EnterGame(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void MoveAllPlayers(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void PlayerSplit(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void Respawn(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void SpawnFood(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void Suicide(ECallReducerFlags Flag); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + void UpdatePlayerInput(ECallReducerFlags Flag); + +}; + +// RemoteTables class +UCLASS(BlueprintType) +class CLIENT_UNREAL_API URemoteTables : public UObject +{ + GENERATED_BODY() + +public: + void Initialize(); + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UEntityTable* LoggedOutEntity; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UMoveAllPlayersTimerTable* MoveAllPlayersTimer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UCircleDecayTimerTable* CircleDecayTimer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UEntityTable* Entity; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UFoodTable* Food; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UCircleRecombineTimerTable* CircleRecombineTimer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UConfigTable* Config; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UPlayerTable* LoggedOutPlayer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UCircleTable* LoggedOutCircle; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UPlayerTable* Player; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UConsumeEntityTimerTable* ConsumeEntityTimer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + USpawnFoodTimerTable* SpawnFoodTimer; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + UCircleTable* Circle; + +}; + +// RemoteReducers class +UCLASS(BlueprintType) +class CLIENT_UNREAL_API URemoteReducers : public UObject +{ + GENERATED_BODY() + +public: + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FCircleDecayHandler, + const FReducerEventContext&, Context, + const FCircleDecayTimerType&, Timer + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FCircleDecayHandler OnCircleDecay; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void CircleDecay(const FCircleDecayTimerType& Timer); + + bool InvokeCircleDecay(const FReducerEventContext& Context, const UCircleDecayReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FCircleRecombineHandler, + const FReducerEventContext&, Context, + const FCircleRecombineTimerType&, Timer + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FCircleRecombineHandler OnCircleRecombine; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void CircleRecombine(const FCircleRecombineTimerType& Timer); + + bool InvokeCircleRecombine(const FReducerEventContext& Context, const UCircleRecombineReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( + FConnectHandler, + const FReducerEventContext&, Context + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FConnectHandler OnConnect; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void Connect(); + + bool InvokeConnect(const FReducerEventContext& Context, const UConnectReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FConsumeEntityHandler, + const FReducerEventContext&, Context, + const FConsumeEntityTimerType&, Request + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FConsumeEntityHandler OnConsumeEntity; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void ConsumeEntity(const FConsumeEntityTimerType& Request); + + bool InvokeConsumeEntity(const FReducerEventContext& Context, const UConsumeEntityReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( + FDisconnectHandler, + const FReducerEventContext&, Context + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FDisconnectHandler OnDisconnect; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void Disconnect(); + + bool InvokeDisconnect(const FReducerEventContext& Context, const UDisconnectReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FEnterGameHandler, + const FReducerEventContext&, Context, + const FString&, Name + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FEnterGameHandler OnEnterGame; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void EnterGame(const FString& Name); + + bool InvokeEnterGame(const FReducerEventContext& Context, const UEnterGameReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FMoveAllPlayersHandler, + const FReducerEventContext&, Context, + const FMoveAllPlayersTimerType&, Timer + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FMoveAllPlayersHandler OnMoveAllPlayers; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void MoveAllPlayers(const FMoveAllPlayersTimerType& Timer); + + bool InvokeMoveAllPlayers(const FReducerEventContext& Context, const UMoveAllPlayersReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( + FPlayerSplitHandler, + const FReducerEventContext&, Context + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FPlayerSplitHandler OnPlayerSplit; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void PlayerSplit(); + + bool InvokePlayerSplit(const FReducerEventContext& Context, const UPlayerSplitReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( + FRespawnHandler, + const FReducerEventContext&, Context + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FRespawnHandler OnRespawn; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void Respawn(); + + bool InvokeRespawn(const FReducerEventContext& Context, const URespawnReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FSpawnFoodHandler, + const FReducerEventContext&, Context, + const FSpawnFoodTimerType&, Timer + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FSpawnFoodHandler OnSpawnFood; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void SpawnFood(const FSpawnFoodTimerType& Timer); + + bool InvokeSpawnFood(const FReducerEventContext& Context, const USpawnFoodReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( + FSuicideHandler, + const FReducerEventContext&, Context + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FSuicideHandler OnSuicide; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void Suicide(); + + bool InvokeSuicide(const FReducerEventContext& Context, const USuicideReducer* Args); + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FUpdatePlayerInputHandler, + const FReducerEventContext&, Context, + const FDbVector2Type&, Direction + ); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FUpdatePlayerInputHandler OnUpdatePlayerInput; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + void UpdatePlayerInput(const FDbVector2Type& Direction); + + bool InvokeUpdatePlayerInput(const FReducerEventContext& Context, const UUpdatePlayerInputReducer* Args); + + // Internal error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); + FInternalOnUnhandledReducerError InternalOnUnhandledReducerError; + +private: + + friend UDbConnection; + + UPROPERTY() + class UDbConnection* Conn; + + UPROPERTY() + USetReducerFlags* SetCallReducerFlags; +}; + +// SubscriptionBuilder class +UCLASS(BlueprintType) +class CLIENT_UNREAL_API USubscriptionBuilder : public USubscriptionBuilderBase +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionBuilder* OnApplied(FOnSubscriptionApplied Callback); + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionBuilder* OnError(FOnSubscriptionError Callback); + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionHandle* Subscribe(const TArray& SQL); + + /** Convenience for subscribing to all rows from all tables */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + USubscriptionHandle* SubscribeToAllTables(); + + + friend class UDbConnection; + friend class UDbConnectionBase; + +protected: + UPROPERTY() + class UDbConnection* Conn; + + // Delegates stored so Subscribe() can bind forwarding callbacks + FOnSubscriptionApplied OnAppliedDelegateInternal; + FOnSubscriptionError OnErrorDelegateInternal; +}; + +// SubscriptionHandle class +UCLASS(BlueprintType) +class CLIENT_UNREAL_API USubscriptionHandle : public USubscriptionHandleBase +{ + GENERATED_BODY() + +public: + + USubscriptionHandle() {}; + + explicit USubscriptionHandle(UDbConnection* InConn); + + friend class USubscriptionBuilder; + +private: + UPROPERTY() + class UDbConnection* Conn; + + // Delegates that expose subscription events with connection aware contexts + FOnSubscriptionApplied OnAppliedDelegate; + FOnSubscriptionError OnErrorDelegate; + + UFUNCTION() + void ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx); + + UFUNCTION() + void ForwardOnError(const FErrorContextBase& BaseCtx); +}; + +/* + @Note: Child class of UDbConnectionBuilderBase. +*/ +UCLASS(BlueprintType) +class CLIENT_UNREAL_API UDbConnectionBuilder : public UDbConnectionBuilderBase +{ + GENERATED_BODY() +public: + + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithUri(const FString& InUri); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithModuleName(const FString& InName); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithToken(const FString& InToken); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* WithCompression(const ESpacetimeDBCompression& InCompression); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnConnect(FOnConnectDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnConnectError(FOnConnectErrorDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnectionBuilder* OnDisconnect(FOnDisconnectDelegate Callback); + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB") + UDbConnection* Build(); + +private: + + // Stored delegates which will be forwarded when the connection events occur. + FOnConnectDelegate OnConnectDelegateInternal; + FOnDisconnectDelegate OnDisconnectDelegateInternal; +}; + +// Main DbConnection class +UCLASS(BlueprintType) +class CLIENT_UNREAL_API UDbConnection : public UDbConnectionBase +{ + GENERATED_BODY() + +public: + explicit UDbConnection(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteTables* Db; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + URemoteReducers* Reducers; + + UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") + USetReducerFlags* SetReducerFlags; + + // Delegates that allow users to bind with the concrete connection type. + FOnConnectDelegate OnConnectDelegate; + FOnDisconnectDelegate OnDisconnectDelegate; + + UFUNCTION(BlueprintCallable, Category="SpacetimeDB") + USubscriptionBuilder* SubscriptionBuilder(); + + /** Static entry point for constructing a connection. */ + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB", DisplayName = "SpacetimeDB Builder") + static UDbConnectionBuilder* Builder(); + + // Error handling + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error); + UPROPERTY(BlueprintAssignable, Category="SpacetimeDB") + FOnUnhandledReducerError OnUnhandledReducerError; + + +protected: + + // Hook up error handling to reducers + virtual void PostInitProperties() override; + + UFUNCTION() + void ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken); + UFUNCTION() + void ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error); + + UFUNCTION() + void OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error); + + // Override the DbConnectionBase methods to handle updates and events + virtual void DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event) override; + + // Override the reducer event handler to dispatch events to the appropriate reducers + virtual void ReducerEvent(const FReducerEvent& Event) override; + + // Override the reducer event failed handler + virtual void ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage) override; +}; + diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h new file mode 100644 index 000000000..67734c5a8 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleDecayTimerTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h new file mode 100644 index 000000000..fa2584ed4 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleRecombineTimerTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h new file mode 100644 index 000000000..645dc04c5 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/CircleTable.g.h @@ -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> 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> InCircleCache) + { + EntityIdIndexHelper.Cache = InCircleCache; + } +}; +/***/ + +UCLASS(Blueprintable) +class UCirclePlayerIdIndex : public UObject +{ + GENERATED_BODY() + +public: + TArray Filter(const uint32& PlayerId) const + { + TArray OutResults; + + LocalCache->FindByMultiKeyBTreeIndex>( + OutResults, + TEXT("player_id"), + MakeTuple(PlayerId) + ); + + return OutResults; + } + + void SetCache(TSharedPtr> InCache) + { + LocalCache = InCache; + } + +private: + // NOTE: Not exposed to Blueprint because some parameter types are not Blueprint-compatible + void FilterPlayerId(TArray& OutResults, const uint32& PlayerId) + { + OutResults = Filter(PlayerId); + } + + TSharedPtr> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConfigTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConfigTable.g.h new file mode 100644 index 000000000..3efa76559 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConfigTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h new file mode 100644 index 000000000..f07cca059 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/ConsumeEntityTimerTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/EntityTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/EntityTable.g.h new file mode 100644 index 000000000..ac15afa51 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/EntityTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/FoodTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/FoodTable.g.h new file mode 100644 index 000000000..1e1893796 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/FoodTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h new file mode 100644 index 000000000..5e81ed977 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/MoveAllPlayersTimerTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h new file mode 100644 index 000000000..e22c9590c --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/PlayerTable.g.h @@ -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> 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> 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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h new file mode 100644 index 000000000..362243f28 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Tables/SpawnFoodTimerTable.g.h @@ -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> 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> 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 Update(TArray> InsertsRef, TArray> 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 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> Data; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleDecayTimerType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleDecayTimerType.g.h new file mode 100644 index 000000000..998d85a4e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleDecayTimerType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleRecombineTimerType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleRecombineTimerType.g.h new file mode 100644 index 000000000..dd5197710 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleRecombineTimerType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleType.g.h new file mode 100644 index 000000000..f4169b7a3 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/CircleType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/ConfigType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/ConfigType.g.h new file mode 100644 index 000000000..deace670b --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/ConfigType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/ConsumeEntityTimerType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/ConsumeEntityTimerType.g.h new file mode 100644 index 000000000..3f1eada55 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/ConsumeEntityTimerType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/DbVector2Type.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/DbVector2Type.g.h new file mode 100644 index 000000000..5eae3d926 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/DbVector2Type.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/EntityType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/EntityType.g.h new file mode 100644 index 000000000..d95e3567c --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/EntityType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/FoodType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/FoodType.g.h new file mode 100644 index 000000000..48e069952 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/FoodType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/MoveAllPlayersTimerType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/MoveAllPlayersTimerType.g.h new file mode 100644 index 000000000..5bd566a94 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/MoveAllPlayersTimerType.g.h @@ -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); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/PlayerType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/PlayerType.g.h new file mode 100644 index 000000000..e50121102 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/PlayerType.g.h @@ -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 "PlayerType.g.generated.h" + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FPlayerType +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FSpacetimeDBIdentity Identity; + + // NOTE: uint32 field not exposed to Blueprint due to non-blueprintable elements + uint32 PlayerId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") + FString Name; + + FORCEINLINE bool operator==(const FPlayerType& Other) const + { + return Identity == Other.Identity && PlayerId == Other.PlayerId && Name == Other.Name; + } + + FORCEINLINE bool operator!=(const FPlayerType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FPlayerType. + * Combines the hashes of all fields that are compared in operator==. + * @param PlayerType The FPlayerType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FPlayerType& PlayerType) +{ + uint32 Hash = GetTypeHash(PlayerType.Identity); + Hash = HashCombine(Hash, GetTypeHash(PlayerType.PlayerId)); + Hash = HashCombine(Hash, GetTypeHash(PlayerType.Name)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FPlayerType); + + UE_SPACETIMEDB_STRUCT(FPlayerType, Identity, PlayerId, Name); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/SpawnFoodTimerType.g.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/SpawnFoodTimerType.g.h new file mode 100644 index 000000000..51cc04b32 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/ModuleBindings/Types/SpawnFoodTimerType.g.h @@ -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 "SpawnFoodTimerType.g.generated.h" + +USTRUCT(BlueprintType) +struct CLIENT_UNREAL_API FSpawnFoodTimerType +{ + 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 FSpawnFoodTimerType& Other) const + { + return ScheduledId == Other.ScheduledId && ScheduledAt == Other.ScheduledAt; + } + + FORCEINLINE bool operator!=(const FSpawnFoodTimerType& Other) const + { + return !(*this == Other); + } +}; + +/** + * Custom hash function for FSpawnFoodTimerType. + * Combines the hashes of all fields that are compared in operator==. + * @param SpawnFoodTimerType The FSpawnFoodTimerType instance to hash. + * @return The combined hash value. + */ +FORCEINLINE uint32 GetTypeHash(const FSpawnFoodTimerType& SpawnFoodTimerType) +{ + uint32 Hash = GetTypeHash(SpawnFoodTimerType.ScheduledId); + Hash = HashCombine(Hash, GetTypeHash(SpawnFoodTimerType.ScheduledAt)); + return Hash; +} + +namespace UE::SpacetimeDB +{ + UE_SPACETIMEDB_ENABLE_TARRAY(FSpawnFoodTimerType); + + UE_SPACETIMEDB_STRUCT(FSpawnFoodTimerType, ScheduledId, ScheduledAt); +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/Public/PlayerPawn.h b/demo/Blackholio/client-unreal/Source/client_unreal/Public/PlayerPawn.h new file mode 100644 index 000000000..8215e4f0e --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/Public/PlayerPawn.h @@ -0,0 +1,61 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Pawn.h" +#include "PlayerPawn.generated.h" + +class ACircle; +struct FPlayerType; +class UCameraComponent; +class USpringArmComponent; + +UCLASS() +class CLIENT_UNREAL_API APlayerPawn : public APawn +{ + GENERATED_BODY() + +public: + APlayerPawn(); + void Initialize(FPlayerType Player); + + uint32 PlayerId = 0; + UPROPERTY(BlueprintReadWrite, Category="BH|Player") + bool bIsLocalPlayer = false; + + UPROPERTY() + TArray> OwnedCircles; + + UFUNCTION() + FString GetUsername() const; + UFUNCTION() + void OnCircleSpawned(ACircle* Circle); + UFUNCTION() + void OnCircleDeleted(ACircle* Circle); + + UFUNCTION(BlueprintCallable, Category="BH|Input") + void Split(); + UFUNCTION(BlueprintCallable, Category="BH|Input") + void Suicide(); + + uint32 TotalMass() const; + UFUNCTION(BlueprintPure, Category="BH|Player") + FVector CenterOfMass() const; + +protected: + virtual void Destroyed() override; + UPROPERTY(EditDefaultsOnly, Category="BH|Camera") + float BaseSize = 50.f; + UPROPERTY(EditDefaultsOnly, Category="BH|Camera") + float MassToSizeDivisor = 5.f; + UPROPERTY(EditDefaultsOnly, Category="BH|Camera") + float MaxMassBonus = 50.f; + UPROPERTY(EditDefaultsOnly, Category="BH|Camera") + float SplitBonus = 30.f; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + TObjectPtr SpringArm; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + TObjectPtr Camera; +public: + virtual void Tick(float DeltaTime) override; +}; diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.Build.cs b/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.Build.cs new file mode 100644 index 000000000..9b3242194 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.Build.cs @@ -0,0 +1,37 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class client_unreal : ModuleRules +{ + public client_unreal(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "EnhancedInput", + "SpacetimeDbSdk", + "Paper2D" + }); + + PrivateDependencyModuleNames.AddRange(new string[] + { + "UMG", + "SlateCore", + "Slate" + }); + + // Uncomment if you are using Slate UI + // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); + + // Uncomment if you are using online features + // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + + // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true + } +} diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.cpp b/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.cpp new file mode 100644 index 000000000..9b2cb8261 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.cpp @@ -0,0 +1,6 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "client_unreal.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, client_unreal, "client_unreal" ); diff --git a/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.h b/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.h new file mode 100644 index 000000000..677c8e25b --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unreal/client_unreal.h @@ -0,0 +1,6 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" + diff --git a/demo/Blackholio/client-unreal/Source/client_unrealEditor.Target.cs b/demo/Blackholio/client-unreal/Source/client_unrealEditor.Target.cs new file mode 100644 index 000000000..1e073cfc5 --- /dev/null +++ b/demo/Blackholio/client-unreal/Source/client_unrealEditor.Target.cs @@ -0,0 +1,15 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class client_unrealEditorTarget : TargetRules +{ + public client_unrealEditorTarget( TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V5; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_6; + ExtraModuleNames.Add("client_unreal"); + } +} diff --git a/demo/Blackholio/client-unreal/client_unreal.uproject b/demo/Blackholio/client-unreal/client_unreal.uproject new file mode 100644 index 000000000..513949e4d --- /dev/null +++ b/demo/Blackholio/client-unreal/client_unreal.uproject @@ -0,0 +1,28 @@ +{ + "FileVersion": 3, + "EngineAssociation": "5.6", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "client_unreal", + "Type": "Runtime", + "LoadingPhase": "Default", + "AdditionalDependencies": [ + "Engine" + ] + } + ], + "Plugins": [ + { + "Name": "ModelingToolsEditorMode", + "Enabled": true, + "TargetAllowList": [ + "Editor" + ] + } + ], + "AdditionalPluginDirectories": [ + "../../../sdks/unreal/src" + ] +} \ No newline at end of file diff --git a/demo/Blackholio/server-csharp/generate.bat b/demo/Blackholio/server-csharp/generate.bat new file mode 100644 index 000000000..9a58365cb --- /dev/null +++ b/demo/Blackholio/server-csharp/generate.bat @@ -0,0 +1,2 @@ +spacetime generate --out-dir ../client-unity/Assets/Scripts/autogen -y --lang cs +spacetime generate --lang unrealcpp --uproject-dir ../client-unreal --project-path ./ --module-name client_unreal diff --git a/demo/Blackholio/server-csharp/generate.sh b/demo/Blackholio/server-csharp/generate.sh index b9c25552d..d21e860e0 100644 --- a/demo/Blackholio/server-csharp/generate.sh +++ b/demo/Blackholio/server-csharp/generate.sh @@ -3,3 +3,4 @@ set -euo pipefail spacetime generate --out-dir ../client-unity/Assets/Scripts/autogen --lang cs $@ +spacetime generate --lang unrealcpp --uproject-dir ../client-unreal --project-path ./ --module-name client_unreal diff --git a/demo/Blackholio/server-csharp/publish.bat b/demo/Blackholio/server-csharp/publish.bat new file mode 100644 index 000000000..d9b60d8bb --- /dev/null +++ b/demo/Blackholio/server-csharp/publish.bat @@ -0,0 +1 @@ +spacetime publish -s local -c -y blackholio \ No newline at end of file diff --git a/demo/Blackholio/server-rust/generate.bat b/demo/Blackholio/server-rust/generate.bat index 6fabe2009..9a58365cb 100644 --- a/demo/Blackholio/server-rust/generate.bat +++ b/demo/Blackholio/server-rust/generate.bat @@ -1 +1,2 @@ spacetime generate --out-dir ../client-unity/Assets/Scripts/autogen -y --lang cs +spacetime generate --lang unrealcpp --uproject-dir ../client-unreal --project-path ./ --module-name client_unreal diff --git a/demo/Blackholio/server-rust/generate.sh b/demo/Blackholio/server-rust/generate.sh index b9c25552d..d21e860e0 100755 --- a/demo/Blackholio/server-rust/generate.sh +++ b/demo/Blackholio/server-rust/generate.sh @@ -3,3 +3,4 @@ set -euo pipefail spacetime generate --out-dir ../client-unity/Assets/Scripts/autogen --lang cs $@ +spacetime generate --lang unrealcpp --uproject-dir ../client-unreal --project-path ./ --module-name client_unreal