diff --git a/.idea/.idea.BABA_YAGA/.idea/workspace.xml b/.idea/.idea.BABA_YAGA/.idea/workspace.xml
index ead077d5..732d9261 100644
--- a/.idea/.idea.BABA_YAGA/.idea/workspace.xml
+++ b/.idea/.idea.BABA_YAGA/.idea/workspace.xml
@@ -10,7 +10,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -18,7 +26,6 @@
-
@@ -37,6 +44,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -48,34 +114,34 @@
- {
+ "keyToString": {
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
+ "RunOnceActivity.MCP Project settings loaded": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
+ "RunOnceActivity.cidr.known.project.marker": "true",
+ "RunOnceActivity.git.unshallow": "true",
+ "RunOnceActivity.readMode.enableVisualFormatting": "true",
+ "RunOnceActivity.typescript.service.memoryLimit.init": "true",
+ "cidr.known.project.marker": "true",
+ "codeWithMe.voiceChat.enabledByDefault": "false",
+ "com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
+ "git-widget-placeholder": "main",
+ "junie.onboarding.icon.badge.shown": "true",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "settings.editor.selected.configurable": "preferences.lookFeel",
+ "to.speed.mode.migration.done": "true",
+ "vue.rearranger.settings.migration": "true"
}
-}]]>
+}
-
+
@@ -85,7 +151,7 @@
-
+
@@ -130,6 +196,7 @@
+
diff --git a/Assets/Scripts/Network/BasicSpawner.cs b/Assets/Scripts/Network/BasicSpawner.cs
index f35a2ab1..3b7377fa 100644
--- a/Assets/Scripts/Network/BasicSpawner.cs
+++ b/Assets/Scripts/Network/BasicSpawner.cs
@@ -350,16 +350,12 @@ namespace Hallucinate.UI
public void OnInput(NetworkRunner runner, NetworkInput input)
{
- // var data = new PlayerInputData();
- // if (PlayerStateMachine.Local != null && PlayerStateMachine.Local.Input != null)
- // {
- // data.Direction = PlayerStateMachine.Local.Input.MoveInput;
- // data.sprint = PlayerStateMachine.Local.Input.IsSprintHeld;
- // data.jump = PlayerStateMachine.Local.Input.ConsumeJumpInput();
- // if (PlayerStateMachine.Local.Cam != null)
- // data.rot = PlayerStateMachine.Local.Cam.PlanarRotation;
- // }
- // input.Set(data);
+ var data = new PlayerInputData();
+ if (Hallucinate.Network.FusionClientMovementBridge.Local != null)
+ {
+ data = Hallucinate.Network.FusionClientMovementBridge.Local.GetLocalInputData();
+ }
+ input.Set(data);
}
public void OnConnectedToServer(NetworkRunner runner) { }
diff --git a/Assets/Scripts/Network/FusionClientMovementBridge.cs b/Assets/Scripts/Network/FusionClientMovementBridge.cs
index 3ac523e7..c832c4d0 100644
--- a/Assets/Scripts/Network/FusionClientMovementBridge.cs
+++ b/Assets/Scripts/Network/FusionClientMovementBridge.cs
@@ -1,26 +1,50 @@
using UnityEngine;
using Fusion;
+using Opsive.Shared.Events;
using Opsive.UltimateCharacterController.Networking;
using Opsive.UltimateCharacterController.Networking.Character;
using Opsive.UltimateCharacterController.Character;
-using Opsive.UltimateCharacterController.Camera; // Corrected namespace
-using Opsive.UltimateCharacterController.Input; // Corrected namespace
-
+using Opsive.UltimateCharacterController.Character.Abilities;
+using Opsive.UltimateCharacterController.Character.Abilities.Items;
+using Opsive.UltimateCharacterController.Camera;
+using Opsive.UltimateCharacterController.Input;
+using OnlyScove.Scripts;
+using Opsive.UltimateCharacterController.Game;
namespace Hallucinate.Network
{
// Ensure Opsive components load before this
[DefaultExecutionOrder(100)]
- public class FusionClientMovementBridge : NetworkBehaviour, INetworkInfo, INetworkCharacter
+ public class FusionClientMovementBridge : NetworkBehaviour, INetworkInfo, INetworkCharacter, ILookSource
{
+ public static FusionClientMovementBridge Local { get; private set; }
+
+ [Networked]
+ public PlayerInputData SyncInput { get; set; }
+
+ private UltimateCharacterLocomotion m_CharacterLocomotion;
+ private UltimateCharacterLocomotionHandler m_LocoHandler;
+ private Opsive.UltimateCharacterController.Input.PlayerInput m_PlayerInput;
+
+ private void Awake()
+ {
+ m_CharacterLocomotion = GetComponent();
+ m_LocoHandler = GetComponent();
+ m_PlayerInput = GetComponent();
+ }
+
public override void Spawned()
{
// Because we passed State Authority to the client in BasicSpawner,
// HasStateAuthority is true ONLY for the local player.
bool isLocal = Object.HasStateAuthority;
+ if (isLocal)
+ {
+ Local = this;
+ }
+
// 1. Isolate Input: Only the local player should read keyboard/mouse inputs.
- var locoHandler = GetComponent();
- if (locoHandler != null) locoHandler.enabled = isLocal;
+ if (m_LocoHandler != null) m_LocoHandler.enabled = isLocal;
var activeInput = GetComponent(); // Corrected class reference
if (activeInput != null) activeInput.enabled = isLocal;
@@ -34,6 +58,150 @@ namespace Hallucinate.Network
cameraController.Character = gameObject;
}
}
+ else
+ {
+ // For remote players, register this bridge as the LookSource
+ EventHandler.ExecuteEvent(gameObject, "OnCharacterAttachLookSource", this);
+ }
+ }
+
+ public override void Despawned(NetworkRunner runner, bool hasState)
+ {
+ if (Local == this)
+ {
+ Local = null;
+ }
+ }
+
+ public override void FixedUpdateNetwork()
+ {
+ if (Object.HasStateAuthority)
+ {
+ if (GetInput(out var input))
+ {
+ SyncInput = input;
+ }
+ }
+
+ if (!Object.HasStateAuthority)
+ {
+ // Ensure look source is attached for remote players
+ if (m_CharacterLocomotion != null && m_CharacterLocomotion.LookSource != (ILookSource)this)
+ {
+ EventHandler.ExecuteEvent(gameObject, "OnCharacterAttachLookSource", this);
+ }
+
+ // Sync the movement inputs to KinematicObjectManager so it moves the remote player character
+ if (m_CharacterLocomotion != null && m_CharacterLocomotion.KinematicObjectIndex != -1)
+ {
+ KinematicObjectManager.SetCharacterMovementInput(
+ m_CharacterLocomotion.KinematicObjectIndex,
+ SyncInput.Direction.x,
+ SyncInput.Direction.y
+ );
+ }
+
+ if (m_CharacterLocomotion != null)
+ {
+ m_CharacterLocomotion.InputVector = SyncInput.InputVector;
+ m_CharacterLocomotion.RawInputVector = SyncInput.RawInputVector;
+ m_CharacterLocomotion.DeltaRotation = SyncInput.DeltaRotation;
+
+ // Sync remote abilities based on state
+ UpdateRemoteAbility(SyncInput.sprint);
+ UpdateRemoteAbility(SyncInput.jump);
+ UpdateRemoteAbility(SyncInput.crouch);
+ UpdateRemoteAbility(SyncInput.aim);
+ UpdateRemoteAbility