syncing works

This commit is contained in:
in0finite 2021-01-05 21:09:25 +01:00
parent f9e320ce23
commit 8d400bfceb
2 changed files with 124 additions and 4 deletions

View file

@ -1,10 +1,19 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Mirror;
using SanAndreasUnity.Importing.Conversion;
using SanAndreasUnity.Importing.Items;
using SanAndreasUnity.Importing.Items.Definitions;
using SanAndreasUnity.Net;
using SanAndreasUnity.Utilities;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace SanAndreasUnity.Behaviours.Peds
{
public class DeadBody : MonoBehaviour
public class DeadBody : NetworkBehaviour
{
private static List<DeadBody> _deadBodies = new List<DeadBody>();
public static IEnumerable<DeadBody> DeadBodies => _deadBodies;
@ -12,6 +21,18 @@ namespace SanAndreasUnity.Behaviours.Peds
public PushableByDamage PushableByDamage { get; private set; }
private Dictionary<int, Transform> m_framesDict = new Dictionary<int, Transform>();
[SyncVar] private int m_net_modelId;
private class SyncDictionaryIntVector3 : SyncDictionary<int, Vector3>
{
}
private SyncDictionaryIntVector3 m_syncDictionaryBonePositions = new SyncDictionaryIntVector3();
private SyncDictionaryIntVector3 m_syncDictionaryBoneRotations = new SyncDictionaryIntVector3();
private void Awake()
{
@ -29,6 +50,67 @@ namespace SanAndreasUnity.Behaviours.Peds
_deadBodies.Remove(this);
}
public override void OnStartClient()
{
if (NetStatus.IsServer)
return;
F.RunExceptionSafe(this.InitialClientOnlySetup);
}
private void InitialClientOnlySetup()
{
// load ped model
// apply initial bones sync data (because not all bones have rigid bodies)
// apply initial ragdoll (rigid bodies) sync data - this should be done AFTER applying bones sync data
var def = Item.GetDefinition<PedestrianDef>(m_net_modelId);
if (null == def)
{
Debug.LogError($"Failed to initialize dead body: ped definition not found by id {m_net_modelId}");
return;
}
this.gameObject.name = $"dead body {m_net_modelId} {def.ModelName}";
var geoms = Geometry.Load(def.ModelName, def.TextureDictionaryName);
var frames = geoms.AttachFrames(this.transform, MaterialFlags.Default);
m_framesDict = frames.ToDictionary(f => f.BoneId, f => f.transform);
// apply initial transformation data to bones (at the moment when ragdoll was detached) - this is needed because not all bones have rigid bodies
// attached, and so will not be moved/rotated by physics engine
foreach (var pair in m_framesDict)
{
if (m_syncDictionaryBonePositions.TryGetValue(pair.Key, out Vector3 pos))
pair.Value.localPosition = pos;
if (m_syncDictionaryBoneRotations.TryGetValue(pair.Key, out Vector3 rotation))
pair.Value.localRotation = Quaternion.Euler(rotation);
}
// register to dictionary callbacks
RegisterDictionaryCallback(
m_syncDictionaryBonePositions,
(tr, pos) => tr.localPosition = pos);
RegisterDictionaryCallback(
m_syncDictionaryBoneRotations,
(tr, rotation) => tr.localRotation = Quaternion.Euler(rotation));
}
private void RegisterDictionaryCallback<T>(SyncDictionary<int, T> dict, System.Action<Transform, T> action)
{
dict.Callback += (op, key, item) => F.RunExceptionSafe(() =>
{
if (m_framesDict.TryGetValue(key, out Transform tr))
action(tr, item);
});
}
public static DeadBody Create(Transform ragdollTransform, Ped ped)
{
NetStatus.ThrowIfNotOnServer();
@ -42,9 +124,47 @@ namespace SanAndreasUnity.Behaviours.Peds
ragdollTransform.SetParent(ragdollGameObject.transform);
deadBody.m_framesDict = ragdollTransform.GetComponentsInChildren<Frame>()
.ToDictionary(f => f.BoneId, f => f.transform);
deadBody.InitSyncVarsOnServer(ped);
NetManager.Spawn(ragdollGameObject);
return deadBody;
}
private void InitSyncVarsOnServer(Ped ped)
{
m_net_modelId = ped.PedDef.Id;
// assign initial bones transformations
foreach (var pair in m_framesDict)
{
m_syncDictionaryBonePositions.Add(pair.Key, pair.Value.localPosition);
m_syncDictionaryBoneRotations.Add(pair.Key, pair.Value.localRotation.eulerAngles);
}
}
private void Update()
{
if (NetStatus.IsServer)
{
foreach (var pair in m_framesDict)
{
Vector3 pos = pair.Value.localPosition;
Vector3 rotation = pair.Value.localRotation.eulerAngles;
if (m_syncDictionaryBonePositions[pair.Key] != pos)
m_syncDictionaryBonePositions[pair.Key] = pos;
if (m_syncDictionaryBoneRotations[pair.Key] != rotation)
m_syncDictionaryBoneRotations[pair.Key] = rotation;
}
}
else
{
}
}
}
}

View file

@ -383,7 +383,7 @@ namespace SanAndreasUnity.Behaviours
}
public GameObject DetachRagdoll(DamageInfo damageInfo)
public DeadBody DetachRagdoll(DamageInfo damageInfo)
{
if (null == m_ragdollBuilder)
return null;
@ -435,7 +435,7 @@ namespace SanAndreasUnity.Behaviours
// change layer
ragdollTransform.gameObject.SetLayerRecursive(GameManager.DefaultLayerIndex);
return DeadBody.Create(ragdollTransform, m_ped).gameObject;
return DeadBody.Create(ragdollTransform, m_ped);
}
public float GetAmountOfDamageForBone(Transform boneTransform, float baseDamageValue)