SRMP-Public/SRMP/SRMP.cs

271 lines
10 KiB
C#

using MonomiPark.SlimeRancher.Persist;
using MonomiPark.SlimeRancher.Regions;
using SRMultiplayer.Networking;
using SRMultiplayer.Packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace SRMultiplayer
{
public class SRMP : SRSingleton<SRMP>
{
public static string ModDataPath { get { return Path.Combine(Application.dataPath, "..", "SRMP"); } }
private float m_LastTimeSync;
/// <summary>
/// Acts as the initializer for the Mod
/// </summary>
public override void Awake()
{
base.Awake();
//attach scene manager to trigger event when in a menu or loading up a game
SceneManager.activeSceneChanged += SceneManager_activeSceneChanged;
//attach log messager to log all game errors and exceptions into the SRMP Logs
Application.logMessageReceived += Application_logMessageReceived;
//load up mod specific resources
var myLoadedAssetBundle = AssetBundle.LoadFromMemory(Utils.ExtractResource("SRMultiplayer.srmultiplayer.dat"));
if (myLoadedAssetBundle == null)
{
SRMP.Log("Failed to load AssetBundle!");
return;
}
//load up the Player moment animator for the Beatrix model
Globals.BeatrixController = myLoadedAssetBundle.LoadAsset<RuntimeAnimatorController>("Controller");
//unused prefab menus, these menus functions are handled in the floating gui
//Globals.IngameMultiplayerMenuPrefab = myLoadedAssetBundle.LoadAsset<GameObject>("IngameMultiplayerMenu");
//Globals.MainMultiplayerMenuPrefab = myLoadedAssetBundle.LoadAsset<GameObject>("MainMultiplayerMenu");
}
/// <summary>
/// Subscriber to the Applicaiton log and process it on to the Mods console
/// </summary>
/// <param name="condition">Log condition</param>
/// <param name="stackTrace">Stack trace of log strigger (if applicable)</param>
/// <param name="type">Log Type</param>
private void Application_logMessageReceived(string condition, string stackTrace, LogType type)
{
//if Error or Exception hand the error of to the Mods log/console to display
if(type == LogType.Error || type == LogType.Exception)
{
SRMP.Log(condition);
if (!string.IsNullOrEmpty(stackTrace))
SRMP.Log(stackTrace);
}
}
private void Start()
{
//var menuObj = Instantiate(Globals.MainMultiplayerMenuPrefab, null, false);
//menuObj.AddComponent<NetworkClientUI>();
}
/// <summary>
/// After triggering base destroy
/// trigger disconnect and shut down the server
/// </summary>
public override void OnDestroy()
{
base.OnDestroy();
NetworkClient.Instance.Disconnect();
NetworkServer.Instance.Disconnect();
}
/// <summary>
/// On Game quit trigger disconnect and shut down the server
/// </summary>
private void OnApplicationQuit()
{
NetworkClient.Instance.Disconnect();
NetworkServer.Instance.Disconnect();
}
/// <summary>
/// On Update triggered sync up game time
/// </summary>
private void Update()
{
if(Globals.GameLoaded)
{
if(Globals.IsServer)
{
//every 30 seconds send a time updater out to all clients
if(Time.time - m_LastTimeSync > 30)
{
m_LastTimeSync = Time.time;
new PacketWorldTime()
{
Time = SRSingleton<SceneContext>.Instance.TimeDirector.WorldTime()
}.Send();
}
}
//if(Time.time - m_LastActorTime > 0.5f)
//{
// foreach(var actor in Globals.Actors.Values.ToList())
// {
// if(actor.IsLocal && !actor.gameObject.activeInHierarchy)
// {
// actor.DropOwnership();
// //SRMP.Log($"Dropping actor {actor.name} ({actor.ID}) as it's unloaded");
// }
// }
//}
}
}
/// <summary>
/// Handle scene changed events triggered by the game
/// </summary>
/// <param name="from">Scene previously</param>
/// <param name="to">New Scene</param>
private void SceneManager_activeSceneChanged(Scene from, Scene to)
{
//trigger handlers for returning or going to the main menu
if (to.buildIndex == 2) OnMainMenuLoaded();
//trigger handlers for loading the game
else if (to.buildIndex == 3) OnGameLoaded();
}
/// <summary>
/// Handle user changing to the main menu, whether it is start up or from saving/ being kicked out of the game
/// </summary>
private void OnMainMenuLoaded()
{
//var menuObj = Instantiate(Globals.MainMultiplayerMenuPrefab, null, false);
//menuObj.AddComponent<NetworkClientUI>();
//innitialize all necessary global variables
Globals.LocalID = 0;
Globals.DisableAchievements = false;
Globals.GameLoaded = false;
Globals.ClientLoaded = false;
Globals.LocalPlayer = null;
Globals.Audios.Clear();
Globals.Actors.Clear();
Globals.Regions.Clear();
Globals.LandPlots.Clear();
Globals.SpawnResources.Clear();
Globals.FXPrefabs.Clear();
Globals.AccessDoors.Clear();
Globals.Gordos.Clear();
Globals.PuzzleSlots.Clear();
Globals.Switches.Clear();
Globals.GadgetSites.Clear();
Globals.PacketSize.Clear();
Globals.Spawners.Clear();
Globals.TreasurePods.Clear();
Globals.ExchangeAcceptors.Clear();
Globals.FireColumns.Clear();
Globals.Kookadobas.Clear();
Globals.LemonTrees.Clear();
Globals.Nutcrackers.Clear();
Globals.RaceTriggers.Clear();
NetworkAmmo.All.Clear();
//clean up any lingering players in the global list
foreach (var player in Globals.Players.Values.ToList())
{
if(player != null && player.gameObject != null)
{
Destroy(player.gameObject);
}
}
Globals.Players.Clear();
//reset the chat
ChatUI.Instance.Clear();
}
/// <summary>
/// Handle the user loading into the multiplayer game
/// </summary>
private void OnGameLoaded()
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
var ranchui = Resources.FindObjectsOfTypeAll<RanchHouseUI>().FirstOrDefault();
if (ranchui != null)
{
Globals.BeatrixModel = Instantiate(ranchui.beatrixPrefab.transform.GetChild(1).GetChild(0).gameObject);
Globals.BeatrixModel.transform.localScale *= 0.75f;
Globals.BeatrixModel.SetActive(false);
Utils.SetLayer(Globals.BeatrixModel, 0);
}
foreach (var audio in Resources.FindObjectsOfTypeAll<SECTR_AudioCue>())
{
Globals.Audios.Add(audio.name, audio);
}
var splashOnTrigger = GameObject.FindObjectOfType<SplashOnTrigger>();
Globals.FXPrefabs.Add(splashOnTrigger.playerSplashFX.name, splashOnTrigger.playerSplashFX);
Globals.FXPrefabs.Add(splashOnTrigger.splashFX.name, splashOnTrigger.splashFX);
if (Globals.IsClient)
{
Globals.DisableAchievements = true;
Globals.LocalPlayer.transform.SetParent(SRSingleton<SceneContext>.Instance.Player.transform, false);
Globals.LocalPlayer.HasLoaded = true;
foreach (var player in Globals.Players.Values.ToList())
{
if (player.HasLoaded)
{
player.Spawn();
}
}
new PacketPlayerLoaded().Send();
}
else
{
//var hostMenuObj = Instantiate(Globals.IngameMultiplayerMenuPrefab, SRSingleton<PauseMenu>.Instance.transform, true);
//hostMenuObj.AddComponent<NetworkHostUI>();
//hostMenuObj.SetActive(false);
}
Globals.PauseState = PauseState.Playing;
Globals.GameLoaded = true;
stopwatch.Stop();
SRMP.Log($"Loaded the game in {stopwatch.ElapsedMilliseconds}ms");
}
private static FileStream m_LogFileStream;
private static StreamWriter m_LogWriter;
/// <summary>
/// Custom message logging of a given message
/// </summary>
/// <param name="msg">Main message to be logged</param>
/// <param name="prefix">Prefix to be displayed before the message. Prefix will be after time marker and before the message
/// It will also be incapsulated in []</param>
public static void Log(string msg, string prefix = null)
{
if(m_LogFileStream == null)
{
string n = string.Format("log-{0:yyyy-MM-dd_hh-mm-ss-tt}.txt", DateTime.Now);
Directory.CreateDirectory(Path.Combine(ModDataPath, "Logs"));
m_LogFileStream = File.Create(Path.Combine(ModDataPath, "Logs", n));
m_LogWriter = new StreamWriter(m_LogFileStream);
}
string txt = $"[{DateTime.Now.ToString("HH:mm:ss")}]{(prefix != null ? "[" + prefix + "]" : "")} {msg}";
Debug.Log("[SRMP]" + txt);
m_LogWriter.WriteLine(txt);
m_LogWriter.Flush();
}
}
}