Nekopletní fix

This commit is contained in:
Dominik G.
2025-10-29 19:14:20 +01:00
parent cd0ef3c73a
commit 4c110f98c0
9 changed files with 18049 additions and 39 deletions

View File

@@ -0,0 +1,250 @@
using UnityEngine;
using TMPro;
using Steamworks;
using MegaKoop.Game.Networking;
namespace MegaKoop.Game.UI
{
[DefaultExecutionOrder(10000)]
[DisallowMultipleComponent]
public class SteamNameTag : MonoBehaviour
{
[SerializeField] private Transform followHead;
[SerializeField] private Vector3 worldOffset = new Vector3(0f, 2.5f, 0f);
[SerializeField] private bool billboardToCamera = true;
[SerializeField] private bool hideForLocal = true;
[SerializeField] private float visibleDistance = 60f;
private TextMeshPro text;
private Transform tagTransform;
private Transform camTransform;
private SteamCharacterNetworkBridge bridge;
private Callback<PersonaStateChange_t> personaChanged;
private ulong lastSteamId;
private float camFindTimer;
private Coroutine ensureActiveRoutine;
private void Awake()
{
// Reuse existing NameTag child if present (prevents duplicates when cloning templates)
var existing = transform.Find("NameTag");
GameObject go;
if (existing != null)
{
tagTransform = existing;
go = existing.gameObject;
}
else
{
go = new GameObject("NameTag");
go.layer = gameObject.layer;
tagTransform = go.transform;
tagTransform.SetParent(transform, worldPositionStays: false);
}
if (!go.activeSelf) go.SetActive(true);
text = go.GetComponent<TextMeshPro>();
if (text == null)
{
text = go.AddComponent<TextMeshPro>();
}
text.alignment = TextAlignmentOptions.Center;
text.color = Color.white;
text.fontSize = 2.5f;
text.enableAutoSizing = true;
text.fontSizeMin = 1.5f;
text.fontSizeMax = 4.5f;
text.text = GetObjectDisplayName();
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
text.enabled = true;
bridge = GetComponent<SteamCharacterNetworkBridge>();
if (followHead == null)
{
followHead = FindChildRecursive(transform, "Head");
if (followHead == null)
{
followHead = transform;
worldOffset = new Vector3(0f, 2.5f, 0f);
}
}
}
public void SetFollowHead(Transform head, SteamCharacterNetworkBridge b)
{
if (head != null) followHead = head;
if (b != null) bridge = b;
UpdateDisplayName(true);
}
private void OnEnable()
{
camTransform = Camera.main != null ? Camera.main.transform : null;
TryCreatePersonaCallback();
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
{
tagTransform.gameObject.SetActive(true);
}
if (text != null)
{
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
text.enabled = true;
}
if (ensureActiveRoutine == null)
{
ensureActiveRoutine = StartCoroutine(EnsureActiveLoop());
}
UpdateDisplayName(true);
}
private void OnDisable()
{
personaChanged = null;
if (ensureActiveRoutine != null)
{
StopCoroutine(ensureActiveRoutine);
ensureActiveRoutine = null;
}
}
private void TryCreatePersonaCallback()
{
if (personaChanged == null)
{
personaChanged = Callback<PersonaStateChange_t>.Create(OnPersonaChanged);
}
}
private System.Collections.IEnumerator EnsureActiveLoop()
{
var waiter = new WaitForEndOfFrame();
while (isActiveAndEnabled)
{
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
{
tagTransform.gameObject.SetActive(true);
}
if (text != null)
{
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
text.enabled = true;
}
yield return waiter;
}
}
private void OnPersonaChanged(PersonaStateChange_t cb)
{
if (bridge == null) return;
if (cb.m_ulSteamID == bridge.OwnerSteamId)
{
UpdateDisplayName(true);
}
}
private void LateUpdate()
{
camFindTimer -= Time.unscaledDeltaTime;
if ((camTransform == null || !camTransform.gameObject.activeInHierarchy) && camFindTimer <= 0f)
{
var cam = Camera.main;
camTransform = cam != null ? cam.transform : null;
camFindTimer = 1f;
}
// Never deactivate the NameTag GameObject; only toggle text rendering
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
{
tagTransform.gameObject.SetActive(true);
}
Vector3 basePos = followHead != null ? followHead.position : transform.position;
tagTransform.position = basePos + worldOffset;
if (billboardToCamera && camTransform != null)
{
Vector3 dir = tagTransform.position - camTransform.position;
if (dir.sqrMagnitude > 0.001f)
{
tagTransform.rotation = Quaternion.LookRotation(dir, Vector3.up);
}
}
if (text != null)
{
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
text.enabled = true;
}
UpdateDisplayName(false);
}
private void UpdateDisplayName(bool force)
{
if (text == null) return;
ulong sid = 0;
if (bridge != null) sid = bridge.OwnerSteamId;
if (!force && sid == lastSteamId && !string.IsNullOrEmpty(text.text)) return;
lastSteamId = sid;
string display = null;
if (sid != 0)
{
display = ResolvePersonaName(sid);
}
if (string.IsNullOrWhiteSpace(display))
{
display = GetObjectDisplayName();
}
if (!string.Equals(text.text, display))
{
text.text = display;
}
}
private string ResolvePersonaName(ulong sid)
{
if (!SteamBootstrap.IsInitialized)
{
return null;
}
ulong local = SteamUser.GetSteamID().m_SteamID;
if (sid == local)
{
return SteamFriends.GetPersonaName();
}
var csid = new CSteamID(sid);
string name = SteamFriends.GetFriendPersonaName(csid);
if (string.IsNullOrEmpty(name) || name == "???")
{
SteamFriends.RequestUserInformation(csid, true);
}
return name;
}
private string GetObjectDisplayName()
{
string n = transform.root != null ? transform.root.name : gameObject.name;
if (n.StartsWith("Wizard_"))
{
return n.Substring("Wizard_".Length);
}
return n;
}
private static Transform FindChildRecursive(Transform root, string name)
{
if (root == null) return null;
foreach (Transform c in root)
{
if (c.name == name) return c;
var r = FindChildRecursive(c, name);
if (r != null) return r;
}
return null;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 79fb1fbc20d80f546ba695c751860930