SanAndreasUnity/Assets/Scripts/Behaviours/Ped/Ped_Networking.cs

260 lines
8.7 KiB
C#
Raw Normal View History

2019-04-23 23:59:56 +00:00
using System.Collections.Generic;
using UnityEngine;
using Mirror;
2019-04-25 23:39:07 +00:00
using System.Linq;
using SanAndreasUnity.Utilities;
2019-04-27 13:36:44 +00:00
using SanAndreasUnity.Net;
2019-04-23 23:59:56 +00:00
namespace SanAndreasUnity.Behaviours
{
public partial class Ped
{
public NetworkTransform NetTransform { get; private set; }
[Range(1f / 60f, 0.5f)] [SerializeField] float m_inputSendInterval = 1f / 30f;
float m_timeSinceSentInput = 0f;
[SyncVar] GameObject m_net_playerOwnerGameObject;
internal GameObject NetPlayerOwnerGameObject { set { m_net_playerOwnerGameObject = value; } }
public Player PlayerOwner => Player.GetOwningPlayer(this);
2019-04-23 23:59:56 +00:00
[SyncVar(hook=nameof(Net_OnIdChanged))] int m_net_pedId = 0;
struct StateSyncData
{
public string state;
public string additionalData;
}
//[SyncVar(hook=nameof(Net_OnStateChanged))] StateSyncData m_net_stateData;
[SyncVar] string m_net_additionalStateData = "";
[SyncVar(hook=nameof(Net_OnStateChanged))] string m_net_state = "";
2019-04-23 23:59:56 +00:00
//[SyncVar] Weapon m_net_weapon = null;
2019-05-25 23:51:29 +00:00
public static int NumStateChangesReceived { get; private set; }
public class SyncDictionaryStringUint : Mirror.SyncDictionary<string, uint> { }
public SyncDictionaryStringUint syncDictionaryStringUint = new SyncDictionaryStringUint();
2019-07-07 21:41:18 +00:00
[SyncVar] Vector3 m_net_movementInput;
[SyncVar] Vector3 m_net_heading;
2019-07-08 14:25:33 +00:00
[SyncVar] float m_net_health;
2019-07-06 22:46:47 +00:00
//[SyncVar(hook=nameof(Net_OnWeaponChanged))] GameObject m_net_weaponGameObject;
[SyncVar(hook=nameof(Net_OnWeaponChanged))] int m_net_currentWeaponSlot;
2019-07-06 16:05:21 +00:00
2019-07-07 00:09:06 +00:00
[SyncVar] internal Vector3 m_net_aimDir;
2019-07-12 23:20:12 +00:00
public Vector3 NetFirePos { get; set; }
2019-07-12 20:17:22 +00:00
public Vector3 NetFireDir { get; set; }
2019-07-07 00:09:06 +00:00
2019-04-23 23:59:56 +00:00
void Awake_Net()
{
this.NetTransform = this.GetComponentOrThrow<NetworkTransform>();
2019-04-23 23:59:56 +00:00
}
2019-04-24 00:50:28 +00:00
public override void OnStartClient()
{
base.OnStartClient();
if (this.isServer)
return;
// owner player sync var should point to created game object, because player's game object is always created before
// ped's game object
// assign var in Player script
if (m_net_playerOwnerGameObject != null)
m_net_playerOwnerGameObject.GetComponent<Player>().OwnedPed = this;
this.TryToLoadNewModel(m_net_pedId);
2019-07-06 22:46:47 +00:00
// switch weapon
F.RunExceptionSafe( () => this.WeaponHolder.SwitchWeapon(m_net_currentWeaponSlot) );
this.ChangeStateBasedOnSyncData(new StateSyncData(){state = m_net_state, additionalData = m_net_additionalStateData});
2019-04-24 00:50:28 +00:00
}
2019-05-24 21:51:39 +00:00
void Start_Net()
{
this.ApplySyncRate(PedManager.Instance.pedSyncRate);
}
public void ApplySyncRate(float newSyncRate)
{
float newSyncInterval = 1.0f / newSyncRate;
2019-05-24 21:51:39 +00:00
foreach (var comp in this.GetComponents<NetworkBehaviour>())
comp.syncInterval = newSyncInterval;
// also change it for NetworkTransform, because it can be disabled
if (this.NetTransform != null)
this.NetTransform.syncInterval = newSyncInterval;
2019-05-24 21:51:39 +00:00
}
2019-04-23 23:59:56 +00:00
void Update_Net()
{
if (NetStatus.IsServer)
{
2019-07-07 21:41:18 +00:00
// update syncvars
if (this.PedDef != null && this.PedDef.Id != m_net_pedId)
m_net_pedId = this.PedDef.Id;
2019-04-26 00:23:54 +00:00
string newStateName = this.CurrentState != null ? this.CurrentState.GetType().Name : "";
if (newStateName != m_net_state)
{
// state changed
2019-05-27 01:13:11 +00:00
//Debug.LogFormat("Updating state syncvar - ped {0}, new state {1}, old state {2}", this.netId, newStateName, m_net_state);
//m_net_stateData = new StateSyncData();
2019-05-26 14:52:19 +00:00
// obtain additional data from state
byte[] data = this.CurrentState != null ? this.CurrentState.GetAdditionalNetworkData() : null;
// assign additional data
m_net_additionalStateData = data != null ? System.Convert.ToBase64String(data) : "";
// assign new state
m_net_state = newStateName;
}
2019-07-06 22:46:47 +00:00
2019-07-07 21:41:18 +00:00
if (m_net_movementInput != this.Movement)
m_net_movementInput = this.Movement;
if (m_net_heading != this.Heading)
m_net_heading = this.Heading;
2019-07-08 14:25:33 +00:00
if (m_net_health != this.Health)
m_net_health = this.Health;
2019-08-29 21:31:46 +00:00
Vector3 aimDir = this.AimDirection;
if (m_net_aimDir != aimDir)
m_net_aimDir = aimDir;
2019-07-06 22:46:47 +00:00
if (this.WeaponHolder.CurrentWeaponSlot != m_net_currentWeaponSlot)
{
m_net_currentWeaponSlot = this.WeaponHolder.CurrentWeaponSlot;
}
2019-07-07 21:41:18 +00:00
}
else
{
// apply syncvars
if (!this.IsControlledByLocalPlayer)
{
this.Movement = m_net_movementInput;
this.Heading = m_net_heading;
}
2019-07-08 14:25:33 +00:00
this.Health = m_net_health;
}
// send input to server
if (!NetStatus.IsServer && this.IsControlledByLocalPlayer && PedSync.Local != null)
{
m_timeSinceSentInput += Time.unscaledDeltaTime;
if (m_timeSinceSentInput >= m_inputSendInterval)
{
m_timeSinceSentInput = 0f;
PedSync.Local.SendInput();
}
}
2019-04-26 00:23:54 +00:00
2019-04-23 23:59:56 +00:00
}
2019-04-27 01:11:07 +00:00
void FixedUpdate_Net()
{
2019-04-27 01:11:07 +00:00
}
void TryToLoadNewModel(int newId)
{
if (this.PedDef != null && this.PedDef.Id == newId) // same id
return;
if (newId > 0)
F.RunExceptionSafe( () => this.PlayerModel.Load(newId) );
}
2019-04-23 23:59:56 +00:00
void Net_OnIdChanged(int newId)
{
2019-07-11 15:36:31 +00:00
//Debug.LogFormat("ped (net id {0}) changed model id to {1}", this.netId, newId);
2019-04-25 23:45:11 +00:00
2019-04-23 23:59:56 +00:00
if (this.isServer)
return;
this.TryToLoadNewModel(newId);
2019-04-23 23:59:56 +00:00
}
void Net_OnStateChanged(string newStateName)
2019-04-23 23:59:56 +00:00
{
if (this.isServer)
return;
StateSyncData newStateData = new StateSyncData(){state = newStateName, additionalData = m_net_additionalStateData};
2019-05-27 01:13:11 +00:00
//Debug.LogFormat("Net_OnStateChanged(): ped {0} changed state to {1}", this.netId, newStateData.state);
2019-05-25 23:51:29 +00:00
NumStateChangesReceived ++;
this.ChangeStateBasedOnSyncData(newStateData);
}
void ChangeStateBasedOnSyncData(StateSyncData newStateData)
{
2019-05-27 01:13:11 +00:00
if (string.IsNullOrEmpty(newStateData.state))
{
// don't do anything, this only happens when creating the ped
return;
}
2019-04-25 23:39:07 +00:00
// forcefully change the state
F.RunExceptionSafe( () => {
var newState = this.States.FirstOrDefault(state => state.GetType().Name == newStateData.state);
2019-04-25 23:39:07 +00:00
if (null == newState)
{
Debug.LogErrorFormat("New ped state '{0}' could not be found", newStateData.state);
2019-04-25 23:39:07 +00:00
}
else
{
2019-05-27 01:13:11 +00:00
//Debug.LogFormat("Switching state based on sync data - ped: {0}, state: {1}", this.netId, newState.GetType().Name);
byte[] data = string.IsNullOrEmpty(newStateData.additionalData) ? null : System.Convert.FromBase64String(newStateData.additionalData);
newState.OnSwitchedStateByServer(data);
2019-04-25 23:39:07 +00:00
}
});
2019-05-27 01:13:11 +00:00
2019-04-23 23:59:56 +00:00
}
2019-07-06 22:46:47 +00:00
void Net_OnWeaponChanged(int newSlot)
{
if (NetStatus.IsServer)
return;
F.RunExceptionSafe( () => {
2019-07-11 15:36:31 +00:00
//Debug.LogFormat("weapon slot changed for ped {0} to {1}", this.DescriptionForLogging, newSlot);
if (this.CurrentState != null)
2019-07-06 22:46:47 +00:00
{
//this.CurrentState.OnChangedWeaponByServer(newWeaponGameObject != null ? newWeaponGameObject.GetComponent<Weapon>() : null);
this.CurrentState.OnChangedWeaponByServer(newSlot);
}
});
}
2019-04-23 23:59:56 +00:00
}
}