mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-01-29 00:32:43 +00:00
commit
20b56995c7
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
QSB/AssetBundles/qsb_hud
Normal file
BIN
QSB/AssetBundles/qsb_hud
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
19
QSB/HUD/HUDIcon.cs
Normal file
19
QSB/HUD/HUDIcon.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace QSB.HUD;
|
||||
|
||||
public enum HUDIcon
|
||||
{
|
||||
UNKNOWN,
|
||||
SPACE,
|
||||
DEAD,
|
||||
SHIP,
|
||||
CAVE_TWIN,
|
||||
TOWER_TWIN,
|
||||
TIMBER_HEARTH,
|
||||
ATTLEROCK,
|
||||
BRITTLE_HOLLOW,
|
||||
HOLLOWS_LANTERN,
|
||||
GIANTS_DEEP,
|
||||
DARK_BRAMBLE,
|
||||
INTERLOPER,
|
||||
WHITE_HOLE
|
||||
}
|
24
QSB/HUD/Messages/PlanetMessage.cs
Normal file
24
QSB/HUD/Messages/PlanetMessage.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
using QSB.Utility;
|
||||
|
||||
namespace QSB.HUD.Messages;
|
||||
|
||||
internal class PlanetMessage : QSBMessage<HUDIcon>
|
||||
{
|
||||
public PlanetMessage(HUDIcon icon) : base(icon) { }
|
||||
|
||||
public override void OnReceiveLocal() => OnReceiveRemote();
|
||||
|
||||
public override void OnReceiveRemote()
|
||||
{
|
||||
var from = QSBPlayerManager.GetPlayer(From);
|
||||
|
||||
if (from == default)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
from.HUDBox?.UpdateIcon(Data);
|
||||
}
|
||||
}
|
272
QSB/HUD/MultiplayerHUDManager.cs
Normal file
272
QSB/HUD/MultiplayerHUDManager.cs
Normal file
@ -0,0 +1,272 @@
|
||||
using QSB.HUD.Messages;
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
using QSB.ServerSettings;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace QSB.HUD;
|
||||
|
||||
internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
|
||||
{
|
||||
public static MultiplayerHUDManager Instance;
|
||||
|
||||
private Transform _playerList;
|
||||
private Material _markerMaterial;
|
||||
|
||||
public static Sprite UnknownSprite;
|
||||
public static Sprite DeadSprite;
|
||||
public static Sprite SpaceSprite;
|
||||
public static Sprite ShipSprite;
|
||||
public static Sprite TimberHearth;
|
||||
public static Sprite Attlerock;
|
||||
public static Sprite CaveTwin;
|
||||
public static Sprite TowerTwin;
|
||||
public static Sprite BrittleHollow;
|
||||
public static Sprite HollowsLantern;
|
||||
public static Sprite GiantsDeep;
|
||||
public static Sprite DarkBramble;
|
||||
public static Sprite Interloper;
|
||||
public static Sprite WhiteHole;
|
||||
|
||||
public static ListStack<HUDIcon> HUDIconStack = new();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
GlobalMessenger.AddListener(OWEvents.WakeUp, OnWakeUp);
|
||||
|
||||
QSBPlayerManager.OnAddPlayer += OnAddPlayer;
|
||||
QSBPlayerManager.OnRemovePlayer += OnRemovePlayer;
|
||||
|
||||
UnknownSprite = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_unknown.png");
|
||||
DeadSprite = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_dead.png");
|
||||
ShipSprite = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_ship.png");
|
||||
CaveTwin = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_cavetwin.png");
|
||||
TowerTwin = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_towertwin.png");
|
||||
TimberHearth = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_timberhearth.png");
|
||||
Attlerock = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_attlerock.png");
|
||||
BrittleHollow = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_brittlehollow.png");
|
||||
HollowsLantern = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_hollowslantern.png");
|
||||
GiantsDeep = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_giantsdeep.png");
|
||||
DarkBramble = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_darkbramble.png");
|
||||
Interloper = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_interloper.png");
|
||||
WhiteHole = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_whitehole.png");
|
||||
SpaceSprite = QSBCore.HUDAssetBundle.LoadAsset<Sprite>("Assets/MULTIPLAYER_UI/playerbox_space.png");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!QSBWorldSync.AllObjectsReady || _playerList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_playerList.gameObject.SetActive(ServerSettingsManager.ShowExtraHUD);
|
||||
}
|
||||
|
||||
private void OnWakeUp()
|
||||
{
|
||||
var hudController = Locator.GetPlayerCamera().transform.Find("Helmet").Find("HUDController").GetComponent<HUDCanvas>();
|
||||
var hudCamera = hudController._hudCamera;
|
||||
var hudCanvas = hudCamera.transform.parent.Find("UICanvas");
|
||||
|
||||
var multiplayerGroup = Instantiate(QSBCore.HUDAssetBundle.LoadAsset<GameObject>("assets/Prefabs/multiplayergroup.prefab"));
|
||||
|
||||
Delay.RunNextFrame(() =>
|
||||
{
|
||||
// no idea why this has to be next frame, but it does
|
||||
multiplayerGroup.transform.parent = hudCanvas;
|
||||
multiplayerGroup.transform.localPosition = Vector3.zero;
|
||||
var rect = multiplayerGroup.GetComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(1, 0.5f);
|
||||
rect.anchorMax = new Vector2(1, 0.5f);
|
||||
rect.sizeDelta = new Vector2(100, 100);
|
||||
rect.anchoredPosition3D = new Vector3(-267, 0, 0);
|
||||
rect.localRotation = Quaternion.Euler(0, 55, 0);
|
||||
rect.localScale = Vector3.one;
|
||||
});
|
||||
|
||||
_playerList = multiplayerGroup.transform.Find("PlayerList");
|
||||
|
||||
foreach (var player in QSBPlayerManager.PlayerList)
|
||||
{
|
||||
AddBox(player);
|
||||
|
||||
foreach (var item in QSBWorldSync.GetUnityObjects<Minimap>())
|
||||
{
|
||||
AddMinimapMarker(player, item);
|
||||
}
|
||||
}
|
||||
|
||||
CreateTrigger("TowerTwin_Body/Sector_TowerTwin", HUDIcon.TOWER_TWIN);
|
||||
CreateTrigger("CaveTwin_Body/Sector_CaveTwin", HUDIcon.CAVE_TWIN);
|
||||
CreateTrigger("TimberHearth_Body/Sector_TH", HUDIcon.TIMBER_HEARTH);
|
||||
CreateTrigger("Moon_Body/Sector_THM", HUDIcon.ATTLEROCK);
|
||||
CreateTrigger("BrittleHollow_Body/Sector_BH", HUDIcon.BRITTLE_HOLLOW);
|
||||
CreateTrigger("VolcanicMoon_Body/Sector_VM", HUDIcon.HOLLOWS_LANTERN);
|
||||
CreateTrigger("GiantsDeep_Body/Sector_GD", HUDIcon.GIANTS_DEEP);
|
||||
CreateTrigger("DarkBramble_Body/Sector_DB", HUDIcon.DARK_BRAMBLE);
|
||||
CreateTrigger("Comet_Body/Sector_CO", HUDIcon.INTERLOPER);
|
||||
CreateTrigger("WhiteHole_Body/Sector_WhiteHole", HUDIcon.WHITE_HOLE);
|
||||
|
||||
HUDIconStack.Clear();
|
||||
HUDIconStack.Push(HUDIcon.SPACE);
|
||||
HUDIconStack.Push(HUDIcon.TIMBER_HEARTH);
|
||||
|
||||
new PlanetMessage(HUDIcon.TIMBER_HEARTH).Send();
|
||||
|
||||
var playerMinimap = QSBWorldSync.GetUnityObjects<Minimap>().First(x => x.name == "Minimap_Root");
|
||||
_markerMaterial = Instantiate(playerMinimap._probeMarkerTransform.GetComponent<MeshRenderer>().material);
|
||||
_markerMaterial.color = Color.gray;
|
||||
}
|
||||
|
||||
public void UpdateMinimapMarkers(Minimap minimap)
|
||||
{
|
||||
var localRuleset = Locator.GetPlayerRulesetDetector().GetPlanetoidRuleset();
|
||||
|
||||
foreach (var player in QSBPlayerManager.PlayerList)
|
||||
{
|
||||
if (player.IsDead || player.IsLocalPlayer || !player.IsReady)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player.RulesetDetector == null)
|
||||
{
|
||||
if (player.Body != null)
|
||||
{
|
||||
DebugLog.ToConsole($"Error - {player.PlayerId}'s RulesetDetector is null.", OWML.Common.MessageType.Error);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player.RulesetDetector.GetPlanetoidRuleset() == null
|
||||
|| player.RulesetDetector.GetPlanetoidRuleset() != localRuleset)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player.MinimapPlayerMarker == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ServerSettingsManager.ShowExtraHUD)
|
||||
{
|
||||
player.MinimapPlayerMarker.localPosition = GetLocalMapPosition(player, minimap);
|
||||
player.MinimapPlayerMarker.LookAt(minimap._globeMeshTransform, minimap._globeMeshTransform.up);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.MinimapPlayerMarker.localPosition = Vector3.zero;
|
||||
player.MinimapPlayerMarker.localRotation = Quaternion.identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddMinimapMarker(PlayerInfo player, Minimap minimap)
|
||||
{
|
||||
player.MinimapPlayerMarker = Instantiate(minimap._probeMarkerTransform);
|
||||
player.MinimapPlayerMarker.parent = minimap._probeMarkerTransform.parent;
|
||||
player.MinimapPlayerMarker.localScale = new Vector3(0.05f, 0.05f, 0.05f);
|
||||
player.MinimapPlayerMarker.localPosition = Vector3.zero;
|
||||
player.MinimapPlayerMarker.localRotation = Quaternion.identity;
|
||||
player.MinimapPlayerMarker.GetComponent<MeshRenderer>().material = _markerMaterial;
|
||||
}
|
||||
|
||||
private void AddBox(PlayerInfo player)
|
||||
{
|
||||
var box = Instantiate(QSBCore.HUDAssetBundle.LoadAsset<GameObject>("assets/Prefabs/playerbox.prefab"));
|
||||
box.transform.parent = _playerList;
|
||||
box.transform.localScale = new Vector3(1, 1, 1);
|
||||
box.transform.localPosition = Vector3.zero;
|
||||
box.transform.localRotation = Quaternion.identity;
|
||||
|
||||
var boxScript = box.GetComponent<PlayerBox>();
|
||||
boxScript.AssignPlayer(player);
|
||||
}
|
||||
|
||||
private Vector3 GetLocalMapPosition(PlayerInfo player, Minimap minimap)
|
||||
{
|
||||
return Vector3.Scale(
|
||||
player.RulesetDetector.GetPlanetoidRuleset().transform.InverseTransformPoint(player.Body.transform.position).normalized * 0.51f,
|
||||
minimap._globeMeshTransform.localScale);
|
||||
}
|
||||
|
||||
private void OnAddPlayer(PlayerInfo player)
|
||||
{
|
||||
if (!QSBWorldSync.AllObjectsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AddBox(player);
|
||||
|
||||
foreach (var item in QSBWorldSync.GetUnityObjects<Minimap>())
|
||||
{
|
||||
AddMinimapMarker(player, item);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRemovePlayer(PlayerInfo player)
|
||||
{
|
||||
Destroy(player.HUDBox.gameObject);
|
||||
}
|
||||
|
||||
private PlanetTrigger CreateTrigger(string parentPath, HUDIcon icon)
|
||||
=> CreateTrigger(Find(parentPath), icon);
|
||||
|
||||
private PlanetTrigger CreateTrigger(GameObject parent, HUDIcon icon)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var triggerGO = parent.FindChild("HUD_PLANET_TRIGGER");
|
||||
if (triggerGO != null)
|
||||
{
|
||||
var trigger = triggerGO.GetAddComponent<PlanetTrigger>();
|
||||
trigger.Icon = icon;
|
||||
return trigger;
|
||||
}
|
||||
else
|
||||
{
|
||||
triggerGO = new GameObject("HUD_PLANET_TRIGGER");
|
||||
triggerGO.transform.SetParent(parent.transform, false);
|
||||
triggerGO.SetActive(false);
|
||||
var trigger = triggerGO.AddComponent<PlanetTrigger>();
|
||||
trigger.Icon = icon;
|
||||
triggerGO.SetActive(true);
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
|
||||
public static GameObject Find(string path)
|
||||
{
|
||||
var go = GameObject.Find(path);
|
||||
|
||||
if (go == null)
|
||||
{
|
||||
// find inactive use root + transform.find
|
||||
var names = path.Split('/');
|
||||
var rootName = names[0];
|
||||
var root = SceneManager.GetActiveScene().GetRootGameObjects().FirstOrDefault(x => x.name == rootName);
|
||||
if (root == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var childPath = string.Join("/", names.Skip(1));
|
||||
go = root.FindChild(childPath);
|
||||
}
|
||||
|
||||
return go;
|
||||
}
|
||||
}
|
17
QSB/HUD/Patches/MinimapPatches.cs
Normal file
17
QSB/HUD/Patches/MinimapPatches.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
|
||||
namespace QSB.HUD.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(Minimap))]
|
||||
internal class MinimapPatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(nameof(Minimap.UpdateMarkers))]
|
||||
public static void UpdateMarkers(Minimap __instance)
|
||||
{
|
||||
MultiplayerHUDManager.Instance.UpdateMinimapMarkers(__instance);
|
||||
}
|
||||
}
|
54
QSB/HUD/Patches/RulesetVolumePatches.cs
Normal file
54
QSB/HUD/Patches/RulesetVolumePatches.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
using QSB.Player;
|
||||
using QSB.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.HUD.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(RulesetVolume))]
|
||||
internal class RulesetVolumePatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(RulesetVolume.OnEffectVolumeEnter))]
|
||||
public static bool OnEffectVolumeEnter(RulesetVolume __instance, GameObject hitObj)
|
||||
{
|
||||
var baseDetector = hitObj.GetComponent<RulesetDetector>();
|
||||
var customDetector = hitObj.GetComponent<RemotePlayerRulesetDetector>();
|
||||
if (baseDetector != null)
|
||||
{
|
||||
baseDetector.AddVolume(__instance);
|
||||
}
|
||||
else if (customDetector != null)
|
||||
{
|
||||
customDetector.AddVolume(__instance);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(RulesetVolume.OnEffectVolumeExit))]
|
||||
public static bool OnEffectVolumeExit(RulesetVolume __instance, GameObject hitObj)
|
||||
{
|
||||
var baseDetector = hitObj.GetComponent<RulesetDetector>();
|
||||
var customDetector = hitObj.GetComponent<RemotePlayerRulesetDetector>();
|
||||
if (baseDetector != null)
|
||||
{
|
||||
baseDetector.RemoveVolume(__instance);
|
||||
}
|
||||
else if (customDetector != null)
|
||||
{
|
||||
customDetector.RemoveVolume(__instance);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
34
QSB/HUD/PlanetTrigger.cs
Normal file
34
QSB/HUD/PlanetTrigger.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using QSB.HUD.Messages;
|
||||
using QSB.Messaging;
|
||||
using QSB.Utility;
|
||||
|
||||
namespace QSB.HUD;
|
||||
|
||||
public class PlanetTrigger : SectoredMonoBehaviour
|
||||
{
|
||||
public HUDIcon Icon;
|
||||
|
||||
public override void OnSectorOccupantAdded(SectorDetector detector)
|
||||
{
|
||||
if (detector.GetOccupantType() != DynamicOccupant.Player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MultiplayerHUDManager.HUDIconStack.Push(Icon);
|
||||
var top = MultiplayerHUDManager.HUDIconStack.Peek();
|
||||
new PlanetMessage(top).Send();
|
||||
}
|
||||
|
||||
public override void OnSectorOccupantRemoved(SectorDetector detector)
|
||||
{
|
||||
if (detector.GetOccupantType() != DynamicOccupant.Player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MultiplayerHUDManager.HUDIconStack.Remove(Icon);
|
||||
var top = MultiplayerHUDManager.HUDIconStack.Peek();
|
||||
new PlanetMessage(top).Send();
|
||||
}
|
||||
}
|
113
QSB/HUD/PlayerBox.cs
Normal file
113
QSB/HUD/PlayerBox.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using QSB.Player;
|
||||
using QSB.Player.Messages;
|
||||
using QSB.Utility;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QSB.HUD;
|
||||
|
||||
public class PlayerBox : MonoBehaviour
|
||||
{
|
||||
public Text PlayerName;
|
||||
public Image InfoImage;
|
||||
|
||||
private PlayerInfo _player;
|
||||
private bool _planetIconOverride;
|
||||
private bool _inUnknown;
|
||||
|
||||
public HUDIcon PlanetIcon { get; private set; }
|
||||
|
||||
public void AssignPlayer(PlayerInfo player)
|
||||
{
|
||||
_player = player;
|
||||
_player.HUDBox = this;
|
||||
|
||||
if (player.Name != null)
|
||||
{
|
||||
PlayerName.text = player.Name.ToUpper();
|
||||
}
|
||||
|
||||
InfoImage.sprite = MultiplayerHUDManager.UnknownSprite;
|
||||
|
||||
new RequestStateResyncMessage().Send();
|
||||
}
|
||||
|
||||
public void OnDeath()
|
||||
{
|
||||
InfoImage.sprite = MultiplayerHUDManager.DeadSprite;
|
||||
_planetIconOverride = true;
|
||||
}
|
||||
|
||||
public void OnRespawn()
|
||||
{
|
||||
InfoImage.sprite = MultiplayerHUDManager.ShipSprite;
|
||||
_planetIconOverride = true; // still in ship
|
||||
}
|
||||
|
||||
public void OnEnterShip()
|
||||
{
|
||||
if (_inUnknown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InfoImage.sprite = MultiplayerHUDManager.ShipSprite;
|
||||
_planetIconOverride = true;
|
||||
}
|
||||
|
||||
public void OnExitShip()
|
||||
{
|
||||
if (_inUnknown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_planetIconOverride = false;
|
||||
InfoImage.sprite = SpriteFromEnum(PlanetIcon);
|
||||
}
|
||||
|
||||
public void OnEnterUnknown()
|
||||
{
|
||||
_inUnknown = true;
|
||||
_planetIconOverride = true;
|
||||
InfoImage.sprite = MultiplayerHUDManager.UnknownSprite;
|
||||
}
|
||||
|
||||
public void OnExitUnknown()
|
||||
{
|
||||
_inUnknown = false;
|
||||
_planetIconOverride = false;
|
||||
InfoImage.sprite = SpriteFromEnum(PlanetIcon);
|
||||
}
|
||||
|
||||
public void UpdateIcon(HUDIcon icon)
|
||||
{
|
||||
PlanetIcon = icon;
|
||||
|
||||
if (!_planetIconOverride)
|
||||
{
|
||||
InfoImage.sprite = SpriteFromEnum(PlanetIcon);
|
||||
}
|
||||
}
|
||||
|
||||
public Sprite SpriteFromEnum(HUDIcon icon) => icon switch
|
||||
{
|
||||
HUDIcon.SHIP => MultiplayerHUDManager.ShipSprite,
|
||||
HUDIcon.DEAD => MultiplayerHUDManager.DeadSprite,
|
||||
HUDIcon.SPACE => MultiplayerHUDManager.SpaceSprite,
|
||||
HUDIcon.CAVE_TWIN => MultiplayerHUDManager.CaveTwin,
|
||||
HUDIcon.TOWER_TWIN => MultiplayerHUDManager.TowerTwin,
|
||||
HUDIcon.TIMBER_HEARTH => MultiplayerHUDManager.TimberHearth,
|
||||
HUDIcon.ATTLEROCK => MultiplayerHUDManager.Attlerock,
|
||||
HUDIcon.BRITTLE_HOLLOW => MultiplayerHUDManager.BrittleHollow,
|
||||
HUDIcon.HOLLOWS_LANTERN => MultiplayerHUDManager.HollowsLantern,
|
||||
HUDIcon.GIANTS_DEEP => MultiplayerHUDManager.GiantsDeep,
|
||||
HUDIcon.DARK_BRAMBLE => MultiplayerHUDManager.DarkBramble,
|
||||
HUDIcon.INTERLOPER => MultiplayerHUDManager.Interloper,
|
||||
HUDIcon.WHITE_HOLE => MultiplayerHUDManager.WhiteHole,
|
||||
_ => MultiplayerHUDManager.UnknownSprite,
|
||||
};
|
||||
}
|
@ -60,15 +60,19 @@ internal class EnterLeaveMessage : QSBMessage<EnterLeaveType>
|
||||
{
|
||||
case EnterLeaveType.EnterMoon:
|
||||
player.IsInMoon = true;
|
||||
player.HUDBox.OnEnterUnknown();
|
||||
break;
|
||||
case EnterLeaveType.ExitMoon:
|
||||
player.IsInMoon = false;
|
||||
player.HUDBox.OnExitUnknown();
|
||||
break;
|
||||
case EnterLeaveType.EnterCloak:
|
||||
player.IsInCloak = true;
|
||||
player.HUDBox.OnEnterUnknown();
|
||||
break;
|
||||
case EnterLeaveType.ExitCloak:
|
||||
player.IsInCloak = false;
|
||||
player.HUDBox.OnExitUnknown();
|
||||
break;
|
||||
case EnterLeaveType.EnterPlatform:
|
||||
CustomNomaiRemoteCameraPlatform.CustomPlatformList[ObjectId]
|
||||
|
@ -1,6 +1,7 @@
|
||||
using Mirror;
|
||||
using OWML.Common;
|
||||
using QSB.ClientServerStateSync;
|
||||
using QSB.HUD;
|
||||
using QSB.Messaging;
|
||||
using QSB.Utility;
|
||||
|
||||
@ -19,6 +20,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
private ClientState ClientState;
|
||||
private float FieldOfView;
|
||||
private bool IsInShip;
|
||||
private HUDIcon HUDIcon;
|
||||
|
||||
public PlayerInformationMessage()
|
||||
{
|
||||
@ -34,6 +36,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
ClientState = player.State;
|
||||
FieldOfView = PlayerData.GetGraphicSettings().fieldOfView;
|
||||
IsInShip = player.IsInShip;
|
||||
HUDIcon = player.HUDBox == null ? HUDIcon.UNKNOWN : player.HUDBox.PlanetIcon;
|
||||
}
|
||||
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
@ -50,6 +53,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
writer.Write(ClientState);
|
||||
writer.Write(FieldOfView);
|
||||
writer.Write(IsInShip);
|
||||
writer.Write(HUDIcon);
|
||||
}
|
||||
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
@ -66,6 +70,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
ClientState = reader.Read<ClientState>();
|
||||
FieldOfView = reader.ReadFloat();
|
||||
IsInShip = reader.ReadBool();
|
||||
HUDIcon = reader.Read<HUDIcon>();
|
||||
}
|
||||
|
||||
public override void OnReceiveRemote()
|
||||
@ -93,6 +98,12 @@ public class PlayerInformationMessage : QSBMessage
|
||||
() => player.Camera.fieldOfView = FieldOfView);
|
||||
|
||||
player.State = ClientState;
|
||||
|
||||
Delay.RunWhen(() => player.HUDBox != null, () =>
|
||||
{
|
||||
player.HUDBox.PlayerName.text = PlayerName.ToUpper();
|
||||
player.HUDBox.UpdateIcon(HUDIcon);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
using QSB.Animation.Player;
|
||||
using QSB.Audio;
|
||||
using QSB.ClientServerStateSync;
|
||||
using QSB.HUD;
|
||||
using QSB.Messaging;
|
||||
using QSB.ModelShip;
|
||||
using QSB.Player.Messages;
|
||||
@ -11,6 +12,7 @@ using QSB.ShipSync;
|
||||
using QSB.Tools;
|
||||
using QSB.Utility;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.Player;
|
||||
|
||||
@ -23,6 +25,8 @@ public partial class PlayerInfo
|
||||
public string Name { get; set; }
|
||||
public PlayerHUDMarker HudMarker { get; set; }
|
||||
public PlayerMapMarker MapMarker { get; set; }
|
||||
public PlayerBox HUDBox { get; set; }
|
||||
public Transform MinimapPlayerMarker { get; set; }
|
||||
public PlayerTransformSync TransformSync { get; }
|
||||
public ClientState State { get; set; }
|
||||
public EyeState EyeState { get; set; }
|
||||
@ -39,6 +43,7 @@ public partial class PlayerInfo
|
||||
public ThrusterLightTracker ThrusterLightTracker;
|
||||
public bool FlyingShip => ShipManager.Instance.CurrentFlyer == PlayerId;
|
||||
public bool FlyingModelShip => ModelShipManager.Instance.CurrentFlyer == PlayerId;
|
||||
public RemotePlayerRulesetDetector RulesetDetector { get; set; }
|
||||
|
||||
public PlayerInfo(PlayerTransformSync transformSync)
|
||||
{
|
||||
@ -159,5 +164,19 @@ public partial class PlayerInfo
|
||||
}
|
||||
}
|
||||
|
||||
public void Die()
|
||||
{
|
||||
IsDead = true;
|
||||
SetVisible(false, 1);
|
||||
HUDBox.OnDeath();
|
||||
}
|
||||
|
||||
public void Revive()
|
||||
{
|
||||
IsDead = false;
|
||||
SetVisible(true, 1);
|
||||
HUDBox.OnRespawn();
|
||||
}
|
||||
|
||||
public override string ToString() => $"{PlayerId}:{GetType().Name} ({Name})";
|
||||
}
|
||||
|
@ -8,15 +8,7 @@ public partial class PlayerInfo
|
||||
{
|
||||
public OWCamera Camera
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_camera == null && IsReady)
|
||||
{
|
||||
DebugLog.ToConsole($"Warning - {PlayerId}.Camera is null!", MessageType.Warning);
|
||||
}
|
||||
|
||||
return _camera;
|
||||
}
|
||||
get => _camera;
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
|
73
QSB/Player/RemotePlayerRulesetDetector.cs
Normal file
73
QSB/Player/RemotePlayerRulesetDetector.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using QSB.Utility;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.Player;
|
||||
|
||||
[UsedInUnityProject]
|
||||
public class RemotePlayerRulesetDetector : Detector
|
||||
{
|
||||
private PlanetoidRuleset _closestPlanetoidRuleset;
|
||||
private List<PlanetoidRuleset> _planetoidRulesets;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_planetoidRulesets = new List<PlanetoidRuleset>(8);
|
||||
}
|
||||
|
||||
public override void AddVolume(EffectVolume volume)
|
||||
{
|
||||
if ((volume as RulesetVolume) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base.AddVolume(volume);
|
||||
if (volume.GetType() == typeof(PlanetoidRuleset))
|
||||
{
|
||||
_planetoidRulesets.Add((PlanetoidRuleset)volume);
|
||||
UpdateClosestPlanetoidRuleset();
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveVolume(EffectVolume volume)
|
||||
{
|
||||
if ((volume as RulesetVolume) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base.RemoveVolume(volume);
|
||||
if (volume.GetType() == typeof(PlanetoidRuleset))
|
||||
{
|
||||
_planetoidRulesets.Remove((PlanetoidRuleset)volume);
|
||||
UpdateClosestPlanetoidRuleset();
|
||||
}
|
||||
}
|
||||
|
||||
public PlanetoidRuleset GetPlanetoidRuleset() => _closestPlanetoidRuleset;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_planetoidRulesets.Count > 1)
|
||||
{
|
||||
UpdateClosestPlanetoidRuleset();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateClosestPlanetoidRuleset()
|
||||
{
|
||||
_closestPlanetoidRuleset = null;
|
||||
var num = float.PositiveInfinity;
|
||||
for (var i = 0; i < _planetoidRulesets.Count; i++)
|
||||
{
|
||||
var num2 = Vector3.SqrMagnitude(_planetoidRulesets[i].transform.position - transform.position);
|
||||
if (num2 < num)
|
||||
{
|
||||
_closestPlanetoidRuleset = _planetoidRulesets[i];
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,12 @@ public static class FontReplacer
|
||||
|
||||
foreach (var monoBehaviour in prefab.GetComponentsInChildren<MonoBehaviour>(true))
|
||||
{
|
||||
if (monoBehaviour == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Null monobehaviour found on {prefab.name}!", OWML.Common.MessageType.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var publicFields = monoBehaviour
|
||||
.GetType()
|
||||
.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
@ -53,6 +53,7 @@ public static class RemotePlayerCreation
|
||||
player.Body = REMOTE_Player_Body;
|
||||
player.ThrusterLightTracker = player.Body.GetComponentInChildren<ThrusterLightTracker>();
|
||||
player.FluidDetector = REMOTE_PlayerDetector.GetComponent<RemotePlayerFluidDetector>();
|
||||
player.RulesetDetector = REMOTE_PlayerDetector.GetComponent<RemotePlayerRulesetDetector>();
|
||||
|
||||
player.AnimationSync.InitRemote(REMOTE_Traveller_HEA_Player_v2.transform);
|
||||
|
||||
|
@ -50,6 +50,7 @@ public class QSBCore : ModBehaviour
|
||||
public static AssetBundle NetworkAssetBundle { get; private set; }
|
||||
public static AssetBundle ConversationAssetBundle { get; private set; }
|
||||
public static AssetBundle DebugAssetBundle { get; private set; }
|
||||
public static AssetBundle HUDAssetBundle { get; private set; }
|
||||
public static bool IsHost => NetworkServer.active;
|
||||
public static bool IsInMultiplayer;
|
||||
public static string QSBVersion => Helper.Manifest.Version;
|
||||
@ -60,6 +61,7 @@ public class QSBCore : ModBehaviour
|
||||
public static bool IncompatibleModsAllowed { get; private set; }
|
||||
public static bool ShowPlayerNames { get; private set; }
|
||||
public static bool ShipDamage { get; private set; }
|
||||
public static bool ShowExtraHUDElements { get ; private set; }
|
||||
public static GameVendor GameVendor { get; private set; } = GameVendor.None;
|
||||
public static bool IsStandalone => GameVendor is GameVendor.Epic or GameVendor.Steam;
|
||||
public static IProfileManager ProfileManager => IsStandalone
|
||||
@ -174,6 +176,7 @@ public class QSBCore : ModBehaviour
|
||||
NetworkAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_network");
|
||||
ConversationAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_conversation");
|
||||
DebugAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_debug");
|
||||
HUDAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_hud");
|
||||
|
||||
if (NetworkAssetBundle == null || ConversationAssetBundle == null || DebugAssetBundle == null)
|
||||
{
|
||||
@ -255,6 +258,7 @@ public class QSBCore : ModBehaviour
|
||||
IncompatibleModsAllowed = config.GetSettingsValue<bool>("incompatibleModsAllowed");
|
||||
ShowPlayerNames = config.GetSettingsValue<bool>("showPlayerNames");
|
||||
ShipDamage = config.GetSettingsValue<bool>("shipDamage");
|
||||
ShowExtraHUDElements = config.GetSettingsValue<bool>("showExtraHud");
|
||||
|
||||
if (IsHost)
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ internal class RespawnManager : MonoBehaviour, IAddComponentOnStart
|
||||
|
||||
public void OnPlayerDeath(PlayerInfo player)
|
||||
{
|
||||
player.IsDead = true;
|
||||
player.Die();
|
||||
|
||||
if (_playersPendingRespawn.Contains(player))
|
||||
{
|
||||
@ -160,13 +160,11 @@ internal class RespawnManager : MonoBehaviour, IAddComponentOnStart
|
||||
new EndLoopMessage().Send();
|
||||
return;
|
||||
}
|
||||
|
||||
player.SetVisible(false, 1);
|
||||
}
|
||||
|
||||
public void OnPlayerRespawn(PlayerInfo player)
|
||||
{
|
||||
player.IsDead = false;
|
||||
player.Revive();
|
||||
|
||||
if (!_playersPendingRespawn.Contains(player))
|
||||
{
|
||||
@ -176,8 +174,6 @@ internal class RespawnManager : MonoBehaviour, IAddComponentOnStart
|
||||
{
|
||||
_playersPendingRespawn.Remove(player);
|
||||
}
|
||||
|
||||
player.SetVisible(true, 1);
|
||||
}
|
||||
|
||||
public void RespawnSomePlayer()
|
||||
|
@ -7,4 +7,5 @@ internal class ServerSettingsManager : MonoBehaviour, IAddComponentOnStart
|
||||
{
|
||||
public static bool ServerShowPlayerNames;
|
||||
public static bool ShowPlayerNames => (ServerShowPlayerNames || QSBCore.IsHost) && QSBCore.ShowPlayerNames;
|
||||
public static bool ShowExtraHUD => ShowPlayerNames && QSBCore.ShowExtraHUDElements;
|
||||
}
|
||||
|
@ -166,6 +166,7 @@ internal class ShipManager : WorldObjectManager
|
||||
public void AddPlayerToShip(PlayerInfo player)
|
||||
{
|
||||
player.IsInShip = true;
|
||||
player.HUDBox.OnEnterShip();
|
||||
_playersInShip.Add(player);
|
||||
UpdateElectricalComponent();
|
||||
}
|
||||
@ -173,6 +174,7 @@ internal class ShipManager : WorldObjectManager
|
||||
public void RemovePlayerFromShip(PlayerInfo player)
|
||||
{
|
||||
player.IsInShip = false;
|
||||
player.HUDBox.OnExitShip();
|
||||
_playersInShip.Remove(player);
|
||||
UpdateElectricalComponent();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using QSB.ClientServerStateSync;
|
||||
using QSB.EchoesOfTheEye.Ghosts.WorldObjects;
|
||||
using QSB.HUD;
|
||||
using QSB.Player;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.ShipSync;
|
||||
@ -152,6 +153,12 @@ internal class DebugGUI : MonoBehaviour, IAddComponentOnStart
|
||||
{
|
||||
WriteLine(1, $" - {item}");
|
||||
}
|
||||
|
||||
WriteLine(1, $"HUD Icon Stack :");
|
||||
foreach (var item in MultiplayerHUDManager.HUDIconStack)
|
||||
{
|
||||
WriteLine(1, $" - {item}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -172,10 +179,10 @@ internal class DebugGUI : MonoBehaviour, IAddComponentOnStart
|
||||
|
||||
if (player.IsReady && QSBWorldSync.AllObjectsReady)
|
||||
{
|
||||
WriteLine(2, $"Illuminated : {player.LightSensor.IsIlluminated()}");
|
||||
WriteLine(2, $"Illuminated : {player.LightSensor?.IsIlluminated()}");
|
||||
var singleLightSensor = (SingleLightSensor)player.LightSensor;
|
||||
// will be null for remote player light sensors
|
||||
if (singleLightSensor._lightSources != null)
|
||||
if (singleLightSensor?._lightSources != null)
|
||||
{
|
||||
foreach (var item in singleLightSensor._lightSources)
|
||||
{
|
||||
|
@ -31,6 +31,9 @@ public static class Extensions
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static GameObject FindChild(this GameObject g, string childPath) =>
|
||||
g.transform.Find(childPath)?.gameObject;
|
||||
|
||||
#endregion
|
||||
|
||||
#region MIRROR
|
||||
|
51
QSB/Utility/ListStack.cs
Normal file
51
QSB/Utility/ListStack.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QSB.Utility;
|
||||
|
||||
public class ListStack<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly List<T> _items = new();
|
||||
|
||||
public void Clear()
|
||||
=> _items.Clear();
|
||||
|
||||
public void Push(T item)
|
||||
{
|
||||
if (_items.Contains(item))
|
||||
{
|
||||
RemoveAll(x => EqualityComparer<T>.Default.Equals(x, item));
|
||||
}
|
||||
|
||||
_items.Add(item);
|
||||
}
|
||||
|
||||
public T Pop()
|
||||
{
|
||||
if (_items.Count > 0)
|
||||
{
|
||||
var temp = _items[_items.Count - 1];
|
||||
_items.RemoveAt(_items.Count - 1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public T Peek() => _items.Count > 0
|
||||
? _items[_items.Count - 1]
|
||||
: default;
|
||||
|
||||
public void RemoveAt(int index)
|
||||
=> _items.RemoveAt(index);
|
||||
|
||||
public bool Remove(T item)
|
||||
=> _items.Remove(item);
|
||||
|
||||
public int RemoveAll(Predicate<T> match)
|
||||
=> _items.RemoveAll(match);
|
||||
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => ((IEnumerable<T>)_items).GetEnumerator();
|
||||
public IEnumerator GetEnumerator() => ((IEnumerable<T>)_items).GetEnumerator();
|
||||
}
|
@ -24,6 +24,12 @@
|
||||
"type": "toggle",
|
||||
"value": true,
|
||||
"tooltip": "Take impact damage when inside the ship."
|
||||
},
|
||||
"showExtraHud": {
|
||||
"title": "Show Extra HUD Elements",
|
||||
"type": "toggle",
|
||||
"value": true,
|
||||
"tooltip" : "Show extra HUD elements, like player status and minimap icons."
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user