267 lines
7.1 KiB
C#
267 lines
7.1 KiB
C#
using System;
|
|
using UdonSharp;
|
|
using UnityEngine;
|
|
using VRC.SDKBase;
|
|
using VRC.Udon;
|
|
using VRRefAssist;
|
|
|
|
[Singleton]
|
|
public class PlayerManager : UdonSharpBehaviour
|
|
{
|
|
[UdonSynced] public int[] playerIds = new int[0];
|
|
[UdonSynced] private int[] playerScores = new int[0];
|
|
[UdonSynced] private string[] playerTeams = new string[0];
|
|
[UdonSynced] public int[] currentPlayerIds = new int[0];
|
|
public ScoreboardManager scoreboardManager;
|
|
|
|
public override void OnPlayerJoined(VRCPlayerApi player)
|
|
{
|
|
if (!Networking.IsOwner(gameObject)) return;
|
|
|
|
int id = player.playerId;
|
|
int index = GetPlayerIndex(id);
|
|
|
|
if (index == -1)
|
|
{
|
|
int[] newIds = new int[playerIds.Length + 1];
|
|
int[] newScores = new int[playerScores.Length + 1];
|
|
string[] newTeams = new string[playerTeams.Length + 1];
|
|
|
|
Array.Copy(playerIds, newIds, playerIds.Length);
|
|
Array.Copy(playerScores, newScores, playerScores.Length);
|
|
Array.Copy(playerTeams, newTeams, playerTeams.Length);
|
|
|
|
newIds[playerIds.Length] = id;
|
|
newScores[playerScores.Length] = 0;
|
|
newTeams[playerTeams.Length] = "unassigned";
|
|
|
|
playerIds = newIds;
|
|
playerScores = newScores;
|
|
playerTeams = newTeams;
|
|
}
|
|
|
|
// Add to current players
|
|
int[] newCurrentIds = new int[currentPlayerIds.Length + 1];
|
|
Array.Copy(currentPlayerIds, newCurrentIds, currentPlayerIds.Length);
|
|
newCurrentIds[currentPlayerIds.Length] = id;
|
|
currentPlayerIds = newCurrentIds;
|
|
|
|
UpdateScoreboards();
|
|
RequestSerialization();
|
|
}
|
|
|
|
public override void OnPlayerLeft(VRCPlayerApi player)
|
|
{
|
|
if (!Networking.IsOwner(gameObject)) return;
|
|
|
|
// Remove from current players
|
|
int[] newCurrentIds = new int[currentPlayerIds.Length - 1];
|
|
int j = 0;
|
|
for (int i = 0; i < currentPlayerIds.Length; i++)
|
|
{
|
|
if (currentPlayerIds[i] != player.playerId)
|
|
{
|
|
newCurrentIds[j] = currentPlayerIds[i];
|
|
j++;
|
|
}
|
|
}
|
|
currentPlayerIds = newCurrentIds;
|
|
|
|
UpdateScoreboards();
|
|
RequestSerialization();
|
|
}
|
|
|
|
public void SetScore(int playerId, int score)
|
|
{
|
|
if (!Networking.IsOwner(gameObject)) return;
|
|
|
|
for (int i = 0; i < playerIds.Length; i++)
|
|
{
|
|
if (playerIds[i] == playerId)
|
|
{
|
|
playerScores[i] = score;
|
|
break;
|
|
}
|
|
}
|
|
UpdateScoreboards();
|
|
RequestSerialization();
|
|
}
|
|
|
|
public int GetScore(int playerId)
|
|
{
|
|
for (int i = 0; i < playerIds.Length; i++)
|
|
{
|
|
if (playerIds[i] == playerId)
|
|
{
|
|
return playerScores[i];
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public void AddScore(int playerId, int increment)
|
|
{
|
|
if (!Networking.IsOwner(gameObject)) return;
|
|
|
|
for (int i = 0; i < playerIds.Length; i++)
|
|
{
|
|
if (playerIds[i] == playerId)
|
|
{
|
|
playerScores[i] += increment;
|
|
break;
|
|
}
|
|
}
|
|
UpdateScoreboards();
|
|
RequestSerialization();
|
|
}
|
|
|
|
public VRCPlayerApi[] GetCurrentPlayers()
|
|
{
|
|
VRCPlayerApi[] players = new VRCPlayerApi[currentPlayerIds.Length];
|
|
for (int i = 0; i < currentPlayerIds.Length; i++)
|
|
{
|
|
players[i] = VRCPlayerApi.GetPlayerById(currentPlayerIds[i]);
|
|
}
|
|
return players;
|
|
}
|
|
|
|
// Team Management Methods
|
|
public void SetTeam(int playerId, string team)
|
|
{
|
|
if (!Networking.IsOwner(gameObject)) return;
|
|
|
|
if (team != "red" && team != "blue" && team != "unassigned") return;
|
|
|
|
int index = GetPlayerIndex(playerId);
|
|
if (index >= 0)
|
|
{
|
|
playerTeams[index] = team;
|
|
UpdateScoreboards();
|
|
RequestSerialization();
|
|
}
|
|
}
|
|
|
|
public string GetRandomViableTeam()
|
|
{
|
|
int redCount = 0;
|
|
int blueCount = 0;
|
|
|
|
for (int i = 0; i < currentPlayerIds.Length; i++)
|
|
{
|
|
string team = GetTeam(currentPlayerIds[i]);
|
|
if (team == "red") redCount++;
|
|
else if (team == "blue") blueCount++;
|
|
}
|
|
|
|
float half = currentPlayerIds.Length / 2f;
|
|
bool canJoinRed = redCount < half;
|
|
bool canJoinBlue = blueCount < half;
|
|
|
|
if (canJoinRed && canJoinBlue)
|
|
{
|
|
return UnityEngine.Random.Range(0, 2) == 0 ? "red" : "blue";
|
|
}
|
|
else if (canJoinRed)
|
|
{
|
|
return "red";
|
|
}
|
|
else if (canJoinBlue)
|
|
{
|
|
return "blue";
|
|
}
|
|
|
|
return "unassigned";
|
|
}
|
|
|
|
public void RandomizeAllPlayerTeams()
|
|
{
|
|
if (!Networking.IsOwner(gameObject)) return;
|
|
|
|
float half = currentPlayerIds.Length / 2f;
|
|
int redSlots = (int)half;
|
|
int blueSlots = currentPlayerIds.Length - redSlots;
|
|
int redAssigned = 0;
|
|
int blueAssigned = 0;
|
|
|
|
// Shuffle player IDs
|
|
int[] shuffledIds = new int[currentPlayerIds.Length];
|
|
System.Array.Copy(currentPlayerIds, shuffledIds, currentPlayerIds.Length);
|
|
ShuffleArray(shuffledIds);
|
|
|
|
// Assign teams based on shuffled order
|
|
for (int i = 0; i < shuffledIds.Length; i++)
|
|
{
|
|
string team = "unassigned";
|
|
if (redAssigned < redSlots)
|
|
{
|
|
team = "red";
|
|
redAssigned++;
|
|
}
|
|
else if (blueAssigned < blueSlots)
|
|
{
|
|
team = "blue";
|
|
blueAssigned++;
|
|
}
|
|
SetTeam(shuffledIds[i], team);
|
|
}
|
|
}
|
|
|
|
private void ShuffleArray(int[] array)
|
|
{
|
|
for (int i = array.Length - 1; i > 0; i--)
|
|
{
|
|
int randomIndex = UnityEngine.Random.Range(0, i + 1);
|
|
int temp = array[i];
|
|
array[i] = array[randomIndex];
|
|
array[randomIndex] = temp;
|
|
}
|
|
}
|
|
|
|
public string GetTeam(int playerId)
|
|
{
|
|
int index = GetPlayerIndex(playerId);
|
|
return index >= 0 ? playerTeams[index] : "unassigned";
|
|
}
|
|
|
|
public int[] GetTeamMembers(string team)
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < playerTeams.Length; i++)
|
|
{
|
|
if (playerTeams[i] == team) count++;
|
|
}
|
|
|
|
int[] members = new int[count];
|
|
int j = 0;
|
|
for (int i = 0; i < playerTeams.Length; i++)
|
|
{
|
|
if (playerTeams[i] == team)
|
|
{
|
|
members[j++] = playerIds[i];
|
|
}
|
|
}
|
|
return members;
|
|
}
|
|
|
|
private int GetPlayerIndex(int playerId)
|
|
{
|
|
for (int i = 0; i < playerIds.Length; i++)
|
|
{
|
|
if (playerIds[i] == playerId) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public override void OnDeserialization()
|
|
{
|
|
UpdateScoreboards();
|
|
}
|
|
|
|
private void UpdateScoreboards()
|
|
{
|
|
if (scoreboardManager != null)
|
|
{
|
|
scoreboardManager.UpdateAllScoreboards();
|
|
}
|
|
}
|
|
} |