Files
BetterAmongUs/Patches/AnnouncementPatch.cs
T
2025-07-14 04:50:04 -05:00

175 lines
5.8 KiB
C#

using AmongUs.Data;
using AmongUs.Data.Player;
using Assets.InnerNet;
using BetterAmongUs.Helpers;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using System.Reflection;
using UnityEngine;
namespace BetterAmongUs.Patches;
internal enum NewsTypes
{
None,
BAU,
TEN
}
[HarmonyPatch]
internal class ModNews
{
internal NewsTypes NewsType;
internal int Number;
internal string Title;
internal string SubTitle;
internal string ShortTitle;
internal string Text;
internal string Date;
internal Announcement ToAnnouncement()
{
var result = new Announcement
{
Number = Number,
Title = Title,
SubTitle = SubTitle,
ShortTitle = ShortTitle,
Text = Text,
Language = (uint)DataManager.Settings.Language.CurrentLanguage,
Date = Date,
Id = "ModNews"
};
return result;
}
internal static List<ModNews> AllModNews = new List<ModNews>();
public ModNews(NewsTypes type, int number, string title, string subTitle, string shortTitle, string text, string date)
{
NewsType = type;
Number = number;
Title = title;
SubTitle = subTitle;
ShortTitle = shortTitle;
Text = text;
Date = date;
AllModNews.Add(this);
}
private static string ReadEmbeddedResource(string resourceName)
{
var assembly = Assembly.GetExecutingAssembly();
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
throw new FileNotFoundException("Resource not found: " + resourceName);
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
private static void ProcessModNewsFiles()
{
AllModNews.Clear();
var assembly = Assembly.GetExecutingAssembly();
var resourceNames = assembly.GetManifestResourceNames()
.Where(name => name.StartsWith("BetterAmongUs.Resources.ModNews") && name.EndsWith(".txt"));
foreach (var resourceName in resourceNames)
{
var content = ReadEmbeddedResource(resourceName);
ParseModNewsContent(content);
}
}
private static void ParseModNewsContent(string content)
{
var lines = content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int number = 0;
string title = "", subTitle = "", shortTitle = "", text = "", date = "";
NewsTypes type = NewsTypes.None;
foreach (var line in lines)
{
if (line.StartsWith("#Skip")) return;
else if (line.StartsWith("#Type:"))
{
switch (line[6..])
{
case "BAU":
type = NewsTypes.BAU;
break;
case "TEN":
type = NewsTypes.TEN;
break;
}
}
else if (line.StartsWith("#Number:")) number = int.Parse(line[8..]);
else if (line.StartsWith("#Title:")) title = line[7..];
else if (line.StartsWith("#SubTitle:")) subTitle = line[10..];
else if (line.StartsWith("#ShortTitle:")) shortTitle = line[12..];
else if (line.StartsWith("#Date:")) date = line[6..];
else if (line.StartsWith("#-----------------------------")) continue;
else if (line.StartsWith("#") && line.Length <= 1) text += "\n";
else text += line + "\n";
}
if (number != 0)
{
new ModNews(type, number, title, subTitle, shortTitle, text, date);
}
}
[HarmonyPatch(typeof(PlayerAnnouncementData), nameof(PlayerAnnouncementData.SetAnnouncements)), HarmonyPrefix]
internal static bool SetModAnnouncements(PlayerAnnouncementData __instance, [HarmonyArgument(0)] ref Il2CppReferenceArray<Announcement> aRange)
{
ProcessModNewsFiles();
AllModNews.Sort((a1, a2) => DateTime.Compare(DateTime.Parse(a2.Date), DateTime.Parse(a1.Date)));
List<Announcement> finalAllNews = new List<Announcement>();
AllModNews.ForEach(n => finalAllNews.Add(n.ToAnnouncement()));
foreach (var news in aRange)
{
if (!AllModNews.Any(x => x.Number == news.Number))
finalAllNews.Add(news);
}
finalAllNews.Sort((a1, a2) => DateTime.Compare(DateTime.Parse(a2.Date), DateTime.Parse(a1.Date)));
aRange = new Il2CppReferenceArray<Announcement>(finalAllNews.Count);
for (int i = 0; i < finalAllNews.Count; i++)
aRange[i] = finalAllNews[i];
return true;
}
[HarmonyPatch(typeof(AnnouncementPanel), nameof(AnnouncementPanel.SetUp)), HarmonyPostfix]
internal static void SetUpPanel(AnnouncementPanel __instance, [HarmonyArgument(0)] Announcement announcement)
{
if (announcement.Number < 100000) return;
var obj = new GameObject("ModLabel");
obj.transform.SetParent(__instance.transform);
obj.transform.localPosition = new Vector3(-0.8f, 0.13f, 0.5f);
obj.transform.localScale = new Vector3(0.9f, 0.9f, 0.9f);
var renderer = obj.AddComponent<SpriteRenderer>();
switch (AllModNews.Find(a => a.Number == announcement.Number).NewsType)
{
case NewsTypes.BAU:
renderer.sprite = Utils.LoadSprite($"BetterAmongUs.Resources.Images.BetterAmongUs-Icon.png", 650f);
break;
case NewsTypes.TEN:
renderer.sprite = Utils.LoadSprite($"BetterAmongUs.Resources.Images.TENCreditsButton.png", 365f);
break;
default:
break;
}
renderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask;
}
}