554 lines
17 KiB
C#
554 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using VRC.SDKBase;
|
|
|
|
namespace VRCPrefabs.CyanEmu
|
|
{
|
|
public class CyanEmuPlayerManager
|
|
{
|
|
// Player Manager system
|
|
private static int masterID = -1;
|
|
private static int localPlayerID = -1;
|
|
private static int nextPlayerID = 1;
|
|
private static readonly Dictionary<VRCPlayerApi, int> playerIDs = new Dictionary<VRCPlayerApi, int>();
|
|
private static readonly Dictionary<int, VRCPlayerApi> players = new Dictionary<int, VRCPlayerApi>();
|
|
|
|
private static readonly List<VRCPlayerApi> waitingPlayers = new List<VRCPlayerApi>();
|
|
private static bool networkReady = false;
|
|
|
|
public static void InitializePlayer(VRCPlayerApi player)
|
|
{
|
|
int id = nextPlayerID;
|
|
player.Log("Assigning player id " + id);
|
|
++nextPlayerID;
|
|
|
|
playerIDs[player] = id;
|
|
players[id] = player;
|
|
player.AddToList();
|
|
|
|
if (masterID == -1)
|
|
{
|
|
player.Log("Player is now master");
|
|
masterID = id;
|
|
Debug.Assert(player.isMaster, "CyanEmuPlayerManager:InitializePlayer Player should be considered master!");
|
|
}
|
|
else
|
|
{
|
|
Debug.Assert(!player.isMaster, "CyanEmuPlayerManager:InitializePlayer Player should not be considered master!");
|
|
}
|
|
|
|
Debug.Assert(player.playerId == id, "CyanEmuPlayerManager:InitializePlayer Player's id does not match assigned id!");
|
|
|
|
if (networkReady)
|
|
{
|
|
CyanEmuMain.PlayerJoined(player);
|
|
}
|
|
else
|
|
{
|
|
waitingPlayers.Add(player);
|
|
}
|
|
}
|
|
|
|
public static void OnNetworkReady()
|
|
{
|
|
networkReady = true;
|
|
foreach (var player in waitingPlayers)
|
|
{
|
|
CyanEmuMain.PlayerJoined(player);
|
|
}
|
|
|
|
waitingPlayers.Clear();
|
|
}
|
|
|
|
public static VRCPlayerApi CreateNewPlayer(bool local, GameObject playerObj, string name = null)
|
|
{
|
|
VRCPlayerApi player = new VRCPlayerApi();
|
|
player.gameObject = playerObj;
|
|
|
|
player.displayName = (string.IsNullOrEmpty(name) ? (local ? "Local" : "Remote") +" Player " + nextPlayerID : name);
|
|
player.isLocal = local;
|
|
InitializePlayer(player);
|
|
|
|
if (local)
|
|
{
|
|
localPlayerID = player.playerId;
|
|
}
|
|
Debug.Assert(player.isLocal == local, "CyanEmuPlayerManager:CreateNewPlayer New player does not match local settings!");
|
|
|
|
return player;
|
|
}
|
|
|
|
public static void RemovePlayer(VRCPlayerApi player)
|
|
{
|
|
if (masterID == player.playerId)
|
|
{
|
|
masterID = -1;
|
|
if (VRCPlayerApi.AllPlayers.Count != 0)
|
|
{
|
|
masterID = VRCPlayerApi.AllPlayers[0].playerId;
|
|
}
|
|
}
|
|
|
|
CyanEmuMain.PlayerLeft(player);
|
|
|
|
playerIDs.Remove(player);
|
|
players.Remove(player.playerId);
|
|
player.RemoveFromList();
|
|
}
|
|
|
|
public static int GetMasterID()
|
|
{
|
|
return masterID;
|
|
}
|
|
|
|
public static VRCPlayerApi LocalPlayer()
|
|
{
|
|
return GetPlayerByID(localPlayerID);
|
|
}
|
|
|
|
public static VRCPlayerApi GetPlayerByID(int playerID)
|
|
{
|
|
players.TryGetValue(playerID, out VRCPlayerApi player);
|
|
return player;
|
|
}
|
|
|
|
public static int GetPlayerID(VRCPlayerApi player)
|
|
{
|
|
if (player == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
playerIDs.TryGetValue(player, out int playerId);
|
|
return playerId;
|
|
}
|
|
|
|
public static bool IsMaster(VRCPlayerApi player)
|
|
{
|
|
return GetPlayerID(player) == masterID;
|
|
}
|
|
|
|
public static bool IsInstanceOwner(VRCPlayerApi player)
|
|
{
|
|
return CyanEmuSettings.Instance.isInstanceOwner;
|
|
}
|
|
|
|
public static bool IsInstanceOwner()
|
|
{
|
|
return CyanEmuSettings.Instance.isInstanceOwner;
|
|
}
|
|
|
|
public static bool IsLocalPlayerMaster()
|
|
{
|
|
return localPlayerID == masterID;
|
|
}
|
|
|
|
public static void EnablePickups(VRCPlayerApi player, bool enabled)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
player.LogWarning("[VRCPlayerAPI.EnablePickups] EnablePickups for remote players will do nothing.");
|
|
return;
|
|
}
|
|
|
|
// TODO
|
|
}
|
|
|
|
public static void Immobilize(VRCPlayerApi player, bool immobilized)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.Immobilize] You cannot set remote players Immobilized");
|
|
}
|
|
|
|
player.GetPlayerController().Immobilize(immobilized);
|
|
}
|
|
|
|
public static void TeleportToOrientationLerp(VRCPlayerApi player, Vector3 position, Quaternion rotation, VRC_SceneDescriptor.SpawnOrientation orientation, bool lerp)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
player.LogWarning("[VRCPlayerAPI.TeleportTo] Teleporting remote players will do nothing.");
|
|
return;
|
|
}
|
|
|
|
// Ignore lerp since there is no networking here
|
|
player.GetPlayerController().Teleport(position, rotation, orientation == VRC_SceneDescriptor.SpawnOrientation.AlignRoomWithSpawnPoint);
|
|
}
|
|
|
|
public static void TeleportToOrientation(VRCPlayerApi player, Vector3 position, Quaternion rotation, VRC_SceneDescriptor.SpawnOrientation orientation)
|
|
{
|
|
TeleportToOrientationLerp(player, position, rotation, VRC_SceneDescriptor.SpawnOrientation.Default, false);
|
|
}
|
|
|
|
public static void TeleportTo(VRCPlayerApi player, Vector3 position, Quaternion rotation)
|
|
{
|
|
TeleportToOrientationLerp(player, position, rotation, VRC_SceneDescriptor.SpawnOrientation.Default, false);
|
|
}
|
|
|
|
public static void PlayHapticEventInHand(VRCPlayerApi player, VRC_Pickup.PickupHand hand, float f1, float f2, float f3)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
player.LogWarning("[VRCPlayerAPI.PlayHapticEventInHand] PlayHapticEventInHand for remote players will do nothing.");
|
|
return;
|
|
}
|
|
|
|
// TODO
|
|
}
|
|
|
|
public static void ClaimNetworkControl(VRCPlayerApi player, VRC_ObjectApi obj)
|
|
{
|
|
// TODO Is this necessary?
|
|
}
|
|
|
|
public static VRCPlayerApi GetPlayerByGameObject(GameObject obj)
|
|
{
|
|
CyanEmuPlayer player = obj.GetComponentInParent<CyanEmuPlayer>();
|
|
if (player != null)
|
|
{
|
|
return player.player;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static VRC_Pickup GetPickupInHand(VRCPlayerApi player, VRC_Pickup.PickupHand hand)
|
|
{
|
|
return player.GetPlayerController().GetHeldPickup(hand);
|
|
}
|
|
|
|
public static VRCPlayerApi.TrackingData GetTrackingData(VRCPlayerApi player, VRCPlayerApi.TrackingDataType trackingDataType)
|
|
{
|
|
return player.GetPlayerController().GetTrackingData(trackingDataType);
|
|
}
|
|
|
|
public static void TakeOwnership(VRCPlayerApi player, GameObject obj)
|
|
{
|
|
obj.SetOwner(player);
|
|
}
|
|
|
|
public static VRCPlayerApi GetOwner(GameObject obj)
|
|
{
|
|
ICyanEmuSyncable sync = obj.GetComponent<ICyanEmuSyncable>();
|
|
|
|
int playerID = sync != null ? sync.GetOwner() : masterID;
|
|
|
|
if (!players.TryGetValue(playerID, out VRCPlayerApi player))
|
|
{
|
|
return null;
|
|
}
|
|
return player;
|
|
}
|
|
|
|
public static bool IsOwner(VRCPlayerApi player, GameObject obj)
|
|
{
|
|
ICyanEmuSyncable sync = obj.GetComponent<ICyanEmuSyncable>();
|
|
int owner = sync == null ? masterID : sync.GetOwner();
|
|
return owner == player.playerId;
|
|
}
|
|
|
|
public static float GetRunSpeed(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.GetRunSpeed] You cannot get run speed for remote clients!");
|
|
}
|
|
return player.GetPlayerController().GetRunSpeed();
|
|
}
|
|
|
|
public static void SetRunSpeed(VRCPlayerApi player, float speed)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.SetRunSpeed] You cannot set run speed for remote clients!");
|
|
}
|
|
player.GetPlayerController().SetRunSpeed(speed);
|
|
}
|
|
|
|
public static float GetStrafeSpeed(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.GetStrafeSpeed] You cannot get strafe speed for remote clients!");
|
|
}
|
|
return player.GetPlayerController().GetStrafeSpeed();
|
|
}
|
|
|
|
public static void SetStrafeSpeed(VRCPlayerApi player, float speed)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.SetStrafeSpeed] You cannot set strafe speed for remote clients!");
|
|
}
|
|
player.GetPlayerController().SetStrafeSpeed(speed);
|
|
}
|
|
|
|
public static float GetWalkSpeed(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.GetWalkSpeed] You cannot get walk speed for remote clients!");
|
|
}
|
|
return player.GetPlayerController().GetWalkSpeed();
|
|
}
|
|
|
|
public static void SetWalkSpeed(VRCPlayerApi player, float speed)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.SetWalkSpeed] You cannot set walk speed for remote clients!");
|
|
}
|
|
player.GetPlayerController().SetWalkSpeed(speed);
|
|
}
|
|
|
|
public static float GetJumpImpulse(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.GetJumpImpulse] You cannot get jump impulse for remote clients!");
|
|
}
|
|
return player.GetPlayerController().GetJump();
|
|
}
|
|
|
|
public static void SetJumpImpulse(VRCPlayerApi player, float jump)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.SetJumpImpulse] You cannot set jump impulse for remote clients!");
|
|
}
|
|
player.GetPlayerController().SetJump(jump);
|
|
}
|
|
|
|
public static float GetGravityStrength(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.GetGravityStrength] You cannot get gravity strength for remote clients!");
|
|
}
|
|
return player.GetPlayerController().GetGravityStrength();
|
|
}
|
|
|
|
public static void SetGravityStrength(VRCPlayerApi player, float gravity)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
throw new Exception("[VRCPlayerAPI.SetGravityStrength] You cannot set gravity strength for remote clients!");
|
|
}
|
|
player.GetPlayerController().SetGravityStrength(gravity);
|
|
}
|
|
|
|
public static Vector3 GetVelocity(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
return Vector3.zero;
|
|
}
|
|
return player.GetPlayerController().GetVelocity();
|
|
}
|
|
|
|
public static void SetVelocity(VRCPlayerApi player, Vector3 velocity)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
return;
|
|
}
|
|
player.GetPlayerController().SetVelocity(velocity);
|
|
}
|
|
|
|
public static Vector3 GetPosition(VRCPlayerApi player)
|
|
{
|
|
return player.gameObject.transform.position;
|
|
}
|
|
|
|
public static Quaternion GetRotation(VRCPlayerApi player)
|
|
{
|
|
return player.gameObject.transform.rotation;
|
|
}
|
|
|
|
public static bool IsGrounded(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
// TODO verify remote player values when not grounded.
|
|
return true;
|
|
}
|
|
return player.GetPlayerController().IsGrounded();
|
|
}
|
|
|
|
public static void UseAttachedStation(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GameObject obj = null;
|
|
#if UDON
|
|
// This is dumb
|
|
obj = VRC.Udon.UdonManager.Instance.currentlyExecuting.gameObject;
|
|
#endif
|
|
obj?.GetComponent<CyanEmuStationHelper>()?.UseStation();
|
|
}
|
|
|
|
public static void UseLegacyLocomotion(VRCPlayerApi player)
|
|
{
|
|
if (!player.isLocal)
|
|
{
|
|
return;
|
|
}
|
|
player.GetPlayerController().UseLegacyLocomotion();
|
|
}
|
|
|
|
|
|
public static Quaternion GetBoneRotation(VRCPlayerApi player, HumanBodyBones bone)
|
|
{
|
|
return Quaternion.identity;
|
|
}
|
|
|
|
public static Vector3 GetBonePosition(VRCPlayerApi player, HumanBodyBones bone)
|
|
{
|
|
return Vector3.zero;
|
|
}
|
|
|
|
public static Transform GetBoneTransform(VRCPlayerApi player, HumanBodyBones bone)
|
|
{
|
|
// TODO
|
|
return null;
|
|
}
|
|
|
|
#region Player Tags
|
|
|
|
public static List<int> GetPlayersWithTag(string tagName, string tagValue)
|
|
{
|
|
List<int> players = new List<int>();
|
|
foreach (var player in VRCPlayerApi.AllPlayers)
|
|
{
|
|
if (player.GetCyanEmuPlayer().HasTag(tagName, tagValue))
|
|
{
|
|
players.Add(player.playerId);
|
|
}
|
|
}
|
|
return players;
|
|
}
|
|
|
|
public static void ClearPlayerTag(VRCPlayerApi player)
|
|
{
|
|
player.LogError("Clearing all player tags. VRCPlayerApi.ClearPlayerTags is a dangerous call, as it will clear all the tags and this might break prefabs that rely on them.");
|
|
player.GetCyanEmuPlayer().ClearTags();
|
|
}
|
|
|
|
public static void SetPlayerTag(VRCPlayerApi player, string tagName, string tagValue)
|
|
{
|
|
player.GetCyanEmuPlayer().SetTag(tagName, tagValue);
|
|
}
|
|
|
|
public static string GetPlayerTag(VRCPlayerApi player, string tagName)
|
|
{
|
|
return player.GetCyanEmuPlayer().GetTag(tagName);
|
|
}
|
|
|
|
|
|
public static void ClearSilence(VRCPlayerApi player)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetSilencedToUntagged(VRCPlayerApi player, int number, string tagName, string tagValue)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetSilencedToTagged(VRCPlayerApi player, int number, string tagName, string tagValue)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
|
|
public static void ClearInvisible(VRCPlayerApi player)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetInvisibleToUntagged(VRCPlayerApi player, bool invisible, string tagName, string tagValue)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetInvisibleToTagged(VRCPlayerApi player, bool invisible, string tagName, string tagValue)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Player Audio
|
|
|
|
public static void SetAvatarAudioVolumetricRadius(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetAvatarAudioNearRadius(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetAvatarAudioFarRadius(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetAvatarAudioGain(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetVoiceLowpass(VRCPlayerApi player, bool value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetVoiceVolumetricRadius(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetVoiceDistanceFar(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetVoiceDistanceNear(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
public static void SetVoiceGain(VRCPlayerApi player, float value)
|
|
{
|
|
// TODO?
|
|
}
|
|
|
|
#endregion
|
|
|
|
/*
|
|
TODO all the interfaces:
|
|
|
|
public static ClaimNetworkControlDelegate ClaimNetworkControl;
|
|
public static GetLookRayDelegate GetLookRay;
|
|
|
|
public static Action<VRCPlayerApi, RuntimeAnimatorController> _PushAnimations;
|
|
public static Action<VRCPlayerApi> _PopAnimations;
|
|
public static SetAnimatorBoolDelegate SetAnimatorBool;
|
|
|
|
public static Func<VRCPlayerApi, bool> _isModeratorDelegate;
|
|
public static Func<VRCPlayerApi, bool> _isSuperDelegate;
|
|
|
|
public static Action<VRCPlayerApi, Color> _SetNamePlateColor;
|
|
public static Action<VRCPlayerApi> _RestoreNamePlateColor;
|
|
public static Action<VRCPlayerApi, bool> _SetNamePlateVisibility;
|
|
public static Action<VRCPlayerApi> _RestoreNamePlateVisibility;
|
|
*/
|
|
}
|
|
}
|
|
|