Player Sync stuff
This commit is contained in:
@@ -11,39 +11,269 @@ using StressLevelZero.Player;
|
||||
using StressLevelZero.VRMK;
|
||||
using BoneSync.Networking;
|
||||
using BoneSync.Networking.Messages;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BoneSync.Data;
|
||||
using StressLevelZero.Interaction;
|
||||
using UnhollowerBaseLib;
|
||||
|
||||
|
||||
namespace BoneSync.Player
|
||||
{
|
||||
public static class EmebeddedAssetBundle
|
||||
{
|
||||
// Credit to the "Entanglement" mod. The playerrep asset bundle is also by them.
|
||||
public static AssetBundle LoadFromAssembly(string name)
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
string[] manifestResources = assembly.GetManifestResourceNames();
|
||||
|
||||
if (manifestResources.Contains(name))
|
||||
{
|
||||
MelonLogger.Msg($"Loading embedded bundle data {name}...");
|
||||
|
||||
byte[] bytes;
|
||||
using (Stream str = assembly.GetManifestResourceStream(name))
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
str.CopyTo(memoryStream);
|
||||
bytes = memoryStream.ToArray();
|
||||
}
|
||||
|
||||
MelonLogger.Msg($"Loading bundle from data {name}, please be patient...");
|
||||
AssetBundle temp = AssetBundle.LoadFromMemory(bytes);
|
||||
MelonLogger.Msg($"Done!");
|
||||
return temp;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal class PlayerRig
|
||||
{
|
||||
//public const string RIGMANAGER_SCENE_NAME = "[RigManager (Default Brett)]";
|
||||
private const float RIG_SYNC_FPS = 30;
|
||||
|
||||
private static List<PlayerRig> _playerRigs = new List<PlayerRig>();
|
||||
public static AssetBundle rigBundle;
|
||||
private static float _lastLocalSyncTime = 0;
|
||||
private static Dictionary<ulong, PlayerRig> _playerRigs = new Dictionary<ulong, PlayerRig>();
|
||||
|
||||
private ulong _ownerId;
|
||||
|
||||
private GameObject playerRig;
|
||||
private RigManager rigManager;
|
||||
private SLZ_Body body;
|
||||
private CharacterAnimationManager characterAnimationManager;
|
||||
private Animator repAnimator;
|
||||
private Animator animator;
|
||||
|
||||
private Transform headTransform;
|
||||
private Transform leftHandTransform;
|
||||
private Transform rightHandTransform;
|
||||
|
||||
public static void LoadBundle()
|
||||
{
|
||||
rigBundle = EmebeddedAssetBundle.LoadFromAssembly("BoneSync.playerrep.eres");
|
||||
|
||||
if (rigBundle == null)
|
||||
throw new NullReferenceException("playerRepBundle is null! Did you forget to compile the player bundle into the dll?");
|
||||
|
||||
|
||||
MelonLogger.Msg("Loaded playerRepBundle success");
|
||||
}
|
||||
|
||||
public static void Tick()
|
||||
{
|
||||
foreach (PlayerRig playerRig in _playerRigs.Values)
|
||||
{
|
||||
playerRig.UpdateIK();
|
||||
}
|
||||
|
||||
if (Time.time - _lastLocalSyncTime > 1 / RIG_SYNC_FPS)
|
||||
{
|
||||
SendLocalPlayerSync();
|
||||
_lastLocalSyncTime = Time.time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetFingerCurl(Handedness handedness, SimpleFingerCurl fingerCurl)
|
||||
{
|
||||
characterAnimationManager.ApplyFingerCurl(handedness, 1f - fingerCurl.thumb, 1f - fingerCurl.index, 1f - fingerCurl.middle, 1f - fingerCurl.ring, 1f - fingerCurl.pinky);
|
||||
}
|
||||
|
||||
public void UpdatePlayerSync(PlayerSyncInfo playerSyncInfo)
|
||||
{
|
||||
//playerRig.transform.ApplySimpleTransform(playerSyncInfo.headPos);
|
||||
playerRig.transform.position = playerSyncInfo.rootPos;
|
||||
|
||||
headTransform.ApplySimpleTransform(playerSyncInfo.headPos);
|
||||
leftHandTransform.ApplySimpleTransform(playerSyncInfo.leftHandPos);
|
||||
rightHandTransform.ApplySimpleTransform(playerSyncInfo.rightHandPos);
|
||||
|
||||
SetFingerCurl(Handedness.LEFT, playerSyncInfo.leftHandFingerCurl);
|
||||
SetFingerCurl(Handedness.RIGHT, playerSyncInfo.rightHandFingerCurl);
|
||||
}
|
||||
|
||||
public PlayerRig()
|
||||
public static PlayerSyncInfo? GetLocalSyncInfo()
|
||||
{
|
||||
GameObject localPlayerRig = GameObject.Find("[RigManager (Default Brett)]/[SkeletonRig (GameWorld Brett)]");
|
||||
if (localPlayerRig == null)
|
||||
{
|
||||
MelonLogger.Msg("Local player rig not found");
|
||||
return null;
|
||||
}
|
||||
Transform root = localPlayerRig.transform;
|
||||
|
||||
_playerRigs.Add(this);
|
||||
Transform localHeadTransform = root.Find("Head");
|
||||
Transform localLeftHandTransform = root.Find("Hand (left)");
|
||||
Transform localRightHandTransform = root.Find("Hand (right)");
|
||||
|
||||
if (localHeadTransform == null || localLeftHandTransform == null || localRightHandTransform == null)
|
||||
{
|
||||
MelonLogger.Msg("Local player rig components not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
PlayerSyncInfo playerSyncInfo = new PlayerSyncInfo()
|
||||
{
|
||||
rootPos = root.position,
|
||||
headPos = new SimpleSyncTransform(localHeadTransform),
|
||||
leftHandPos = new SimpleSyncTransform(localLeftHandTransform),
|
||||
rightHandPos = new SimpleSyncTransform(localRightHandTransform),
|
||||
//leftHandFingerCurl = new SimpleFingerCurl(PlayerScripts.playerLeftHand.fingerCurl),
|
||||
//rightHandFingerCurl = new SimpleFingerCurl(PlayerScripts.playerRightHand.fingerCurl)
|
||||
|
||||
};
|
||||
|
||||
return playerSyncInfo;
|
||||
}
|
||||
|
||||
private static void SendLocalPlayerSync()
|
||||
{
|
||||
if (!BoneSync.lobby.IsConnected()) return;
|
||||
PlayerSyncInfo? playerSyncInfo = GetLocalSyncInfo();
|
||||
if (!playerSyncInfo.HasValue) return;
|
||||
PlayerSyncMessage playerSyncMessage = new PlayerSyncMessage(playerSyncInfo.Value);
|
||||
playerSyncMessage.Broadcast();
|
||||
}
|
||||
|
||||
public static PlayerRig GetPlayerRig(ulong ownerId)
|
||||
{
|
||||
if (_playerRigs.ContainsKey(ownerId))
|
||||
{
|
||||
MelonLogger.Msg("PlayerRig already exists for " + ownerId);
|
||||
return _playerRigs[ownerId];
|
||||
}
|
||||
|
||||
if (rigBundle == null)
|
||||
{
|
||||
MelonLogger.Msg("playerRepBundle is null! Did you forget to load the bundle?");
|
||||
return null;
|
||||
}
|
||||
PlayerRig rig = new PlayerRig(ownerId);
|
||||
rig.EnsurePlayerRig();
|
||||
return rig;
|
||||
}
|
||||
|
||||
public static void DestroyRig(ulong ownerId)
|
||||
{
|
||||
if (_playerRigs.ContainsKey(ownerId))
|
||||
{
|
||||
_playerRigs[ownerId].Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsurePlayerRig() {
|
||||
if (playerRig != null) return;
|
||||
|
||||
playerRig = GameObject.Instantiate(rigBundle.LoadAsset<GameObject>("PlayerRep"));
|
||||
playerRig.name = "PlayerRep";
|
||||
|
||||
body = playerRig.GetComponentInChildren<SLZ_Body>();
|
||||
characterAnimationManager = playerRig.GetComponentInChildren<CharacterAnimationManager>();
|
||||
animator = playerRig.GetComponentInChildren<Animator>();
|
||||
|
||||
headTransform = playerRig.transform.Find("Head");
|
||||
leftHandTransform = playerRig.transform.Find("Hand (left)");
|
||||
rightHandTransform = playerRig.transform.Find("Hand (right)");
|
||||
|
||||
body.OnStart();
|
||||
|
||||
}
|
||||
|
||||
public void UpdateIK()
|
||||
{
|
||||
// Catch errors so other players arent broken
|
||||
try
|
||||
{
|
||||
EnsurePlayerRig();
|
||||
//Re-Apply playermodel if unloaded
|
||||
//if ((!currentSkinBundle || !currentSkinObject) && isCustomSkinned)
|
||||
// PlayerSkinLoader.ApplyPlayermodel(this, currentSkinPath);
|
||||
// Prevent exceptions if we are in the middle of deleting a playermodel
|
||||
if (!animator)
|
||||
return;
|
||||
|
||||
animator.Update(Time.fixedDeltaTime);
|
||||
characterAnimationManager.OnLateUpdate();
|
||||
Vector3 repInputVel = Vector3.zero;
|
||||
|
||||
body.FullBodyUpdate(repInputVel, Vector3.zero);
|
||||
body.ArtToBlender.UpdateBlender();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
|
||||
private PlayerRig(ulong id)
|
||||
{
|
||||
_playerRigs.Add(id, this);
|
||||
_ownerId = id;
|
||||
}
|
||||
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
_playerRigs.Remove(this);
|
||||
_playerRigs.Remove(_ownerId);
|
||||
GameObject.Destroy(playerRig);
|
||||
}
|
||||
}
|
||||
|
||||
// copied from Entanglement mod
|
||||
public static class PlayerScripts
|
||||
{
|
||||
public static RigManager playerRig;
|
||||
public static PhysBody playerPhysBody;
|
||||
public static Player_Health playerHealth;
|
||||
public static PhysGrounder playerGrounder;
|
||||
public static Hand playerLeftHand;
|
||||
public static Hand playerRightHand;
|
||||
public static bool reloadLevelOnDeath;
|
||||
public static RuntimeAnimatorController playerAnimatorController;
|
||||
public static Il2CppStringArray playerHandPoses = null;
|
||||
|
||||
public static void GetPlayerScripts()
|
||||
{
|
||||
GameObject localPlayerRig = GameObject.Find("[RigManager (Default Brett)]/[SkeletonRig (GameWorld Brett)]");
|
||||
playerRig = localPlayerRig.GetComponentInChildren<RigManager>();
|
||||
playerHealth = playerRig.playerHealth;
|
||||
|
||||
reloadLevelOnDeath = playerHealth.reloadLevelOnDeath;
|
||||
|
||||
playerHealth.reloadLevelOnDeath = !BoneSync.lobby.IsConnected();
|
||||
|
||||
PhysicsRig physicsRig = playerRig.physicsRig;
|
||||
playerPhysBody = physicsRig.physBody;
|
||||
playerGrounder = playerPhysBody.physG;
|
||||
playerLeftHand = physicsRig.leftHand;
|
||||
playerRightHand = physicsRig.rightHand;
|
||||
playerAnimatorController = playerRig.gameWorldSkeletonRig.characterAnimationManager.animator.runtimeAnimatorController;
|
||||
GetHandPoses();
|
||||
}
|
||||
|
||||
public static void GetHandPoses()
|
||||
{
|
||||
// Checks if we already got the hand poses to prevent crashes
|
||||
if (playerHandPoses == null)
|
||||
CharacterAnimationManager.FetchHandPoseList(out playerHandPoses); // Lets hope this is constant!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user