RustDedicated/Assembly-CSharp/ComputerStation.cs
2025-11-07 15:19:56 +10:30

703 lines
17 KiB
C#

#define UNITY_ASSERTIONS
using System;
using System.Collections.Generic;
using ConVar;
using Facepunch;
using Network;
using ProtoBuf;
using Rust;
using UnityEngine;
using UnityEngine.Assertions;
public class ComputerStation : BaseMountable
{
public const Flags Flag_HasFullControl = Flags.Reserved2;
[Header("Computer")]
public GameObjectRef menuPrefab;
public ComputerMenu computerMenu;
public EntityRef currentlyControllingEnt;
public List<string> controlBookmarks = new List<string>();
public Transform leftHandIKPosition;
public Transform rightHandIKPosition;
public SoundDefinition turnOnSoundDef;
public SoundDefinition turnOffSoundDef;
public SoundDefinition onLoopSoundDef;
public bool isStatic;
public float autoGatherRadius;
private ulong currentPlayerID;
private float nextAddTime;
private static readonly char[] BookmarkSplit = new char[1] { ';' };
public override bool OnRpcMessage(BasePlayer player, uint rpc, Message msg)
{
using (TimeWarning.New("ComputerStation.OnRpcMessage"))
{
if (rpc == 481778085 && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - AddBookmark ");
}
using (TimeWarning.New("AddBookmark"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg2 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
AddBookmark(msg2);
}
}
catch (Exception exception)
{
Debug.LogException(exception);
player.Kick("RPC Error in AddBookmark");
}
}
return true;
}
if (rpc == 3509814913u && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - AdminForceAddBookmark ");
}
using (TimeWarning.New("AdminForceAddBookmark"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg3 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
AdminForceAddBookmark(msg3);
}
}
catch (Exception exception2)
{
Debug.LogException(exception2);
player.Kick("RPC Error in AdminForceAddBookmark");
}
}
return true;
}
if (rpc == 3237405565u && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - AdminForceClearBookmarks ");
}
using (TimeWarning.New("AdminForceClearBookmarks"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg4 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
AdminForceClearBookmarks(msg4);
}
}
catch (Exception exception3)
{
Debug.LogException(exception3);
player.Kick("RPC Error in AdminForceClearBookmarks");
}
}
return true;
}
if (rpc == 4037724546u && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - AdminForceDeleteBookmark ");
}
using (TimeWarning.New("AdminForceDeleteBookmark"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg5 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
AdminForceDeleteBookmark(msg5);
}
}
catch (Exception exception4)
{
Debug.LogException(exception4);
player.Kick("RPC Error in AdminForceDeleteBookmark");
}
}
return true;
}
if (rpc == 552248427 && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - BeginControllingBookmark ");
}
using (TimeWarning.New("BeginControllingBookmark"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg6 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
BeginControllingBookmark(msg6);
}
}
catch (Exception exception5)
{
Debug.LogException(exception5);
player.Kick("RPC Error in BeginControllingBookmark");
}
}
return true;
}
if (rpc == 2498687923u && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - DeleteBookmark ");
}
using (TimeWarning.New("DeleteBookmark"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg7 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
DeleteBookmark(msg7);
}
}
catch (Exception exception6)
{
Debug.LogException(exception6);
player.Kick("RPC Error in DeleteBookmark");
}
}
return true;
}
if (rpc == 2139261430 && player != null)
{
Assert.IsTrue(player.isServer, "SV_RPC Message is using a clientside player!");
if (ConVar.Global.developer > 2)
{
Debug.Log("SV_RPCMessage: " + player?.ToString() + " - Server_DisconnectControl ");
}
using (TimeWarning.New("Server_DisconnectControl"))
{
try
{
using (TimeWarning.New("Call"))
{
RPCMessage msg8 = new RPCMessage
{
connection = msg.connection,
player = player,
read = msg.read
};
Server_DisconnectControl(msg8);
}
}
catch (Exception exception7)
{
Debug.LogException(exception7);
player.Kick("RPC Error in Server_DisconnectControl");
}
}
return true;
}
}
return base.OnRpcMessage(player, rpc, msg);
}
public bool AllowPings()
{
BaseEntity baseEntity = currentlyControllingEnt.Get(base.isServer);
if (baseEntity != null && baseEntity is IRemoteControllable { CanPing: not false })
{
return true;
}
return false;
}
public static bool IsValidIdentifier(string str)
{
if (string.IsNullOrEmpty(str))
{
return false;
}
if (str.Length > 32)
{
return false;
}
return str.IsAlphaNumeric();
}
public override void DestroyShared()
{
if (base.isServer && (bool)GetMounted())
{
StopControl(GetMounted());
}
base.DestroyShared();
}
public override void ServerInit()
{
base.ServerInit();
Invoke(GatherStaticCameras, 5f);
}
public void GatherStaticCameras()
{
if (Rust.Application.isLoadingSave)
{
Invoke(GatherStaticCameras, 1f);
}
else
{
if (!isStatic || !(autoGatherRadius > 0f))
{
return;
}
List<BaseEntity> obj = Facepunch.Pool.Get<List<BaseEntity>>();
Vis.Entities(base.transform.position, autoGatherRadius, obj, 256, QueryTriggerInteraction.Ignore);
foreach (BaseEntity item in obj)
{
IRemoteControllable component = item.GetComponent<IRemoteControllable>();
if (component != null)
{
CCTV_RC component2 = item.GetComponent<CCTV_RC>();
if (!(component2 == null) && component2.IsStatic() && !controlBookmarks.Contains(component.GetIdentifier()))
{
ForceAddBookmark(component.GetIdentifier());
}
}
}
Facepunch.Pool.FreeUnmanaged(ref obj);
}
}
public override void PostServerLoad()
{
base.PostServerLoad();
GatherStaticCameras();
}
public void StopControl(BasePlayer ply)
{
BaseEntity baseEntity = currentlyControllingEnt.Get(serverside: true);
if ((bool)baseEntity)
{
baseEntity.GetComponent<IRemoteControllable>().StopControl(new CameraViewerId(currentPlayerID, 0L));
}
if ((bool)ply)
{
ply.net.SwitchSecondaryGroup(null);
ply.SetRcEntityPosition(null);
}
currentlyControllingEnt.uid = default(NetworkableId);
currentPlayerID = 0uL;
SetFlag(Flags.Reserved2, b: false, recursive: false, networkupdate: false);
SendNetworkUpdate();
SendControlBookmarks(ply);
CancelInvoke(ControlCheck);
CancelInvoke(CheckCCTVAchievement);
}
public bool IsPlayerAtStation(BasePlayer player)
{
return player == GetMounted();
}
[RPC_Server]
public void AdminForceDeleteBookmark(RPCMessage msg)
{
if (msg.player.IsAdmin)
{
string identifier = msg.read.String();
RemoveBookmark(identifier, GetMounted());
}
}
[RPC_Server]
public void AdminForceClearBookmarks(RPCMessage msg)
{
if (msg.player.IsAdmin)
{
controlBookmarks.Clear();
BasePlayer mounted = GetMounted();
if (mounted != null)
{
SendControlBookmarks(mounted);
StopControl(mounted);
}
}
}
[RPC_Server]
public void DeleteBookmark(RPCMessage msg)
{
BasePlayer player = msg.player;
if (IsPlayerAtStation(player) && !isStatic)
{
string identifier = msg.read.String();
RemoveBookmark(identifier, player);
}
}
private void RemoveBookmark(string identifier, BasePlayer mountedPlayer = null)
{
if (!IsValidIdentifier(identifier) || !controlBookmarks.Contains(identifier))
{
return;
}
controlBookmarks.Remove(identifier);
if (mountedPlayer != null)
{
SendControlBookmarks(mountedPlayer);
BaseEntity baseEntity = currentlyControllingEnt.Get(serverside: true);
if (baseEntity != null && baseEntity.TryGetComponent<IRemoteControllable>(out var component) && component.GetIdentifier() == identifier)
{
StopControl(mountedPlayer);
}
}
}
[RPC_Server]
public void Server_DisconnectControl(RPCMessage msg)
{
BasePlayer player = msg.player;
if (IsPlayerAtStation(player))
{
StopControl(player);
}
}
[RPC_Server]
public void BeginControllingBookmark(RPCMessage msg)
{
BasePlayer player = msg.player;
if (!IsPlayerAtStation(player))
{
return;
}
string text = msg.read.String();
if (!IsValidIdentifier(text) || !controlBookmarks.Contains(text))
{
return;
}
IRemoteControllable remoteControllable = RemoteControlEntity.FindByID(text);
if (remoteControllable == null)
{
return;
}
BaseEntity ent = remoteControllable.GetEnt();
if (ent == null)
{
Debug.LogWarning("RC identifier " + text + " was found but has a null or destroyed entity, this should never happen");
}
else if (remoteControllable.CanControl(player.userID) && !(Vector3.Distance(base.transform.position, ent.transform.position) >= remoteControllable.MaxRange))
{
BaseEntity baseEntity = currentlyControllingEnt.Get(serverside: true);
if ((bool)baseEntity)
{
baseEntity.GetComponent<IRemoteControllable>()?.StopControl(new CameraViewerId(currentPlayerID, 0L));
}
player.net.SwitchSecondaryGroup(ent.net.group);
player.SetRcEntityPosition(ent.transform.position);
currentlyControllingEnt.uid = ent.net.ID;
currentPlayerID = player.userID;
bool b = remoteControllable.InitializeControl(new CameraViewerId(currentPlayerID, 0L));
SetFlag(Flags.Reserved2, b, recursive: false, networkupdate: false);
SendNetworkUpdateImmediate();
SendControlBookmarks(player);
if (GameInfo.HasAchievements && remoteControllable.GetEnt() is CCTV_RC)
{
InvokeRepeating(CheckCCTVAchievement, 1f, 3f);
}
InvokeRepeating(ControlCheck, 0f, 0f);
}
}
private void CheckCCTVAchievement()
{
BasePlayer mounted = GetMounted();
if (!(mounted != null))
{
return;
}
BaseEntity baseEntity = currentlyControllingEnt.Get(serverside: true);
if (!(baseEntity != null) || !(baseEntity is CCTV_RC cCTV_RC))
{
return;
}
foreach (Connection subscriber in mounted.net.secondaryGroup.subscribers)
{
if (!subscriber.active)
{
continue;
}
BasePlayer basePlayer = subscriber.player as BasePlayer;
if (!(basePlayer == null))
{
Vector3 vector = basePlayer.CenterPoint();
float num = Vector3.Dot((vector - cCTV_RC.pitch.position).normalized, cCTV_RC.pitch.forward);
Vector3 vector2 = cCTV_RC.pitch.InverseTransformPoint(vector);
if (num > 0.6f && vector2.magnitude < 10f)
{
mounted.GiveAchievement("BIG_BROTHER");
CancelInvoke(CheckCCTVAchievement);
break;
}
}
}
}
public bool CanAddBookmark(BasePlayer player)
{
if (!IsPlayerAtStation(player))
{
return false;
}
if (isStatic)
{
return false;
}
if (UnityEngine.Time.realtimeSinceStartup < nextAddTime)
{
return false;
}
if (controlBookmarks.Count > 3)
{
player.ChatMessage("Too many bookmarks, delete some");
return false;
}
return true;
}
[RPC_Server]
public void AdminForceAddBookmark(RPCMessage msg)
{
if (msg.player.IsAdmin)
{
string identifier = msg.read.String();
ForceAddBookmark(identifier);
BasePlayer mounted = GetMounted();
if (mounted != null)
{
SendControlBookmarks(mounted);
}
}
}
public void ForceAddBookmark(string identifier)
{
if (controlBookmarks.Count >= 128 || !IsValidIdentifier(identifier) || controlBookmarks.Contains(identifier))
{
return;
}
IRemoteControllable remoteControllable = RemoteControlEntity.FindByID(identifier);
if (remoteControllable != null)
{
if (remoteControllable.GetEnt() == null)
{
Debug.LogWarning("RC identifier " + identifier + " was found but has a null or destroyed entity, this should never happen");
}
else
{
controlBookmarks.Add(identifier);
}
}
}
[RPC_Server]
public void AddBookmark(RPCMessage msg)
{
BasePlayer player = msg.player;
if (IsPlayerAtStation(player) && !isStatic)
{
if (UnityEngine.Time.realtimeSinceStartup < nextAddTime)
{
player.ChatMessage("Slow down...");
return;
}
if (controlBookmarks.Count >= 128)
{
player.ChatMessage("Too many bookmarks, delete some");
return;
}
nextAddTime = UnityEngine.Time.realtimeSinceStartup + 1f;
string identifier = msg.read.String();
ForceAddBookmark(identifier);
SendControlBookmarks(player);
}
}
public void ControlCheck()
{
bool flag = false;
BaseEntity baseEntity = currentlyControllingEnt.Get(base.isServer);
BasePlayer mounted = GetMounted();
if ((bool)baseEntity && (bool)mounted)
{
IRemoteControllable component = baseEntity.GetComponent<IRemoteControllable>();
if (component != null && component.CanControl(mounted.userID) && Vector3.Distance(base.transform.position, baseEntity.transform.position) < component.MaxRange)
{
flag = true;
mounted.net.SwitchSecondaryGroup(baseEntity.net.group);
mounted.SetRcEntityPosition(baseEntity.transform.position);
}
}
if (!flag)
{
StopControl(mounted);
}
}
public string GenerateControlBookmarkString()
{
return string.Join(";", controlBookmarks);
}
public void SendControlBookmarks(BasePlayer player)
{
if (!(player == null))
{
string arg = GenerateControlBookmarkString();
ClientRPC(RpcTarget.Player("ReceiveBookmarks", player), arg);
}
}
public override void OnPlayerMounted()
{
base.OnPlayerMounted();
BasePlayer mounted = GetMounted();
if ((bool)mounted)
{
SendControlBookmarks(mounted);
}
SetFlag(Flags.On, b: true);
}
public override void OnPlayerDismounted(BasePlayer player)
{
base.OnPlayerDismounted(player);
StopControl(player);
SetFlag(Flags.On, b: false);
}
public override void PlayerServerInput(InputState inputState, BasePlayer player)
{
base.PlayerServerInput(inputState, player);
if (HasFlag(Flags.Reserved2) && currentlyControllingEnt.IsValid(serverside: true))
{
currentlyControllingEnt.Get(serverside: true).GetComponent<IRemoteControllable>().UserInput(inputState, new CameraViewerId(player.userID, 0L));
}
}
public override void Save(SaveInfo info)
{
base.Save(info);
if (!info.forDisk)
{
info.msg.ioEntity = Facepunch.Pool.Get<ProtoBuf.IOEntity>();
info.msg.ioEntity.genericEntRef1 = currentlyControllingEnt.uid;
}
else
{
info.msg.computerStation = Facepunch.Pool.Get<ProtoBuf.ComputerStation>();
info.msg.computerStation.bookmarks = GenerateControlBookmarkString();
}
}
public override void AttemptMount(BasePlayer player, bool doMountChecks = true)
{
if (CanPlayerSeeMountAnchor(player))
{
base.AttemptMount(player, doMountChecks);
}
}
private bool CanPlayerSeeMountAnchor(BasePlayer player)
{
return !GamePhysics.CheckCapsule(player.eyes.position, mountAnchor.position + Vector3.up * 0.3f, 0.05f, 2097152);
}
public override void Load(LoadInfo info)
{
base.Load(info);
if (!info.fromDisk)
{
if (info.msg.ioEntity != null)
{
currentlyControllingEnt.uid = info.msg.ioEntity.genericEntRef1;
}
}
else
{
if (info.msg.computerStation == null)
{
return;
}
string[] array = info.msg.computerStation.bookmarks.Split(BookmarkSplit, StringSplitOptions.RemoveEmptyEntries);
foreach (string text in array)
{
if (IsValidIdentifier(text))
{
controlBookmarks.Add(text);
}
}
}
}
}