Skip to content

Commit

Permalink
Adding filters to chat events, custom messages for join/leave/death, …
Browse files Browse the repository at this point in the history
…hopefully fixing leave/join bug
  • Loading branch information
cryptiklemur committed Mar 2, 2021
1 parent 40ad730 commit 314f3ad
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 179 deletions.
13 changes: 0 additions & 13 deletions .github/workflows/compile.yml

This file was deleted.

57 changes: 57 additions & 0 deletions Configuration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DiscordNotifier.Patches;
using HarmonyLib;
using LitJson;
using UnityEngine;

namespace DiscordNotifier
{
public class Configuration
{
public readonly ConfigEntry<string> WebhookUrl;
public readonly ConfigEntry<bool> Enabled;
public readonly ConfigEntry<bool> FetchAndShowIp;
public readonly ConfigEntry<string> RawIgnoredUsernames;
public readonly ConfigEntry<string> IgnoredChatMessageRegex;

public readonly Dictionary<ValheimEvent, ConfigEntry<bool>> Events = new Dictionary<ValheimEvent, ConfigEntry<bool>>();
public readonly Dictionary<ValheimEvent, ConfigEntry<string>> EventMessages = new Dictionary<ValheimEvent, ConfigEntry<string>>();
private string[] _ignoredUsernames;

public string[] IgnoredUsernames => _ignoredUsernames ??= JsonMapper.ToObject<string[]>(RawIgnoredUsernames.Value);

internal Configuration(ConfigFile config)
{
Enabled = config.Bind("General", "Enabled", true, "Is the plugin enabled?");
FetchAndShowIp = config.Bind("General", "FetchAndShowIp", false, "Should the plugin attempt to get the server IP and post to the webhook");
WebhookUrl = config.Bind("General", "WebhookUrl", "", "Enter the Webhook URL from discord here.");
RawIgnoredUsernames = config.Bind("Chat", "IgnoredUsernames", "[]", "Array of ignored usernames. Use the format: [\"Coralle\", \"Steve\"]");
IgnoredChatMessageRegex = config.Bind("Chat", "IgnoredChatMessageRegex", "", "Specify a regex used to ignore chat messages.\nSyntax: /(^START)|(#END$)/\nThis would ignore text from the MapSync mod");

foreach (var eventName in Enum.GetNames(typeof(ValheimEvent)))
{
if (!Enum.TryParse(eventName, false, out ValheimEvent evt))
{
Main.StaticLogger.LogError("Bad event name, somehow: " + eventName);
continue;
}

Events[evt] = config.Bind("Events", eventName, true);
}

EventMessages[ValheimEvent.OnPlayerDeath] = config.Bind("Events", "OnPlayerDeathMessage", "{{username}} has died!",
"Message to send when a player dies.\nAvailable variables: {{username}}, {{userId}}");
EventMessages[ValheimEvent.OnPlayerDisconnected] = config.Bind("Events", "OnPlayerDisconnectedMessage", "{{username}} has disconnected!",
"Message to send when a player disconnects from the server.\nAvailable variables: {{username}}, {{userId}}");
EventMessages[ValheimEvent.OnPlayerJoined] = config.Bind("Events", "OnPlayerJoinedMessage", "{{username}} has joined!",
"Message to send when a player joins the server.\nAvailable variables: {{username}}, {{userId}}");
}
}
}
83 changes: 14 additions & 69 deletions DiscordNotifier.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
Expand All @@ -9,89 +7,36 @@
namespace DiscordNotifier
{
[BepInPlugin(GUID, MODNAME, VERSION)]
[HarmonyPatch]
public class Main : BaseUnityPlugin
{
public const string MODNAME = "Discord Notifier";
public const string AUTHOR = "CryptikLemur";
public const string GUID = "CryptikLemur_DiscordNotifier";
public const string VERSION = "0.0.1.0";
public const string VERSION = "0.0.3.5";

internal readonly Harmony harmony;
internal readonly Assembly assembly;

public static ConfigEntry<string> configWebhookUrl;
public static ConfigEntry<bool> configEnabled;
public static ConfigEntry<bool> configFetchAndShowIp;
public static ConfigEntry<bool> configTrackAllUsers;
public static Dictionary<ValheimEvent, ConfigEntry<bool>> configEvents = new Dictionary<ValheimEvent, ConfigEntry<bool>>();
internal Harmony harmony;
internal Assembly assembly;

internal static ManualLogSource StaticLogger;
internal static ZNet zNet;
internal static ZDOMan zdoMan;
internal static Game game;

public Main()
public static Configuration Configuration;

private void Awake()
{
harmony = new Harmony(GUID);
assembly = Assembly.GetExecutingAssembly();
StaticLogger = Logger;
Configuration = new Configuration(Config);

configEnabled = Config.Bind("General", "Enabled", true, "Is the plugin enabled?");
configFetchAndShowIp = Config.Bind("General", "FetchAndShowIp", false, "Should the plugin attempt to get the server IP and post to the webhook");
configWebhookUrl = Config.Bind("General", "WebhookUrl", "", "Enter the Webhook URL from discord here.");
configTrackAllUsers = Config.Bind("General", "TrackAllUsers", false, "Should the plugin track all the users on the server, or just you. If running as the server, this is ignored.");
if (!Configuration.Enabled.Value || Configuration.WebhookUrl.Value.Length <= 0) return;

foreach (var eventName in Enum.GetNames(typeof(ValheimEvent)))
{
if (!Enum.TryParse(eventName, false, out ValheimEvent evt))
{
Logger.LogError("Bad event name, somehow: " + eventName);
continue;
}

configEvents[evt] = Config.Bind("Events", eventName, true);
}
}
harmony = new Harmony(GUID);
assembly = Assembly.GetExecutingAssembly();

private void Awake()
{
if (configEnabled.Value && configWebhookUrl.Value.Length > 0)
{
harmony.PatchAll(assembly);
Logger.LogMessage($"{AUTHOR}'s {MODNAME} (v{VERSION}) has started");
}
harmony.PatchAll(assembly);
Logger.LogMessage($"{AUTHOR}'s {MODNAME} (v{VERSION}) has started");
}
private void OnDestroy()
{
if (configEnabled.Value) harmony.UnpatchSelf();
}

[HarmonyPatch(typeof(ZNet), "Awake")]
private class ZNetPatch
{
static void Prefix(ref ZNet __instance)
{
zNet = __instance;
}
}

[HarmonyPatch(typeof(ZDOMan), "ResetSectorArray")]
private class ZDOManPatch
{
static void Postfix(ref ZDOMan __instance)
{
zdoMan = __instance;
}
}

[HarmonyPatch(typeof(Game), "Awake")]
private class GamePatch
{
static void Prefix(ref Game __instance)
{
game = __instance;
}
if (Configuration.Enabled.Value) harmony.UnpatchSelf();
}
}
}
30 changes: 26 additions & 4 deletions DiscordNotifier.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<LangVersion>8.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="0Harmony">
<HintPath>Libs\0Harmony.dll</HintPath>
Expand All @@ -49,6 +52,9 @@
<Reference Include="BepInEx.Harmony">
<HintPath>..\..\..\AppData\Roaming\r2modmanPlus-local\Valheim\profiles\Modded2\BepInEx\core\BepInEx.Harmony.dll</HintPath>
</Reference>
<Reference Include="LitJSON, Version=0.17.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\LitJson.0.17.0\lib\net45\LitJSON.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
Expand All @@ -74,9 +80,10 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration.cs" />
<Compile Include="DiscordNotifier.cs" />
<Compile Include="Patches\FejdStartupPatch.cs" />
<Compile Include="Patches\ChatPatch.cs" />
<Compile Include="Patches\PlayerPatch.cs" />
<Compile Include="Patches\ZNetPatch.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils.cs" />
Expand All @@ -86,13 +93,28 @@
<None Include="manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<Content Include=".gitignore" />
<Content Include="icon.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PreBuildEvent>rmdir /s /q "$(TargetDir)\DiscordNotifier"</PreBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>copy /Y "$(TargetDir)$(ProjectName).dll" "C:\Users\aequa\AppData\Roaming\r2modmanPlus-local\Valheim\profiles\Modded3\BepInEx\plugins\$(ProjectName).dll"</PostBuildEvent>
<PostBuildEvent>copy /Y "$(TargetDir)$(ProjectName).dll" "C:\Users\aequa\AppData\Roaming\r2modmanPlus-local\Valheim\profiles\Modded3\BepInEx\plugins\"
copy /Y "$(TargetDir)LitJSON.dll" "C:\Users\aequa\AppData\Roaming\r2modmanPlus-local\Valheim\profiles\Modded3\BepInEx\plugins\"

mkdir "$(TargetDir)\DiscordNotifier"
mkdir "$(TargetDir)\DiscordNotifier\DiscordNotifier"
copy /Y "$(ProjectDir)\README.md" "$(TargetDir)\DiscordNotifier\"
copy /Y "$(ProjectDir)\icon.png" "$(TargetDir)\DiscordNotifier\"
copy /Y "$(ProjectDir)\manifest.json" "$(TargetDir)\DiscordNotifier\"
copy /Y "$(TargetDir)$(ProjectName).dll" "$(TargetDir)\DiscordNotifier\DiscordNotifier\"
copy /Y "$(TargetDir)LitJSON.dll" "$(TargetDir)\DiscordNotifier\DiscordNotifier\"
</PostBuildEvent>
</PropertyGroup>
</Project>
43 changes: 30 additions & 13 deletions Patches/ChatPatch.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,49 @@
using System.Collections.Generic;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using HarmonyLib;
using UnityEngine;

namespace DiscordNotifier.Patches
{
internal class ChatPatch
{
public static bool IsChatMessageIgnored(string user, string text)
{
// Ignoring text from MapSyncMod
if (text.StartsWith("START_") && text.EndsWith("#END")) return true;

// Ignoring "I HAVE ARRIVED!" yell, if we are already alerting when someone joins
if (Main.Configuration.Events[ValheimEvent.OnPlayerJoined].Value && text.ToLower() == "i have arrived!") return true;

// Ignoring messages from Configuration.ignoredUsernames
if (Main.Configuration.IgnoredUsernames.ToList().Contains(user)) return true;

var regexPattern = Main.Configuration.IgnoredChatMessageRegex.Value;
if (regexPattern.Length == 0 || !regexPattern.StartsWith("/")) return false;
var pattern = regexPattern.Substring(1, regexPattern.LastIndexOf("/", StringComparison.Ordinal) - 1);
var flagChars = regexPattern.Substring(regexPattern.LastIndexOf("/", StringComparison.Ordinal) + 1).ToLower().ToCharArray().ToList();

RegexOptions opts = RegexOptions.None;
if (flagChars.Contains('i')) opts |= RegexOptions.IgnoreCase;
if (flagChars.Contains('m')) opts |= RegexOptions.Multiline;
if (!flagChars.Contains('g')) opts |= RegexOptions.Singleline;

return Regex.IsMatch(text, pattern, opts);
}

[HarmonyPatch(typeof(Chat), "OnNewChatMessage")]
internal class OnNewChatMessage
{
private static bool Prefix(ref long senderID, ref string user, ref string text, ref Talker.Type type, ref Vector3 pos)
private static bool Prefix(ref string user, ref string text, ref Talker.Type type, ref Vector3 pos)
{
Main.StaticLogger.LogInfo($"Message from {user} ({senderID}): {text}");

// Ignoring text from MapSyncMod
if (text.StartsWith("START_") && text.EndsWith("#END")) return true;
if (!ZNet.instance.IsServer()|| IsChatMessageIgnored(user, text)) return true;

// Ignoring "I HAVE ARRIVED!" yell, if we are already alerting when someone joins
if (Main.configEvents[ValheimEvent.OnPlayerJoined].Value && text.ToLower() == "i have arrived!") return true;

if (Main.zNet.IsServer() || Main.configTrackAllUsers.Value)
{
ValheimEventHandler.OnPlayerMessage(type, user, text, pos);
}
ValheimEventHandler.OnPlayerMessage(type, user, text, pos);

return true;
}

}
}
}
39 changes: 39 additions & 0 deletions Patches/PlayerPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using HarmonyLib;

namespace DiscordNotifier.Patches
{
internal class PlayerPatch
{
private static bool hasSpawned = false;

private static ZNet.PlayerInfo getBasicPlayerInfoFromPlayer(Player player) => new ZNet.PlayerInfo
{
m_characterID = player.GetZDOID(),
m_name = player.GetPlayerName(),
m_position = player.transform.position
};

[HarmonyPatch(typeof(Player), "OnSpawned")]
internal class OnSpawned
{
private static void Prefix(ref Player __instance)
{
if (hasSpawned || !ZNet.instance.IsServer() || ZNet.instance.IsDedicated()) return;
hasSpawned = true;

ValheimEventHandler.OnPlayerJoined(getBasicPlayerInfoFromPlayer(__instance));
}
}

[HarmonyPatch(typeof(Player), "OnDeath")]
internal class OnDeath
{
private static void Postfix(ref Player __instance)
{
if (!ZNet.instance.IsServer() || ZNet.instance.IsDedicated()) return;

ValheimEventHandler.OnPlayerDeath(getBasicPlayerInfoFromPlayer(__instance));
}
}
}
}
Loading

0 comments on commit 314f3ad

Please sign in to comment.