Decompiled source of AuroraVikingMessages v1.0.1

plugins/VikingMessages.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("VikingMessages")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyDescription("Elden Ring-inspired message system for Valheim")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Viking Messages")]
[assembly: AssemblyTitle("Viking Messages")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VikingMessages
{
	[Serializable]
	public class VikingMessage
	{
		public string Id;

		public Vector3 Position;

		public Quaternion Rotation;

		public string Template;

		public string Words;

		public int EmoteIndex;

		public long AuthorId;

		public string AuthorName;

		public int Reputation;

		public List<long> VotedPlayers = new List<long>();

		public DateTime CreatedTime;

		public string[] EquippedItems = new string[0];

		public Vector3 LookDirection;
	}
	[Serializable]
	public class PlayerReputation
	{
		public long PlayerId;

		public string PlayerName;

		public int TotalReputation;

		public int MessageCount;

		public PlayerReputation()
		{
		}

		public PlayerReputation(long id, string name)
		{
			PlayerId = id;
			PlayerName = name;
			TotalReputation = 0;
			MessageCount = 0;
		}
	}
	[Serializable]
	public class LeaderboardData
	{
		public List<PlayerReputation> Players = new List<PlayerReputation>();
	}
	public class GhostPhantom : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <PlayEmoteDelayed>d__21 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public string emoteName;

			public GhostPhantom <>4__this;

			private string <triggerName>5__1;

			private Exception <ex>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlayEmoteDelayed>d__21(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<triggerName>5__1 = null;
				<ex>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)<>4__this._animator != (Object)null)
					{
						try
						{
							((Behaviour)<>4__this._animator).enabled = true;
							<>4__this._animator.speed = 0.7f;
							<triggerName>5__1 = "emote_" + emoteName.ToLower();
							ManualLogSource log = VikingMessagesPlugin.Log;
							if (log != null)
							{
								log.LogInfo((object)("Attempting to play emote trigger: " + <triggerName>5__1));
							}
							<>4__this._animator.SetTrigger(<triggerName>5__1);
							<triggerName>5__1 = null;
						}
						catch (Exception ex)
						{
							<ex>5__2 = ex;
							ManualLogSource log2 = VikingMessagesPlugin.Log;
							if (log2 != null)
							{
								log2.LogWarning((object)("Failed to play emote " + emoteName + ": " + <ex>5__2.Message));
							}
						}
					}
					else
					{
						ManualLogSource log3 = VikingMessagesPlugin.Log;
						if (log3 != null)
						{
							log3.LogWarning((object)"No animator available for ghost emote");
						}
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SetupGhostCoroutine>d__13 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public GhostPhantom <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetupGhostCoroutine>d__13(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)Player.m_localPlayer == (Object)null)
					{
						ManualLogSource log = VikingMessagesPlugin.Log;
						if (log != null)
						{
							log.LogWarning((object)"No local player for ghost clone");
						}
						<>4__this.CreateFallbackGhost();
					}
					else
					{
						<>4__this.CreatePlayerClone();
					}
					<>4__this.CreateGlowLight();
					<>4__this.Show();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private float _displayDuration = 5f;

		private float _currentTimer;

		private float _fadeInTime = 0.5f;

		private bool _isVisible;

		private List<Renderer> _renderers = new List<Renderer>();

		private static readonly Color GhostColor = new Color(0.85f, 0.9f, 1f, 0.7f);

		private GameObject _visualClone;

		private Animator _animator;

		private Light _glowLight;

		private string _pendingEmote;

		private VikingMessage _message;

		public void Initialize(VikingMessage message, float duration = 5f)
		{
			_message = message;
			_displayDuration = duration;
			_pendingEmote = GetEmoteName(message.EmoteIndex);
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"GhostPhantom.Initialize: emote={_pendingEmote}, emoteIndex={message.EmoteIndex}");
			}
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(SetupGhostCoroutine());
		}

		[IteratorStateMachine(typeof(<SetupGhostCoroutine>d__13))]
		private IEnumerator SetupGhostCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetupGhostCoroutine>d__13(0)
			{
				<>4__this = this
			};
		}

		private void CreatePlayerClone()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player localPlayer = Player.m_localPlayer;
				Transform val = ((Component)localPlayer).transform.Find("Visual");
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = VikingMessagesPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"Could not find Visual transform on player");
					}
					CreateFallbackGhost();
					return;
				}
				_visualClone = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)this).transform);
				((Object)_visualClone).name = "GhostVisual";
				_visualClone.transform.localPosition = Vector3.zero;
				_visualClone.transform.localRotation = Quaternion.identity;
				_visualClone.transform.localScale = Vector3.one;
				_animator = _visualClone.GetComponent<Animator>();
				if ((Object)(object)_animator == (Object)null)
				{
					_animator = _visualClone.GetComponentInChildren<Animator>();
				}
				DisableComponents(_visualClone);
				Renderer[] componentsInChildren = _visualClone.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						val2.enabled = true;
						SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val2 is SkinnedMeshRenderer) ? val2 : null);
						if (val3 != null)
						{
							val3.updateWhenOffscreen = true;
						}
					}
				}
				Transform[] componentsInChildren2 = _visualClone.GetComponentsInChildren<Transform>(true);
				foreach (Transform val4 in componentsInChildren2)
				{
					if ((Object)(object)val4 != (Object)null && (Object)(object)((Component)val4).gameObject != (Object)null)
					{
						((Component)val4).gameObject.SetActive(true);
					}
				}
				ApplyGhostMaterials(_visualClone);
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"Ghost clone created successfully with {_renderers.Count} renderers");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = VikingMessagesPlugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)$"Failed to create player clone: {arg}");
				}
				CreateFallbackGhost();
			}
		}

		private void DisableComponents(GameObject obj)
		{
			MonoBehaviour[] componentsInChildren = obj.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)this)
				{
					((Behaviour)val).enabled = false;
				}
			}
			ZNetView[] componentsInChildren2 = obj.GetComponentsInChildren<ZNetView>(true);
			foreach (ZNetView val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
			}
			ZSyncTransform[] componentsInChildren3 = obj.GetComponentsInChildren<ZSyncTransform>(true);
			foreach (ZSyncTransform val3 in componentsInChildren3)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)val3);
				}
			}
			ZSyncAnimation[] componentsInChildren4 = obj.GetComponentsInChildren<ZSyncAnimation>(true);
			foreach (ZSyncAnimation val4 in componentsInChildren4)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
			}
			VisEquipment[] componentsInChildren5 = obj.GetComponentsInChildren<VisEquipment>(true);
			foreach (VisEquipment val5 in componentsInChildren5)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					Object.Destroy((Object)(object)val5);
				}
			}
			Collider[] componentsInChildren6 = obj.GetComponentsInChildren<Collider>(true);
			foreach (Collider val6 in componentsInChildren6)
			{
				if ((Object)(object)val6 != (Object)null)
				{
					val6.enabled = false;
				}
			}
			ParticleSystem[] componentsInChildren7 = obj.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val7 in componentsInChildren7)
			{
				if ((Object)(object)val7 != (Object)null)
				{
					val7.Stop();
				}
			}
			AudioSource[] componentsInChildren8 = obj.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val8 in componentsInChildren8)
			{
				if ((Object)(object)val8 != (Object)null)
				{
					((Behaviour)val8).enabled = false;
				}
			}
		}

		private void ApplyGhostMaterials(GameObject obj)
		{
			_renderers.Clear();
			Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					_renderers.Add(val);
					Material[] array = (Material[])(object)new Material[val.sharedMaterials.Length];
					for (int j = 0; j < val.sharedMaterials.Length; j++)
					{
						Material val2 = CreateGhostMaterial(val.sharedMaterials[j]);
						array[j] = val2;
					}
					val.materials = array;
				}
			}
		}

		private Material CreateGhostMaterial(Material sourceMat)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Standard");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Sprites/Default");
			}
			Material val2 = new Material(val);
			if ((Object)(object)sourceMat != (Object)null && sourceMat.HasProperty("_MainTex"))
			{
				val2.mainTexture = sourceMat.mainTexture;
			}
			val2.color = GhostColor;
			val2.SetFloat("_Mode", 3f);
			val2.SetInt("_SrcBlend", 5);
			val2.SetInt("_DstBlend", 10);
			val2.SetInt("_ZWrite", 0);
			val2.DisableKeyword("_ALPHATEST_ON");
			val2.EnableKeyword("_ALPHABLEND_ON");
			val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			val2.renderQueue = 3000;
			val2.EnableKeyword("_EMISSION");
			val2.SetColor("_EmissionColor", new Color(0.3f, 0.4f, 0.5f));
			return val2;
		}

		private void CreateFallbackGhost()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Creating fallback ghost (primitive shapes)");
			}
			Material val = CreateGhostMaterial(null);
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)1);
			((Object)val2).name = "GhostBody";
			val2.transform.SetParent(((Component)this).transform);
			val2.transform.localPosition = new Vector3(0f, 1f, 0f);
			val2.transform.localScale = new Vector3(0.5f, 0.7f, 0.35f);
			Object.Destroy((Object)(object)val2.GetComponent<Collider>());
			Renderer component = val2.GetComponent<Renderer>();
			component.material = val;
			_renderers.Add(component);
			GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val3).name = "GhostHead";
			val3.transform.SetParent(((Component)this).transform);
			val3.transform.localPosition = new Vector3(0f, 1.85f, 0f);
			val3.transform.localScale = new Vector3(0.35f, 0.35f, 0.35f);
			Object.Destroy((Object)(object)val3.GetComponent<Collider>());
			Renderer component2 = val3.GetComponent<Renderer>();
			component2.material = Object.Instantiate<Material>(val);
			_renderers.Add(component2);
			GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)1);
			val4.transform.SetParent(((Component)this).transform);
			val4.transform.localPosition = new Vector3(-0.4f, 1.2f, 0f);
			val4.transform.localRotation = Quaternion.Euler(0f, 0f, 30f);
			val4.transform.localScale = new Vector3(0.12f, 0.35f, 0.12f);
			Object.Destroy((Object)(object)val4.GetComponent<Collider>());
			val4.GetComponent<Renderer>().material = Object.Instantiate<Material>(val);
			_renderers.Add(val4.GetComponent<Renderer>());
			GameObject val5 = GameObject.CreatePrimitive((PrimitiveType)1);
			val5.transform.SetParent(((Component)this).transform);
			val5.transform.localPosition = new Vector3(0.4f, 1.2f, 0f);
			val5.transform.localRotation = Quaternion.Euler(0f, 0f, -30f);
			val5.transform.localScale = new Vector3(0.12f, 0.35f, 0.12f);
			Object.Destroy((Object)(object)val5.GetComponent<Collider>());
			val5.GetComponent<Renderer>().material = Object.Instantiate<Material>(val);
			_renderers.Add(val5.GetComponent<Renderer>());
		}

		private void CreateGlowLight()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("GhostLight");
			val.transform.SetParent(((Component)this).transform);
			val.transform.localPosition = new Vector3(0f, 1.2f, 0f);
			_glowLight = val.AddComponent<Light>();
			_glowLight.type = (LightType)2;
			_glowLight.color = new Color(0.7f, 0.8f, 1f);
			_glowLight.intensity = 0.8f;
			_glowLight.range = 3f;
			_glowLight.shadows = (LightShadows)0;
		}

		public void Show()
		{
			((Component)this).gameObject.SetActive(true);
			_isVisible = true;
			_currentTimer = _displayDuration;
			if (!string.IsNullOrEmpty(_pendingEmote))
			{
				((MonoBehaviour)this).StartCoroutine(PlayEmoteDelayed(_pendingEmote));
			}
			UpdateAlpha(0f);
		}

		[IteratorStateMachine(typeof(<PlayEmoteDelayed>d__21))]
		private IEnumerator PlayEmoteDelayed(string emoteName)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlayEmoteDelayed>d__21(0)
			{
				<>4__this = this,
				emoteName = emoteName
			};
		}

		public void Hide()
		{
			_isVisible = false;
			((Component)this).gameObject.SetActive(false);
			foreach (Renderer renderer in _renderers)
			{
				if (!((Object)(object)renderer != (Object)null))
				{
					continue;
				}
				Material[] materials = renderer.materials;
				foreach (Material val in materials)
				{
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			Object.Destroy((Object)(object)((Component)this).gameObject, 0.1f);
		}

		private void Update()
		{
			if (_isVisible)
			{
				_currentTimer -= Time.deltaTime;
				EnsureRenderersEnabled();
				float num = _displayDuration - _currentTimer;
				float num2 = 2f;
				float alpha = ((num < _fadeInTime) ? (num / _fadeInTime * 0.7f) : ((!(_currentTimer < num2)) ? 0.7f : (_currentTimer / num2 * 0.7f)));
				UpdateAlpha(alpha);
				if ((Object)(object)_glowLight != (Object)null)
				{
					_glowLight.intensity = 0.6f + Mathf.Sin(Time.time * 3f) * 0.2f;
				}
				if (_currentTimer <= 0f)
				{
					Hide();
				}
			}
		}

		private void EnsureRenderersEnabled()
		{
			if ((Object)(object)_visualClone == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = _visualClone.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && !val.enabled)
				{
					val.enabled = true;
				}
			}
			Transform[] componentsInChildren2 = _visualClone.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)null && !((Component)val2).gameObject.activeSelf && ((Object)(object)((Component)val2).GetComponent<Renderer>() != (Object)null || (Object)(object)((Component)val2).GetComponent<SkinnedMeshRenderer>() != (Object)null))
				{
					((Component)val2).gameObject.SetActive(true);
				}
			}
		}

		private void UpdateAlpha(float alpha)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Color ghostColor = GhostColor;
			ghostColor.a = alpha;
			foreach (Renderer renderer in _renderers)
			{
				if ((Object)(object)renderer == (Object)null)
				{
					continue;
				}
				Material[] materials = renderer.materials;
				foreach (Material val in materials)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.color = ghostColor;
					}
				}
			}
		}

		private string GetEmoteName(int emoteIndex)
		{
			List<string> availableEmotes = MessageTemplates.AvailableEmotes;
			if (availableEmotes != null && emoteIndex >= 0 && emoteIndex < availableEmotes.Count)
			{
				return availableEmotes[emoteIndex];
			}
			return "wave";
		}

		private void OnDestroy()
		{
			foreach (Renderer renderer in _renderers)
			{
				if (!((Object)(object)renderer != (Object)null))
				{
					continue;
				}
				Material[] materials = renderer.materials;
				foreach (Material val in materials)
				{
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			_renderers.Clear();
		}
	}
	public static class GhostPhantomManager
	{
		private static GhostPhantom _currentGhost;

		public static void ShowGhost(Vector3 position, Quaternion rotation, VikingMessage message, float duration = 5f)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)_currentGhost != (Object)null)
				{
					_currentGhost.Hide();
					_currentGhost = null;
				}
				GameObject val = new GameObject("VikingMessageGhost");
				val.transform.position = position;
				val.transform.rotation = rotation;
				_currentGhost = val.AddComponent<GhostPhantom>();
				_currentGhost.Initialize(message, duration);
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Ghost spawned at {position} with rotation {((Quaternion)(ref rotation)).eulerAngles}");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Failed to spawn ghost: {arg}");
				}
			}
		}

		public static void HideCurrentGhost()
		{
			if ((Object)(object)_currentGhost != (Object)null)
			{
				_currentGhost.Hide();
				_currentGhost = null;
			}
		}

		public static void Cleanup()
		{
			HideCurrentGhost();
		}
	}
	public static class LeaderboardManager
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__CloseLeaderboard;
		}

		private static GameObject _leaderboardUI;

		private static bool _isVisible;

		private static bool _hasStealthBuff;

		private static bool _hasCarryBuff;

		public const float CARRY_WEIGHT_BONUS = 500f;

		private static SE_Stats _reputationBuff;

		private const string BUFF_NAME = "SE_ReputationTop3";

		public static bool IsVisible => _isVisible;

		public static void ShowLeaderboard()
		{
			if ((Object)(object)_leaderboardUI != (Object)null)
			{
				CloseLeaderboard();
				return;
			}
			CreateLeaderboardUI();
			_isVisible = true;
			GUIManager.BlockInput(true);
		}

		public static void CloseLeaderboard()
		{
			if ((Object)(object)_leaderboardUI != (Object)null)
			{
				Object.Destroy((Object)(object)_leaderboardUI);
				_leaderboardUI = null;
			}
			_isVisible = false;
			GUIManager.BlockInput(false);
		}

		private static void CreateLeaderboardUI()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (GUIManager.Instance == null)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"GUIManager not ready");
				}
				return;
			}
			try
			{
				_leaderboardUI = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 500f, 550f, false);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("CreateWoodpanel failed: " + ex.Message));
				}
			}
			if ((Object)(object)_leaderboardUI == (Object)null)
			{
				_leaderboardUI = CreateFallbackPanel();
			}
			if ((Object)(object)_leaderboardUI == (Object)null)
			{
				ManualLogSource log3 = VikingMessagesPlugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)"Failed to create leaderboard UI");
				}
			}
			else
			{
				PopulateLeaderboardContent();
			}
		}

		private static GameObject CreateFallbackPanel()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("VikingMessages_LeaderboardCanvas");
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = 100;
			CanvasScaler val3 = val.AddComponent<CanvasScaler>();
			val3.uiScaleMode = (ScaleMode)1;
			val3.referenceResolution = new Vector2(1920f, 1080f);
			val.AddComponent<GraphicRaycaster>();
			GameObject val4 = new GameObject("Panel");
			val4.transform.SetParent(val.transform, false);
			RectTransform val5 = val4.AddComponent<RectTransform>();
			val5.sizeDelta = new Vector2(500f, 550f);
			val5.anchorMin = new Vector2(0.5f, 0.5f);
			val5.anchorMax = new Vector2(0.5f, 0.5f);
			val5.anchoredPosition = Vector2.zero;
			Image val6 = val4.AddComponent<Image>();
			((Graphic)val6).color = new Color(0.18f, 0.12f, 0.08f, 0.97f);
			CreateBorderFrame(val4.transform, new Vector2(500f, 550f));
			return val4;
		}

		private static void CreateBorderFrame(Transform parent, Vector2 size)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("OuterBorder");
			val.transform.SetParent(parent, false);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = new Color(0.6f, 0.45f, 0.2f);
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(size.x + 8f, size.y + 8f);
			component.anchoredPosition = Vector2.zero;
			val.transform.SetAsFirstSibling();
			GameObject val3 = new GameObject("InnerBorder");
			val3.transform.SetParent(parent, false);
			Image val4 = val3.AddComponent<Image>();
			((Graphic)val4).color = new Color(0.1f, 0.07f, 0.04f);
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(size.x + 4f, size.y + 4f);
			component2.anchoredPosition = Vector2.zero;
			val3.transform.SetSiblingIndex(1);
			GameObject val5 = new GameObject("TopBar");
			val5.transform.SetParent(parent, false);
			Image val6 = val5.AddComponent<Image>();
			((Graphic)val6).color = new Color(0.5f, 0.38f, 0.18f);
			RectTransform component3 = val5.GetComponent<RectTransform>();
			component3.sizeDelta = new Vector2(size.x - 40f, 4f);
			component3.anchorMin = new Vector2(0.5f, 1f);
			component3.anchorMax = new Vector2(0.5f, 1f);
			component3.anchoredPosition = new Vector2(0f, -25f);
			GameObject val7 = new GameObject("BottomBar");
			val7.transform.SetParent(parent, false);
			Image val8 = val7.AddComponent<Image>();
			((Graphic)val8).color = new Color(0.5f, 0.38f, 0.18f);
			RectTransform component4 = val7.GetComponent<RectTransform>();
			component4.sizeDelta = new Vector2(size.x - 40f, 4f);
			component4.anchorMin = new Vector2(0.5f, 0f);
			component4.anchorMax = new Vector2(0.5f, 0f);
			component4.anchoredPosition = new Vector2(0f, 25f);
		}

		private static void PopulateLeaderboardContent()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0472: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.Instance;
			Font font = ((instance != null) ? instance.AveriaSerifBold : null);
			Font font2 = ((instance != null) ? instance.AveriaSerif : null);
			Color color = (Color)(((??)instance?.ValheimOrange) ?? new Color(1f, 0.64f, 0.1f));
			CreateStyledText(_leaderboardUI.transform, "Reputation Leaderboard", new Vector2(0f, -40f), 28, color, font, (TextAnchor)4, outline: true);
			CreateStyledText(_leaderboardUI.transform, "Top 3 players gain +100% Stamina Regen & +500 Carry Weight", new Vector2(0f, -75f), 14, new Color(0.85f, 0.8f, 0.65f), font2, (TextAnchor)4, outline: true);
			CreateStyledText(_leaderboardUI.transform, "[F7] Toggle", new Vector2(0f, -95f), 12, new Color(0.6f, 0.55f, 0.4f), font2, (TextAnchor)4, outline: false);
			CreateStyledText(_leaderboardUI.transform, "Rank", new Vector2(-180f, -130f), 16, color, font, (TextAnchor)4, outline: true, bottomAnchor: false, 60f);
			CreateStyledText(_leaderboardUI.transform, "Player", new Vector2(-50f, -130f), 16, color, font, (TextAnchor)3, outline: true, bottomAnchor: false, 150f);
			CreateStyledText(_leaderboardUI.transform, "Reputation", new Vector2(140f, -130f), 16, color, font, (TextAnchor)4, outline: true, bottomAnchor: false, 100f);
			CreateDividerLine(_leaderboardUI.transform, new Vector2(0f, -150f), 420f);
			List<PlayerReputation> leaderboard = MessageManagerAlt.GetLeaderboard();
			float num = -175f;
			int num2 = 1;
			foreach (PlayerReputation item in leaderboard.Take(12))
			{
				bool flag = num2 <= 3;
				Color val = (Color)(flag ? GetRankColor(num2) : new Color(0.9f, 0.85f, 0.7f));
				if (flag)
				{
					CreateRowHighlight(_leaderboardUI.transform, new Vector2(0f, num), val);
				}
				string rankDisplay = GetRankDisplay(num2);
				CreateStyledText(_leaderboardUI.transform, rankDisplay, new Vector2(-180f, num), 16, val, font, (TextAnchor)4, outline: true, bottomAnchor: false, 60f);
				string text = item.PlayerName ?? "Unknown";
				if (string.IsNullOrEmpty(text) || string.IsNullOrWhiteSpace(text))
				{
					text = "Anonymous";
				}
				if (text.Length > 18)
				{
					text = text.Substring(0, 15) + "...";
				}
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Leaderboard display: rank={num2}, name='{text}', rep={item.TotalReputation}");
				}
				CreateStyledText(_leaderboardUI.transform, text, new Vector2(-50f, num), 15, val, font2, (TextAnchor)3, outline: true, bottomAnchor: false, 150f);
				CreateStyledText(_leaderboardUI.transform, item.TotalReputation.ToString(), new Vector2(140f, num), 16, val, font, (TextAnchor)4, outline: true, bottomAnchor: false, 100f);
				num -= 32f;
				num2++;
			}
			if (leaderboard.Count == 0)
			{
				CreateStyledText(_leaderboardUI.transform, "No reputation data yet!", new Vector2(0f, -220f), 18, new Color(0.75f, 0.7f, 0.55f), font, (TextAnchor)4, outline: true);
				CreateStyledText(_leaderboardUI.transform, "Place messages and earn votes to appear here.", new Vector2(0f, -255f), 14, new Color(0.6f, 0.55f, 0.45f), font2, (TextAnchor)4, outline: true);
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				long playerID = Player.m_localPlayer.GetPlayerID();
				if (MessageManagerAlt.IsPlayerInTop3(playerID))
				{
					CreateStyledText(_leaderboardUI.transform, "★ You are in the Top 3! Buffs Active ★", new Vector2(0f, 80f), 16, new Color(0.4f, 1f, 0.4f), font, (TextAnchor)4, outline: true, bottomAnchor: true);
				}
			}
			CreateCloseButton(_leaderboardUI.transform);
		}

		private static void CreateStyledText(Transform parent, string text, Vector2 position, int fontSize, Color color, Font font, TextAnchor alignment, bool outline, bool bottomAnchor = false, float width = 400f)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Text_" + text.Substring(0, Math.Min(10, text.Length)));
			val.transform.SetParent(parent, false);
			Text val2 = val.AddComponent<Text>();
			val2.text = text;
			val2.font = font ?? Resources.GetBuiltinResource<Font>("Arial.ttf");
			val2.fontSize = fontSize;
			((Graphic)val2).color = color;
			val2.alignment = alignment;
			val2.horizontalOverflow = (HorizontalWrapMode)1;
			val2.verticalOverflow = (VerticalWrapMode)1;
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(width, 30f);
			if (bottomAnchor)
			{
				component.anchorMin = new Vector2(0.5f, 0f);
				component.anchorMax = new Vector2(0.5f, 0f);
			}
			else
			{
				component.anchorMin = new Vector2(0.5f, 1f);
				component.anchorMax = new Vector2(0.5f, 1f);
			}
			component.anchoredPosition = position;
			if (outline)
			{
				Outline val3 = val.AddComponent<Outline>();
				((Shadow)val3).effectColor = Color.black;
				((Shadow)val3).effectDistance = new Vector2(1f, -1f);
			}
		}

		private static void CreateDividerLine(Transform parent, Vector2 position, float width)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Divider");
			val.transform.SetParent(parent, false);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = new Color(0.5f, 0.4f, 0.25f);
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(width, 2f);
			component.anchorMin = new Vector2(0.5f, 1f);
			component.anchorMax = new Vector2(0.5f, 1f);
			component.anchoredPosition = position;
		}

		private static void CreateRowHighlight(Transform parent, Vector2 position, Color baseColor)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("RowHighlight");
			val.transform.SetParent(parent, false);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = new Color(baseColor.r * 0.25f, baseColor.g * 0.25f, baseColor.b * 0.15f, 0.4f);
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(420f, 28f);
			component.anchorMin = new Vector2(0.5f, 1f);
			component.anchorMax = new Vector2(0.5f, 1f);
			component.anchoredPosition = position;
			val.transform.SetSiblingIndex(3);
		}

		private static void CreateCloseButton(Transform parent)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Expected O, but got Unknown
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			GUIManager instance = GUIManager.Instance;
			if (instance != null)
			{
				try
				{
					GameObject val = instance.CreateButton("Close", parent, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 45f), 140f, 45f);
					if ((Object)(object)val != (Object)null)
					{
						Button component = val.GetComponent<Button>();
						if (component != null)
						{
							ButtonClickedEvent onClick = component.onClick;
							object obj = <>O.<0>__CloseLeaderboard;
							if (obj == null)
							{
								UnityAction val2 = CloseLeaderboard;
								<>O.<0>__CloseLeaderboard = val2;
								obj = (object)val2;
							}
							((UnityEvent)onClick).AddListener((UnityAction)obj);
						}
						return;
					}
				}
				catch
				{
				}
			}
			GameObject val3 = new GameObject("CloseButton");
			val3.transform.SetParent(parent, false);
			Image val4 = val3.AddComponent<Image>();
			((Graphic)val4).color = new Color(0.35f, 0.25f, 0.15f);
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(140f, 45f);
			component2.anchorMin = new Vector2(0.5f, 0f);
			component2.anchorMax = new Vector2(0.5f, 0f);
			component2.anchoredPosition = new Vector2(0f, 45f);
			Button val5 = val3.AddComponent<Button>();
			((Selectable)val5).targetGraphic = (Graphic)(object)val4;
			ColorBlock colors = ((Selectable)val5).colors;
			((ColorBlock)(ref colors)).normalColor = new Color(0.35f, 0.25f, 0.15f);
			((ColorBlock)(ref colors)).highlightedColor = new Color(0.45f, 0.35f, 0.2f);
			((ColorBlock)(ref colors)).pressedColor = new Color(0.25f, 0.18f, 0.1f);
			((Selectable)val5).colors = colors;
			ButtonClickedEvent onClick2 = val5.onClick;
			object obj3 = <>O.<0>__CloseLeaderboard;
			if (obj3 == null)
			{
				UnityAction val6 = CloseLeaderboard;
				<>O.<0>__CloseLeaderboard = val6;
				obj3 = (object)val6;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj3);
			GameObject val7 = new GameObject("Border");
			val7.transform.SetParent(val3.transform, false);
			Image val8 = val7.AddComponent<Image>();
			((Graphic)val8).color = new Color(0.55f, 0.42f, 0.22f);
			RectTransform component3 = val7.GetComponent<RectTransform>();
			component3.sizeDelta = new Vector2(144f, 49f);
			component3.anchoredPosition = Vector2.zero;
			val7.transform.SetAsFirstSibling();
			GameObject val9 = new GameObject("Text");
			val9.transform.SetParent(val3.transform, false);
			Text val10 = val9.AddComponent<Text>();
			val10.text = "Close";
			val10.font = ((instance != null) ? instance.AveriaSerifBold : null) ?? Resources.GetBuiltinResource<Font>("Arial.ttf");
			val10.fontSize = 18;
			((Graphic)val10).color = new Color(1f, 0.9f, 0.7f);
			val10.alignment = (TextAnchor)4;
			RectTransform component4 = val9.GetComponent<RectTransform>();
			component4.sizeDelta = new Vector2(140f, 45f);
			component4.anchoredPosition = Vector2.zero;
			Outline val11 = val9.AddComponent<Outline>();
			((Shadow)val11).effectColor = Color.black;
			((Shadow)val11).effectDistance = new Vector2(1f, -1f);
		}

		private static string GetRankDisplay(int rank)
		{
			return rank switch
			{
				1 => "1st", 
				2 => "2nd", 
				3 => "3rd", 
				_ => rank.ToString(), 
			};
		}

		private static Color GetRankColor(int rank)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(rank switch
			{
				1 => new Color(1f, 0.84f, 0f), 
				2 => new Color(0.78f, 0.78f, 0.8f), 
				3 => new Color(0.85f, 0.55f, 0.25f), 
				_ => Color.white, 
			});
		}

		public static void CheckAndApplyBuffs()
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				long playerID = Player.m_localPlayer.GetPlayerID();
				bool flag = MessageManagerAlt.IsPlayerInTop3(playerID);
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"CheckAndApplyBuffs: localId={playerID}, shouldHave={flag}, hasCarry={_hasCarryBuff}");
				}
				if (flag && !_hasCarryBuff)
				{
					ApplyBuffs();
				}
				else if (!flag && _hasCarryBuff)
				{
					RemoveBuffs();
				}
			}
		}

		private static void ApplyBuffs()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			_hasCarryBuff = true;
			_hasStealthBuff = true;
			try
			{
				SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan();
				if (sEMan != null)
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode("SE_ReputationTop3");
					StatusEffect statusEffect = sEMan.GetStatusEffect(stableHashCode);
					if ((Object)(object)statusEffect != (Object)null)
					{
						sEMan.RemoveStatusEffect(statusEffect, false);
					}
					SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>();
					((Object)val).name = "SE_ReputationTop3";
					((StatusEffect)val).m_name = "Reputation Champion";
					((StatusEffect)val).m_tooltip = "Top 3 Reputation Bonus:\n• +500 Carry Weight\n• +100% Stamina Regeneration";
					try
					{
						string[] array = new string[5] { "Thunderstone", "DragonTear", "SurtlingCore", "Coins", "Ruby" };
						string[] array2 = array;
						foreach (string text in array2)
						{
							ObjectDB instance = ObjectDB.instance;
							GameObject val2 = ((instance != null) ? instance.GetItemPrefab(text) : null);
							if (!((Object)(object)val2 != (Object)null))
							{
								continue;
							}
							ItemDrop component = val2.GetComponent<ItemDrop>();
							if ((Object)(object)component != (Object)null && component.m_itemData?.m_shared?.m_icons != null && component.m_itemData.m_shared.m_icons.Length != 0)
							{
								((StatusEffect)val).m_icon = component.m_itemData.m_shared.m_icons[0];
								ManualLogSource log = VikingMessagesPlugin.Log;
								if (log != null)
								{
									log.LogInfo((object)("Using icon from " + text));
								}
								break;
							}
						}
						if ((Object)(object)((StatusEffect)val).m_icon == (Object)null)
						{
							ObjectDB instance2 = ObjectDB.instance;
							StatusEffect val3 = ((instance2 != null) ? instance2.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested")) : null);
							if ((Object)(object)val3 != (Object)null && (Object)(object)val3.m_icon != (Object)null)
							{
								((StatusEffect)val).m_icon = val3.m_icon;
							}
						}
					}
					catch
					{
					}
					val.m_addMaxCarryWeight = 500f;
					val.m_staminaRegenMultiplier = 2f;
					((StatusEffect)val).m_ttl = 0f;
					sEMan.AddStatusEffect((StatusEffect)(object)val, false, 0, 0f);
					_reputationBuff = val;
					ManualLogSource log2 = VikingMessagesPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"Top 3 buffs applied via StatusEffect (hash={stableHashCode}): +500 carry, +100% stamina regen");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = VikingMessagesPlugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("Failed to apply StatusEffect buff: " + ex.Message));
				}
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, "<color=yellow>Top 3 Reputation Bonus Active!</color>\n+500 Carry Weight & +100% Stamina Regen", 0, (Sprite)null);
			}
		}

		private static void RemoveBuffs()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan();
				if (sEMan != null)
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode("SE_ReputationTop3");
					StatusEffect statusEffect = sEMan.GetStatusEffect(stableHashCode);
					if ((Object)(object)statusEffect != (Object)null)
					{
						sEMan.RemoveStatusEffect(statusEffect, false);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Failed to remove buff: " + ex.Message));
				}
			}
			_hasCarryBuff = false;
			_hasStealthBuff = false;
			_reputationBuff = null;
			ManualLogSource log2 = VikingMessagesPlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"Top 3 buffs removed");
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, "<color=#888888>Reputation Bonus Removed</color>", 0, (Sprite)null);
			}
		}

		public static bool HasStealthBuff()
		{
			return _hasStealthBuff;
		}

		public static float GetCarryWeightBonus()
		{
			return _hasCarryBuff ? 500f : 0f;
		}

		public static void Update()
		{
			if (_isVisible && Input.GetKeyDown((KeyCode)27))
			{
				CloseLeaderboard();
			}
			else if (Input.GetKeyDown((KeyCode)288))
			{
				if (_isVisible)
				{
					CloseLeaderboard();
				}
				else if ((Object)(object)Player.m_localPlayer != (Object)null && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Console.IsVisible())
				{
					ShowLeaderboard();
				}
			}
		}
	}
	[HarmonyPatch]
	public static class LeaderboardPatches
	{
	}
	public class MessageGlyphItem : MonoBehaviour, Hoverable
	{
		private ItemDrop _itemDrop;

		private void Awake()
		{
			_itemDrop = ((Component)this).GetComponent<ItemDrop>();
		}

		public string GetHoverText()
		{
			return "Message Glyph\n[<color=yellow><b>E</b></color>] Place Message";
		}

		public string GetHoverName()
		{
			return "Message Glyph";
		}
	}
	public class MessagePlacementHandler : MonoBehaviour
	{
		private static MessagePlacementHandler _instance;

		private bool _isPlacing;

		private float _placementTimer;

		private const float PlacementDuration = 2f;

		private Vector3 _placementPosition;

		private Quaternion _placementRotation;

		public static MessagePlacementHandler Instance
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)_instance == (Object)null)
				{
					GameObject val = new GameObject("MessagePlacementHandler");
					_instance = val.AddComponent<MessagePlacementHandler>();
					Object.DontDestroyOnLoad((Object)(object)val);
				}
				return _instance;
			}
		}

		public bool IsPlacing => _isPlacing;

		private void Update()
		{
			if (_isPlacing)
			{
				_placementTimer -= Time.deltaTime;
				if (_placementTimer <= 0f)
				{
					FinishPlacement();
				}
				if ((Object)(object)Player.m_localPlayer != (Object)null && !((Character)Player.m_localPlayer).IsEncumbered() && !((Character)Player.m_localPlayer).InAttack() && !(((Character)Player.m_localPlayer).GetHealth() < ((Character)Player.m_localPlayer).GetMaxHealth() * 0.9f))
				{
				}
			}
		}

		public void StartPlacement(Player player)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if (!_isPlacing)
			{
				_isPlacing = true;
				_placementTimer = 2f;
				_placementPosition = ((Component)player).transform.position + ((Component)player).transform.forward * 1.5f;
				_placementRotation = Quaternion.Euler(0f, ((Component)player).transform.eulerAngles.y, 0f);
				RaycastHit val = default(RaycastHit);
				if (Physics.Raycast(_placementPosition + Vector3.up * 5f, Vector3.down, ref val, 10f, LayerMask.GetMask(new string[3] { "Default", "static_solid", "terrain" })))
				{
					_placementPosition = ((RaycastHit)(ref val)).point;
				}
				player.StartEmote("kneel", true);
				((Character)player).Message((MessageType)2, "Placing message...", 0, (Sprite)null);
				VikingMessagesPlugin.Log.LogInfo((object)"Started message placement");
			}
		}

		private void FinishPlacement()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			_isPlacing = false;
			MessageUIManager.UI.ShowCreateUI(_placementPosition, _placementRotation);
			VikingMessagesPlugin.Log.LogInfo((object)"Finished placement, opening UI");
		}

		public void CancelPlacement()
		{
			if (_isPlacing)
			{
				_isPlacing = false;
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)1, "Placement cancelled", 0, (Sprite)null);
				}
			}
		}
	}
	[HarmonyPatch]
	public static class MessageGlyphPatches
	{
		[HarmonyPatch(typeof(Player), "ConsumeItem")]
		[HarmonyPrefix]
		public static bool ConsumeItem_Prefix(Player __instance, ItemData item, ref bool __result)
		{
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = item.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			if ((string?)obj != "MessageGlyph")
			{
				return true;
			}
			if (!CanPlaceMessage(__instance))
			{
				((Character)__instance).Message((MessageType)2, "Cannot place message here!", 0, (Sprite)null);
				__result = false;
				return false;
			}
			MessagePlacementHandler.Instance.StartPlacement(__instance);
			((Humanoid)__instance).GetInventory().RemoveItem(item, 1);
			__result = true;
			return false;
		}

		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		[HarmonyPrefix]
		public static bool UseItem_Prefix(Humanoid __instance, ItemData item)
		{
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = item.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			if ((string?)obj != "MessageGlyph")
			{
				return true;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null)
			{
				((Humanoid)val).ConsumeItem(((Humanoid)val).GetInventory(), item, false);
				return false;
			}
			return true;
		}

		private static bool CanPlaceMessage(Player player)
		{
			if (((Character)player).InInterior())
			{
				return false;
			}
			if (((Character)player).IsSwimming())
			{
				return false;
			}
			if (((Character)player).IsAttached())
			{
				return false;
			}
			if (((Character)player).IsDead())
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		[HarmonyPostfix]
		public static void Character_Damage_Postfix(Character __instance, HitData hit)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && MessagePlacementHandler.Instance.IsPlacing)
			{
				MessagePlacementHandler.Instance.CancelPlacement();
			}
		}
	}
	public static class MessageManagerAlt
	{
		private static Dictionary<string, VikingMessage> _messages = new Dictionary<string, VikingMessage>();

		private static Dictionary<long, PlayerReputation> _playerReputations = new Dictionary<long, PlayerReputation>();

		private static string _saveFilePath;

		private static string _leaderboardFilePath;

		private static string _currentWorldName;

		public const string RPC_PlaceMessage = "VikingMessages_PlaceMessage";

		public const string RPC_VoteMessage = "VikingMessages_VoteMessage";

		public const string RPC_RequestSync = "VikingMessages_RequestSync";

		public const string RPC_SyncMessages = "VikingMessages_SyncMessages";

		public const string RPC_RemoveMessage = "VikingMessages_RemoveMessage";

		public const string RPC_SyncTemplates = "VikingMessages_SyncTemplates";

		public const string RPC_SyncLeaderboard = "VikingMessages_SyncLeaderboard";

		public const string RPC_NotifyAppraise = "VikingMessages_NotifyAppraise";

		private static bool _rpcsRegistered = false;

		public static void Initialize()
		{
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"MessageManagerAlt initialized");
			}
		}

		public static void RegisterRPCs()
		{
			if (_rpcsRegistered || ZRoutedRpc.instance == null)
			{
				return;
			}
			try
			{
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_PlaceMessage", (Action<long, ZPackage>)RPC_OnPlaceMessage);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_VoteMessage", (Action<long, ZPackage>)RPC_OnVoteMessage);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_RequestSync", (Action<long, ZPackage>)RPC_OnRequestSync);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_SyncMessages", (Action<long, ZPackage>)RPC_OnSyncMessages);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_RemoveMessage", (Action<long, ZPackage>)RPC_OnRemoveMessage);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_SyncTemplates", (Action<long, ZPackage>)RPC_OnSyncTemplates);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_SyncLeaderboard", (Action<long, ZPackage>)RPC_OnSyncLeaderboard);
				ZRoutedRpc.instance.Register<ZPackage>("VikingMessages_NotifyAppraise", (Action<long, ZPackage>)RPC_OnNotifyAppraise);
				_rpcsRegistered = true;
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"RPCs registered successfully");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Failed to register RPCs: {arg}");
				}
			}
		}

		private static void RPC_OnPlaceMessage(long sender, ZPackage pkg)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = pkg.ReadString();
				Vector3 position = pkg.ReadVector3();
				Quaternion rotation = pkg.ReadQuaternion();
				string template = pkg.ReadString();
				string words = pkg.ReadString();
				int num = pkg.ReadInt();
				string text2 = pkg.ReadString();
				Vector3 lookDirection = pkg.ReadVector3();
				int num2 = pkg.ReadInt();
				string[] array = new string[num2];
				for (int i = 0; i < num2; i++)
				{
					array[i] = pkg.ReadString();
				}
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"RPC_OnPlaceMessage: id={text}, author={text2}, emote={num}");
				}
				VikingMessage value = new VikingMessage
				{
					Id = text,
					Position = position,
					Rotation = rotation,
					Template = template,
					Words = words,
					EmoteIndex = num,
					AuthorId = sender,
					AuthorName = text2,
					Reputation = 0,
					CreatedTime = DateTime.UtcNow,
					VotedPlayers = new List<long>(),
					EquippedItems = array,
					LookDirection = lookDirection
				};
				_messages[text] = value;
				UpdatePlayerMessageCount(sender, text2);
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					SaveMessages();
					SaveLeaderboard();
				}
				BroadcastMessageSync();
				BroadcastLeaderboard();
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Error processing PlaceMessage: {arg}");
				}
			}
		}

		private static void RPC_OnVoteMessage(long sender, ZPackage pkg)
		{
			try
			{
				string text = pkg.ReadString();
				bool flag = pkg.ReadBool();
				if (!_messages.TryGetValue(text, out var value) || value.VotedPlayers.Contains(sender) || value.AuthorId == sender)
				{
					return;
				}
				value.VotedPlayers.Add(sender);
				value.Reputation += (flag ? 1 : (-1));
				UpdatePlayerReputation(value.AuthorId, value.AuthorName, flag ? 1 : (-1));
				if (flag && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					NotifyAuthorOfAppraise(value.AuthorId);
				}
				if (value.Reputation <= VikingMessagesPlugin.MinReputation.Value)
				{
					_messages.Remove(text);
					ManualLogSource log = VikingMessagesPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("Message " + text + " removed due to low reputation"));
					}
				}
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					SaveMessages();
					SaveLeaderboard();
				}
				BroadcastMessageSync();
				BroadcastLeaderboard();
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Error processing VoteMessage: {arg}");
				}
			}
		}

		private static void NotifyAuthorOfAppraise(long authorId)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			try
			{
				ZPackage val = new ZPackage();
				val.Write("appraise");
				List<ZNetPeer> peers = ZNet.instance.GetPeers();
				foreach (ZNetPeer item in peers)
				{
					if (((ZDOID)(ref item.m_characterID)).UserID == authorId)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(item.m_uid, "VikingMessages_NotifyAppraise", new object[1] { val });
						ManualLogSource log = VikingMessagesPlugin.Log;
						if (log != null)
						{
							log.LogInfo((object)$"Sent appraise notification to {authorId}");
						}
						break;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Failed to notify author: " + ex.Message));
				}
			}
		}

		private static void RPC_OnNotifyAppraise(long sender, ZPackage pkg)
		{
			try
			{
				string text = pkg.ReadString();
				if (text == "appraise")
				{
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						((Character)localPlayer).Message((MessageType)2, "<color=#FFD700>Your message was appraised!</color>", 0, (Sprite)null);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Error processing notification: " + ex.Message));
				}
			}
		}

		private static void RPC_OnRequestSync(long sender, ZPackage pkg)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Sync requested by {sender}");
				}
				SendMessagesToClient(sender);
				SendTemplatesToClient(sender);
				SendLeaderboardToClient(sender);
			}
		}

		private static void RPC_OnSyncMessages(long sender, ZPackage pkg)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				return;
			}
			try
			{
				int num = pkg.ReadInt();
				Dictionary<string, VikingMessage> dictionary = new Dictionary<string, VikingMessage>();
				for (int i = 0; i < num; i++)
				{
					VikingMessage vikingMessage = new VikingMessage
					{
						Id = pkg.ReadString(),
						Position = pkg.ReadVector3(),
						Rotation = pkg.ReadQuaternion(),
						Template = pkg.ReadString(),
						Words = pkg.ReadString(),
						EmoteIndex = pkg.ReadInt(),
						AuthorId = pkg.ReadLong(),
						AuthorName = pkg.ReadString(),
						Reputation = pkg.ReadInt(),
						LookDirection = pkg.ReadVector3()
					};
					int num2 = pkg.ReadInt();
					vikingMessage.EquippedItems = new string[num2];
					for (int j = 0; j < num2; j++)
					{
						vikingMessage.EquippedItems[j] = pkg.ReadString();
					}
					int num3 = pkg.ReadInt();
					vikingMessage.VotedPlayers = new List<long>();
					for (int k = 0; k < num3; k++)
					{
						vikingMessage.VotedPlayers.Add(pkg.ReadLong());
					}
					dictionary[vikingMessage.Id] = vikingMessage;
				}
				_messages = dictionary;
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Synced {num} messages from server");
				}
				RefreshAllMessageStones();
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Error processing SyncMessages: {arg}");
				}
			}
		}

		private static void RPC_OnRemoveMessage(long sender, ZPackage pkg)
		{
			try
			{
				string key = pkg.ReadString();
				if (_messages.ContainsKey(key))
				{
					_messages.Remove(key);
					if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
					{
						SaveMessages();
					}
					BroadcastMessageSync();
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogError((object)$"Error processing RemoveMessage: {arg}");
				}
			}
		}

		private static void RPC_OnSyncTemplates(long sender, ZPackage pkg)
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				return;
			}
			try
			{
				string json = pkg.ReadString();
				MessageTemplates.LoadFromServerJson(json);
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Templates synced from server");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Error processing SyncTemplates: {arg}");
				}
			}
		}

		private static void RPC_OnSyncLeaderboard(long sender, ZPackage pkg)
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				return;
			}
			try
			{
				int num = pkg.ReadInt();
				_playerReputations.Clear();
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"RPC_OnSyncLeaderboard: Receiving {num} players");
				}
				for (int i = 0; i < num; i++)
				{
					PlayerReputation playerReputation = new PlayerReputation
					{
						PlayerId = pkg.ReadLong(),
						PlayerName = pkg.ReadString(),
						TotalReputation = pkg.ReadInt(),
						MessageCount = pkg.ReadInt()
					};
					_playerReputations[playerReputation.PlayerId] = playerReputation;
					ManualLogSource log2 = VikingMessagesPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"  Player {i}: id={playerReputation.PlayerId}, name='{playerReputation.PlayerName}', rep={playerReputation.TotalReputation}");
					}
				}
				ManualLogSource log3 = VikingMessagesPlugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)$"Synced leaderboard: {num} players");
				}
				LeaderboardManager.CheckAndApplyBuffs();
			}
			catch (Exception arg)
			{
				ManualLogSource log4 = VikingMessagesPlugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)$"Error processing SyncLeaderboard: {arg}");
				}
			}
		}

		public static void PlaceMessage(Vector3 position, Quaternion rotation, string template, string words, int emoteIndex)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				string text = Guid.NewGuid().ToString();
				string playerName = Player.m_localPlayer.GetPlayerName();
				Vector3 forward = ((Component)Player.m_localPlayer).transform.forward;
				string[] array = CapturePlayerEquipment();
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"PlaceMessage: id={text}, author='{playerName}', emote={emoteIndex}");
				}
				ZPackage val = new ZPackage();
				val.Write(text);
				val.Write(position);
				val.Write(rotation);
				val.Write(template);
				val.Write(words);
				val.Write(emoteIndex);
				val.Write(playerName ?? "Unknown");
				val.Write(forward);
				val.Write(array.Length);
				string[] array2 = array;
				foreach (string text2 in array2)
				{
					val.Write(text2 ?? "");
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VikingMessages_PlaceMessage", new object[1] { val });
			}
		}

		private static string[] CapturePlayerEquipment()
		{
			List<string> list = new List<string>();
			try
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					return list.ToArray();
				}
				VisEquipment component = ((Component)Player.m_localPlayer).GetComponent<VisEquipment>();
				if ((Object)(object)component == (Object)null)
				{
					return list.ToArray();
				}
				Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
				if (inventory == null)
				{
					return list.ToArray();
				}
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem.m_equipped && (Object)(object)allItem.m_dropPrefab != (Object)null)
					{
						list.Add(((Object)allItem.m_dropPrefab).name);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Failed to capture equipment: " + ex.Message));
				}
			}
			return list.ToArray();
		}

		public static bool VoteMessage(string messageId, bool isLike)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			if (!_messages.TryGetValue(messageId, out var value))
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "Message not found!", 0, (Sprite)null);
				}
				return false;
			}
			Player localPlayer2 = Player.m_localPlayer;
			long num = ((localPlayer2 != null) ? localPlayer2.GetPlayerID() : 0);
			Player localPlayer3 = Player.m_localPlayer;
			string value2 = ((localPlayer3 != null) ? localPlayer3.GetPlayerName() : null) ?? "";
			if (value.AuthorId == num || (!string.IsNullOrEmpty(value2) && !string.IsNullOrEmpty(value.AuthorName) && value.AuthorName.Equals(value2, StringComparison.OrdinalIgnoreCase)))
			{
				Player localPlayer4 = Player.m_localPlayer;
				if (localPlayer4 != null)
				{
					((Character)localPlayer4).Message((MessageType)2, "You cannot appraise your own message!", 0, (Sprite)null);
				}
				return false;
			}
			if (value.VotedPlayers.Contains(num))
			{
				Player localPlayer5 = Player.m_localPlayer;
				if (localPlayer5 != null)
				{
					((Character)localPlayer5).Message((MessageType)2, "You have already rated this message!", 0, (Sprite)null);
				}
				return false;
			}
			ZPackage val = new ZPackage();
			val.Write(messageId);
			val.Write(isLike);
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VikingMessages_VoteMessage", new object[1] { val });
			return true;
		}

		public static void RequestMessages()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if (ZRoutedRpc.instance != null)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Requesting sync from server");
				}
				ZPackage val = new ZPackage();
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VikingMessages_RequestSync", new object[1] { val });
			}
		}

		public static VikingMessage GetMessage(string messageId)
		{
			VikingMessage value;
			return _messages.TryGetValue(messageId, out value) ? value : null;
		}

		public static IEnumerable<VikingMessage> GetAllMessages()
		{
			return _messages.Values;
		}

		public static int GetMessageCount()
		{
			return _messages.Count;
		}

		private static void UpdatePlayerMessageCount(long playerId, string playerName)
		{
			if (!_playerReputations.TryGetValue(playerId, out var value))
			{
				value = new PlayerReputation(playerId, playerName);
				_playerReputations[playerId] = value;
			}
			value.MessageCount++;
			value.PlayerName = playerName;
		}

		private static void UpdatePlayerReputation(long playerId, string playerName, int delta)
		{
			if (!_playerReputations.TryGetValue(playerId, out var value))
			{
				value = new PlayerReputation(playerId, playerName);
				_playerReputations[playerId] = value;
			}
			value.TotalReputation += delta;
			value.PlayerName = playerName;
		}

		public static List<PlayerReputation> GetLeaderboard()
		{
			Dictionary<string, PlayerReputation> dictionary = new Dictionary<string, PlayerReputation>();
			foreach (PlayerReputation value2 in _playerReputations.Values)
			{
				string key = (string.IsNullOrEmpty(value2.PlayerName) ? $"id_{value2.PlayerId}" : value2.PlayerName.ToLower());
				if (dictionary.TryGetValue(key, out var value))
				{
					value.TotalReputation += value2.TotalReputation;
					value.MessageCount += value2.MessageCount;
					if (string.IsNullOrEmpty(value.PlayerName) && !string.IsNullOrEmpty(value2.PlayerName))
					{
						value.PlayerName = value2.PlayerName;
					}
				}
				else
				{
					dictionary[key] = new PlayerReputation
					{
						PlayerId = value2.PlayerId,
						PlayerName = value2.PlayerName,
						TotalReputation = value2.TotalReputation,
						MessageCount = value2.MessageCount
					};
				}
			}
			return dictionary.Values.OrderByDescending((PlayerReputation p) => p.TotalReputation).ToList();
		}

		public static bool IsPlayerInTop3(long playerId)
		{
			Player localPlayer = Player.m_localPlayer;
			string localPlayerName = ((localPlayer != null) ? localPlayer.GetPlayerName() : null) ?? "";
			List<PlayerReputation> list = GetLeaderboard().Take(3).ToList();
			bool flag = list.Any((PlayerReputation p) => p.PlayerId == playerId || (!string.IsNullOrEmpty(localPlayerName) && !string.IsNullOrEmpty(p.PlayerName) && p.PlayerName.Equals(localPlayerName, StringComparison.OrdinalIgnoreCase)));
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"IsPlayerInTop3: playerId={playerId}, name={localPlayerName}, top3Count={list.Count}, result={flag}");
			}
			if (list.Count > 0)
			{
				foreach (PlayerReputation item in list)
				{
					ManualLogSource log2 = VikingMessagesPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"  Top3 player: id={item.PlayerId}, name='{item.PlayerName}', rep={item.TotalReputation}");
					}
				}
			}
			return flag;
		}

		private static void SendMessagesToClient(long clientId)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(_messages.Count);
			foreach (VikingMessage value in _messages.Values)
			{
				val.Write(value.Id);
				val.Write(value.Position);
				val.Write(value.Rotation);
				val.Write(value.Template ?? "");
				val.Write(value.Words ?? "");
				val.Write(value.EmoteIndex);
				val.Write(value.AuthorId);
				val.Write(value.AuthorName ?? "Unknown");
				val.Write(value.Reputation);
				val.Write(value.LookDirection);
				string[] array = value.EquippedItems ?? new string[0];
				val.Write(array.Length);
				string[] array2 = array;
				foreach (string text in array2)
				{
					val.Write(text ?? "");
				}
				val.Write(value.VotedPlayers?.Count ?? 0);
				if (value.VotedPlayers == null)
				{
					continue;
				}
				foreach (long votedPlayer in value.VotedPlayers)
				{
					val.Write(votedPlayer);
				}
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(clientId, "VikingMessages_SyncMessages", new object[1] { val });
		}

		private static void BroadcastMessageSync()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(_messages.Count);
			foreach (VikingMessage value in _messages.Values)
			{
				val.Write(value.Id);
				val.Write(value.Position);
				val.Write(value.Rotation);
				val.Write(value.Template ?? "");
				val.Write(value.Words ?? "");
				val.Write(value.EmoteIndex);
				val.Write(value.AuthorId);
				val.Write(value.AuthorName ?? "Unknown");
				val.Write(value.Reputation);
				val.Write(value.LookDirection);
				string[] array = value.EquippedItems ?? new string[0];
				val.Write(array.Length);
				string[] array2 = array;
				foreach (string text in array2)
				{
					val.Write(text ?? "");
				}
				val.Write(value.VotedPlayers?.Count ?? 0);
				if (value.VotedPlayers == null)
				{
					continue;
				}
				foreach (long votedPlayer in value.VotedPlayers)
				{
					val.Write(votedPlayer);
				}
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VikingMessages_SyncMessages", new object[1] { val });
		}

		private static void SendTemplatesToClient(long clientId)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			string serverTemplatesJson = MessageTemplates.GetServerTemplatesJson();
			ZPackage val = new ZPackage();
			val.Write(serverTemplatesJson);
			ZRoutedRpc.instance.InvokeRoutedRPC(clientId, "VikingMessages_SyncTemplates", new object[1] { val });
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Sent templates to client {clientId}");
			}
		}

		private static void SendLeaderboardToClient(long clientId)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			List<PlayerReputation> list = _playerReputations.Values.ToList();
			val.Write(list.Count);
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"SendLeaderboardToClient: Sending {list.Count} players to {clientId}");
			}
			foreach (PlayerReputation item in list)
			{
				val.Write(item.PlayerId);
				val.Write(item.PlayerName ?? "Unknown");
				val.Write(item.TotalReputation);
				val.Write(item.MessageCount);
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"  Sending player: id={item.PlayerId}, name='{item.PlayerName}', rep={item.TotalReputation}");
				}
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(clientId, "VikingMessages_SyncLeaderboard", new object[1] { val });
		}

		private static void BroadcastLeaderboard()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			List<PlayerReputation> list = _playerReputations.Values.ToList();
			val.Write(list.Count);
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"BroadcastLeaderboard: Broadcasting {list.Count} players");
			}
			foreach (PlayerReputation item in list)
			{
				val.Write(item.PlayerId);
				val.Write(item.PlayerName ?? "Unknown");
				val.Write(item.TotalReputation);
				val.Write(item.MessageCount);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VikingMessages_SyncLeaderboard", new object[1] { val });
		}

		public static void SpawnMessageStone(VikingMessage msg)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)VikingMessagesPlugin.MessageStonePrefab == (Object)null))
			{
				GameObject val = Object.Instantiate<GameObject>(VikingMessagesPlugin.MessageStonePrefab, msg.Position, msg.Rotation);
				val.SetActive(true);
				MessageStone component = val.GetComponent<MessageStone>();
				if ((Object)(object)component != (Object)null)
				{
					component.Initialize(msg);
				}
			}
		}

		private static void RefreshAllMessageStones()
		{
			MessageStone[] array = Object.FindObjectsOfType<MessageStone>();
			MessageStone[] array2 = array;
			foreach (MessageStone messageStone in array2)
			{
				Object.Destroy((Object)(object)((Component)messageStone).gameObject);
			}
			foreach (VikingMessage value in _messages.Values)
			{
				SpawnMessageStone(value);
			}
			ManualLogSource log = VikingMessagesPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Refreshed {_messages.Count} message stones");
			}
		}

		private static void SetupSavePath(string worldName)
		{
			if (string.IsNullOrEmpty(worldName))
			{
				worldName = "Unknown";
			}
			_currentWorldName = worldName;
			string text = Path.Combine(Paths.ConfigPath, "VikingMessages");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			string text2 = string.Join("_", worldName.Split(Path.GetInvalidFileNameChars()));
			_saveFilePath = Path.Combine(text, "messages_" + text2 + ".json");
			_leaderboardFilePath = Path.Combine(text, "leaderboard_" + text2 + ".json");
		}

		public static void SaveMessages()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			if (string.IsNullOrEmpty(_saveFilePath))
			{
				SetupSavePath(ZNet.instance.GetWorldName());
			}
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("{");
				stringBuilder.AppendLine("  \"Messages\": [");
				List<VikingMessage> list = _messages.Values.ToList();
				for (int i = 0; i < list.Count; i++)
				{
					VikingMessage vikingMessage = list[i];
					stringBuilder.AppendLine("    {");
					stringBuilder.AppendLine("      \"Id\": \"" + Escape(vikingMessage.Id) + "\",");
					stringBuilder.AppendLine("      \"PosX\": " + F(vikingMessage.Position.x) + ", \"PosY\": " + F(vikingMessage.Position.y) + ", \"PosZ\": " + F(vikingMessage.Position.z) + ",");
					stringBuilder.AppendLine("      \"RotX\": " + F(vikingMessage.Rotation.x) + ", \"RotY\": " + F(vikingMessage.Rotation.y) + ", \"RotZ\": " + F(vikingMessage.Rotation.z) + ", \"RotW\": " + F(vikingMessage.Rotation.w) + ",");
					stringBuilder.AppendLine("      \"Template\": \"" + Escape(vikingMessage.Template) + "\",");
					stringBuilder.AppendLine("      \"Words\": \"" + Escape(vikingMessage.Words) + "\",");
					stringBuilder.AppendLine($"      \"EmoteIndex\": {vikingMessage.EmoteIndex},");
					stringBuilder.AppendLine($"      \"AuthorId\": {vikingMessage.AuthorId},");
					stringBuilder.AppendLine("      \"AuthorName\": \"" + Escape(vikingMessage.AuthorName) + "\",");
					stringBuilder.AppendLine($"      \"Reputation\": {vikingMessage.Reputation},");
					stringBuilder.AppendLine("      \"LookDirX\": " + F(vikingMessage.LookDirection.x) + ", \"LookDirY\": " + F(vikingMessage.LookDirection.y) + ", \"LookDirZ\": " + F(vikingMessage.LookDirection.z) + ",");
					stringBuilder.Append("      \"Equipment\": [");
					if (vikingMessage.EquippedItems != null && vikingMessage.EquippedItems.Length != 0)
					{
						stringBuilder.Append(string.Join(", ", vikingMessage.EquippedItems.Select((string e) => "\"" + Escape(e) + "\"")));
					}
					stringBuilder.AppendLine("],");
					stringBuilder.Append("      \"VotedPlayers\": [");
					if (vikingMessage.VotedPlayers != null && vikingMessage.VotedPlayers.Count > 0)
					{
						stringBuilder.Append(string.Join(", ", vikingMessage.VotedPlayers));
					}
					stringBuilder.AppendLine("]");
					stringBuilder.AppendLine((i < list.Count - 1) ? "    }," : "    }");
				}
				stringBuilder.AppendLine("  ]");
				stringBuilder.AppendLine("}");
				File.WriteAllText(_saveFilePath, stringBuilder.ToString());
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Saved {_messages.Count} messages");
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = VikingMessagesPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Failed to save messages: {arg}");
				}
			}
		}

		public static void SaveLeaderboard()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			if (string.IsNullOrEmpty(_leaderboardFilePath))
			{
				SetupSavePath(ZNet.instance.GetWorldName());
			}
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("{");
				stringBuilder.AppendLine("  \"Players\": [");
				List<PlayerReputation> list = _playerReputations.Values.ToList();
				for (int i = 0; i < list.Count; i++)
				{
					PlayerReputation playerReputation = list[i];
					stringBuilder.AppendLine("    {");
					stringBuilder.AppendLine($"      \"PlayerId\": {playerReputation.PlayerId},");
					stringBuilder.AppendLine("      \"PlayerName\": \"" + Escape(playerReputation.PlayerName) + "\",");
					stringBuilder.AppendLine($"      \"TotalReputation\": {playerReputation.TotalReputation},");
					stringBuilder.AppendLine($"      \"MessageCount\": {playerReputation.MessageCount}");
					stringBuilder.AppendLine((i < list.Count - 1) ? "    }," : "    }");
				}
				stringBuilder.AppendLine("  ]");
				stringBuilder.AppendLine("}");
				File.WriteAllText(_leaderboardFilePath, stringBuilder.ToString());
			}
			catch (Exception arg)
			{
				ManualLogSource log = VikingMessagesPlugin.Log;
				if (log != null)
				{
					log.LogError((object)$"Failed to save leaderboard: {arg}");
				}
			}
		}

		public static void LoadMessages()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			SetupSavePath(ZNet.instance.GetWorldName());
			try
			{
				if (File.Exists(_saveFilePath))
				{
					string json = File.ReadAllText(_saveFilePath);
					ParseMessagesJson(json);
					ManualLogSource log = VikingMessagesPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"Loaded {_messages.Count} messages");
					}
				}
				if (File.Exists(_leaderboardFilePath))
				{
					string json2 = File.ReadAllText(_leaderboardFilePath);
					ParseLeaderboardJson(json2);
					ManualLogSource log2 = VikingMessagesPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"Loaded {_playerReputations.Count} player reputations");
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = VikingMessagesPlugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)$"Failed to load data: {arg}");
				}
			}
		}

		private static void ParseMessagesJson(string json)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			_messages.Clear();
			int startIndex = 0;
			while ((startIndex = json.IndexOf("\"Id\":", startIndex)) >= 0)
			{
				try
				{
					VikingMessage vikingMessage = new VikingMessage();
					vikingMessage.Id = ExtractString(json, "Id", startIndex);
					vikingMessage.Position = new Vector3(ExtractFloat(json, "PosX", startIndex), ExtractFloat(json, "PosY", startIndex), ExtractFloat(json, "PosZ", startIndex));
					vikingMessage.Rotation = new Quaternion(ExtractFloat(json, "RotX", startIndex), ExtractFloat(json, "RotY", startIndex), ExtractFloat(json, "RotZ", startIndex), ExtractFloat(json, "RotW", startIndex));
					vikingMessage.Template = ExtractString(json, "Template", startIndex);
					vikingMessage.Words = ExtractString(json, "Words", startIndex);
					vikingMessage.EmoteIndex = (int)ExtractFloat(json, "EmoteIndex", startIndex);
					vikingMessage.AuthorId = (long)ExtractFloat(json, "AuthorId", startIndex);
					vikingMessage.AuthorName = ExtractString(json, "AuthorName", startIndex);
					vikingMessage.Reputation = (int)ExtractFloat(json, "Reputation", startIndex);
					vikingMessage.LookDirection = new Vector3(ExtractFloat(json, "LookDirX", startIndex), ExtractFloat(json, "LookDirY", startIndex), ExtractFloat(json, "LookDirZ", startIndex));
					vikingMessage.EquippedItems = ExtractStringArray(json, "Equipment", startIndex);
					vikingMessage.VotedPlayers = ExtractLongArray(json, "VotedPlayers", startIndex);
					if (!string.IsNullOrEmpty(vikingMessage.Id))
					{
						_messages[vikingMessage.Id] = vikingMessage;
					}
				}
				catch
				{
				}
				startIndex++;
			}
		}

		private static void ParseLeaderboardJson(string json)
		{
			_playerReputations.Clear();
			int startIndex = 0;
			while ((startIndex = json.IndexOf("\"PlayerId\":", startIndex)) >= 0)
			{
				try
				{
					PlayerReputation playerReputation = new PlayerReputation();
					playerReputation.PlayerId = (long)ExtractFloat(json, "PlayerId", startIndex);
					playerReputation.PlayerName = ExtractString(json, "PlayerName", startIndex);
					playerReputation.TotalReputation = (int)ExtractFloat(json, "TotalReputation", startIndex);
					playerReputation.MessageCount = (int)ExtractFloat(json, "MessageCount", startIndex);
					if (playerReputation.PlayerId != 0)
					{
						_playerReputations[playerReputation.PlayerId] = playerReputation;
					}
				}
				catch
				{
				}
				startIndex++;
			}
		}

		private static string F(float v)
		{
			return v.ToString(CultureInfo.InvariantCulture);
		}

		private static string Escape(string s)
		{
			return s?.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") ?? "";
		}

		private static string ExtractString(string json, string field, int startIdx)
		{
			string text = "\"" + field + "\": \"";
			int num = json.IndexOf(text, startIdx);
			if (num < 0 || num > startIdx + 2000)
			{
				return "";
			}
			num += text.Length;
			int num2 = json.IndexOf("\"", num);
			if (num2 < 0)
			{
				return "";
			}
			return json.Substring(num, num2 - num).Replace("\\n", "\n").Replace("\\\"", "\"");
		}

		private static float ExtractFloat(string json, string field, int startIdx)
		{
			string text = "\"" + field + "\": ";
			int num = json.IndexOf(text, startIdx);
			if (num < 0 || num > startIdx + 2000)
			{
				return 0f;
			}
			num += text.Length;
			int i;
			for (i = num; i < json.Length && (char.IsDigit(json[i]) || json[i] == '.' || json[i] == '-' || json[i] == 'E' || json[i] == 'e' || json[i] == '+'); i++)
			{
			}
			float.TryParse(json.Substring(num, i - num), NumberStyles.Float, CultureInfo.InvariantCulture, out var result);
			return result;
		}

		private static string[] ExtractStringArray(string json, string field, int startIdx)
		{
			List<string> list = new List<string>();
			string text = "\"" + field + "\": [";
			int num = json.IndexOf(text, startIdx);
			if (num < 0 || num > startIdx + 2000)
			{
				return list.ToArray();
			}
			num += text.Length;
			int num2 = json.IndexOf("]", num);
			if (num2 < 0)
			{
				return list.ToArray();
			}
			string text2 = json.Substring(num, num2 - num);
			int startIndex = 0;
			while ((startIndex = text2.IndexOf("\"", startIndex)) >= 0)
			{
				int num3 = startIndex + 1;
				int num4 = text2.IndexOf("\"", num3);
				if (num4 > num3)
				{
					list.Add(text2.Substring(num3, num4 - num3));
				}
				startIndex = num4 + 1;
			}
			return list.ToArray();
		}

		private static List<long> ExtractLongArray(string json, string field, int startIdx)
		{
			List<long> list = new List<long>();
			string text = "\"" + field + "\": [";
			int num = json.IndexOf(text, startIdx);
			if (num < 0 || num > startIdx + 2000)
			{
				return list;
			}
			num += text.Length;
			int num2 = json.IndexOf("]", num);
			if (num2 < 0)
			{
				return list;
			}
			string text2 = json.Substring(num, num2 - num);
			string[] array = text2.Split(new char[1] { ',' });
			foreach (string text3 in array)
			{
				if (long.TryParse(text3.Trim(), out var result))
				{
					list.Add(result);
				}
			}
			return list;
		}
	}
	[HarmonyPatch]
	public static class NetworkingPatches
	{
		[CompilerGenerated]
		private sealed class <DelayedLoad>d__2 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedLoad>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)