Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
using System;
|
2026-03-23 03:06:00 +01:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.Pipes;
|
|
|
|
|
using System.Threading;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
using DiscordRPC;
|
2026-03-23 03:06:00 +01:00
|
|
|
using DiscordRPC.IO;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
using DiscordRPC.Logging;
|
|
|
|
|
using MinecraftClient.Mapping;
|
|
|
|
|
using MinecraftClient.Scripting;
|
|
|
|
|
using Tomlet.Attributes;
|
|
|
|
|
|
|
|
|
|
namespace MinecraftClient.ChatBots
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Displays a Discord Rich Presence status showing the player's
|
|
|
|
|
/// current Minecraft session information (server, health, dimension, etc.).
|
|
|
|
|
/// Requires a Discord Application ID from https://discord.com/developers/applications
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class DiscordRpc : ChatBot
|
|
|
|
|
{
|
|
|
|
|
public static Configs Config = new();
|
|
|
|
|
|
|
|
|
|
[TomlDoNotInlineObject]
|
|
|
|
|
public class Configs
|
|
|
|
|
{
|
|
|
|
|
[NonSerialized]
|
|
|
|
|
private const string BotName = "DiscordRpc";
|
|
|
|
|
|
|
|
|
|
public bool Enabled = false;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ApplicationId$")]
|
|
|
|
|
public string ApplicationId = string.Empty;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.PresenceDetails$")]
|
|
|
|
|
public string PresenceDetails = "Playing on {server_host}:{server_port}";
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.PresenceState$")]
|
|
|
|
|
public string PresenceState = "{dimension} - HP: {health}/{max_health}";
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.LargeImageKey$")]
|
|
|
|
|
public string LargeImageKey = "mcc_icon";
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.LargeImageText$")]
|
|
|
|
|
public string LargeImageText = "Minecraft Console Client";
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.SmallImageKey$")]
|
|
|
|
|
public string SmallImageKey = string.Empty;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.SmallImageText$")]
|
|
|
|
|
public string SmallImageText = string.Empty;
|
|
|
|
|
|
2026-03-23 00:08:08 +00:00
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowServerAddress$")]
|
|
|
|
|
public bool ShowServerAddress = true;
|
|
|
|
|
|
2026-03-23 00:13:03 +00:00
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowCoordinates$")]
|
|
|
|
|
public bool ShowCoordinates = true;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowHealth$")]
|
|
|
|
|
public bool ShowHealth = true;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowDimension$")]
|
|
|
|
|
public bool ShowDimension = true;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowGamemode$")]
|
|
|
|
|
public bool ShowGamemode = true;
|
|
|
|
|
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowElapsedTime$")]
|
|
|
|
|
public bool ShowElapsedTime = true;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.ShowPlayerCount$")]
|
|
|
|
|
public bool ShowPlayerCount = true;
|
|
|
|
|
|
|
|
|
|
[TomlInlineComment("$ChatBot.DiscordRpc.UpdateIntervalSeconds$")]
|
|
|
|
|
public int UpdateIntervalSeconds = 10;
|
|
|
|
|
|
|
|
|
|
public void OnSettingUpdate()
|
|
|
|
|
{
|
|
|
|
|
ApplicationId ??= string.Empty;
|
|
|
|
|
PresenceDetails ??= string.Empty;
|
|
|
|
|
PresenceState ??= string.Empty;
|
|
|
|
|
LargeImageKey ??= string.Empty;
|
|
|
|
|
LargeImageText ??= string.Empty;
|
|
|
|
|
SmallImageKey ??= string.Empty;
|
|
|
|
|
SmallImageText ??= string.Empty;
|
|
|
|
|
|
|
|
|
|
if (UpdateIntervalSeconds < 1)
|
|
|
|
|
{
|
|
|
|
|
UpdateIntervalSeconds = 10;
|
|
|
|
|
LogToConsole(BotName, Translations.bot_DiscordRpc_invalid_interval);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
private DiscordRpcClient? _rpcClient;
|
|
|
|
|
private int _tickCounter;
|
|
|
|
|
private int _updateIntervalTicks;
|
|
|
|
|
private Timestamps? _sessionTimestamps;
|
|
|
|
|
private float _lastHealth;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(Config.ApplicationId))
|
|
|
|
|
{
|
|
|
|
|
LogToConsole(Translations.bot_DiscordRpc_missing_app_id);
|
|
|
|
|
UnloadBot();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-03-23 03:01:06 +01:00
|
|
|
_rpcClient = OperatingSystem.IsLinux()
|
|
|
|
|
? new DiscordRpcClient(Config.ApplicationId.Trim(), client: new DiscordRpcPipeClient())
|
|
|
|
|
: new DiscordRpcClient(Config.ApplicationId.Trim());
|
|
|
|
|
|
|
|
|
|
_rpcClient.Logger = Settings.Config.Logging.DebugMessages
|
|
|
|
|
? new ConsoleLogger(LogLevel.Trace)
|
|
|
|
|
: new ConsoleLogger(LogLevel.None);
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_rpcClient.OnReady += (_, e) =>
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
{
|
|
|
|
|
LogToConsole(string.Format(Translations.bot_DiscordRpc_connected, e.User.Username));
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_rpcClient.OnConnectionFailed += (_, e) =>
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
{
|
|
|
|
|
LogToConsole(string.Format(Translations.bot_DiscordRpc_connection_failed, e.FailedPipe));
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_rpcClient.Initialize();
|
|
|
|
|
_updateIntervalTicks = Settings.DoubleToTick(Config.UpdateIntervalSeconds);
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
|
|
|
|
LogToConsole(Translations.bot_DiscordRpc_initialized);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
LogToConsole(string.Format(Translations.bot_DiscordRpc_init_error, e.Message));
|
|
|
|
|
LogDebugToConsole(e.StackTrace ?? string.Empty);
|
|
|
|
|
UnloadBot();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void OnUnload()
|
|
|
|
|
{
|
2026-03-23 01:05:48 +00:00
|
|
|
if (_rpcClient is { IsDisposed: false })
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
{
|
2026-03-23 01:05:48 +00:00
|
|
|
_rpcClient.ClearPresence();
|
|
|
|
|
_rpcClient.Dispose();
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_rpcClient = null;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void AfterGameJoined()
|
|
|
|
|
{
|
|
|
|
|
if (Config.ShowElapsedTime)
|
2026-03-23 01:05:48 +00:00
|
|
|
_sessionTimestamps = Timestamps.Now;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_lastHealth = Handler.GetHealth();
|
|
|
|
|
_tickCounter = 0;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
SetPresence();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Update()
|
|
|
|
|
{
|
2026-03-23 01:05:48 +00:00
|
|
|
_tickCounter++;
|
|
|
|
|
if (_tickCounter < _updateIntervalTicks)
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
return;
|
|
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_tickCounter = 0;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
SetPresence();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void OnHealthUpdate(float health, int food)
|
|
|
|
|
{
|
2026-03-23 01:05:48 +00:00
|
|
|
_lastHealth = health;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool OnDisconnect(DisconnectReason reason, string message)
|
|
|
|
|
{
|
2026-03-23 01:05:48 +00:00
|
|
|
if (_rpcClient is { IsDisposed: false })
|
|
|
|
|
_rpcClient.ClearPresence();
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetPresence()
|
|
|
|
|
{
|
2026-03-23 01:05:48 +00:00
|
|
|
if (_rpcClient is null or { IsDisposed: true })
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string details = ReplacePlaceholders(Config.PresenceDetails);
|
|
|
|
|
string state = ReplacePlaceholders(Config.PresenceState);
|
|
|
|
|
|
|
|
|
|
var presence = new RichPresence
|
|
|
|
|
{
|
|
|
|
|
Details = TruncateForDiscord(details, 128),
|
|
|
|
|
State = TruncateForDiscord(state, 128)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Assets (images)
|
|
|
|
|
var assets = new Assets();
|
|
|
|
|
bool hasAssets = false;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(Config.LargeImageKey))
|
|
|
|
|
{
|
|
|
|
|
assets.LargeImageKey = Config.LargeImageKey.Trim();
|
|
|
|
|
assets.LargeImageText = TruncateForDiscord(
|
|
|
|
|
ReplacePlaceholders(Config.LargeImageText), 128);
|
|
|
|
|
hasAssets = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(Config.SmallImageKey))
|
|
|
|
|
{
|
|
|
|
|
assets.SmallImageKey = Config.SmallImageKey.Trim();
|
|
|
|
|
assets.SmallImageText = TruncateForDiscord(
|
|
|
|
|
ReplacePlaceholders(Config.SmallImageText), 128);
|
|
|
|
|
hasAssets = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasAssets)
|
|
|
|
|
presence.Assets = assets;
|
|
|
|
|
|
|
|
|
|
// Timestamps
|
2026-03-23 01:05:48 +00:00
|
|
|
if (Config.ShowElapsedTime && _sessionTimestamps is not null)
|
|
|
|
|
presence.Timestamps = _sessionTimestamps;
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
|
|
|
|
// Player count as party
|
|
|
|
|
if (Config.ShowPlayerCount)
|
|
|
|
|
{
|
|
|
|
|
string[] onlinePlayers = GetOnlinePlayers();
|
|
|
|
|
int playerCount = onlinePlayers.Length;
|
|
|
|
|
if (playerCount > 0)
|
|
|
|
|
{
|
|
|
|
|
presence.Party = new Party
|
|
|
|
|
{
|
|
|
|
|
ID = $"mcc_{GetServerHost()}_{GetServerPort()}",
|
|
|
|
|
Size = playerCount,
|
2026-03-23 00:08:08 +00:00
|
|
|
Max = playerCount
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 01:05:48 +00:00
|
|
|
_rpcClient.SetPresence(presence);
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
LogDebugToConsole(string.Format(Translations.bot_DiscordRpc_update_error, e.Message));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string ReplacePlaceholders(string template)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(template))
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
2026-03-23 00:08:08 +00:00
|
|
|
string serverHost = Config.ShowServerAddress ? GetServerHost() : "Hidden";
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
int serverPort = GetServerPort();
|
2026-03-23 00:08:08 +00:00
|
|
|
string serverPortStr = Config.ShowServerAddress ? serverPort.ToString() : "****";
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
string username = GetUsername();
|
|
|
|
|
float health = Handler.GetHealth();
|
2026-03-23 00:08:08 +00:00
|
|
|
int foodLevel = Handler.GetSaturation();
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
Location location = GetCurrentLocation();
|
|
|
|
|
string[] onlinePlayers = GetOnlinePlayers();
|
|
|
|
|
int gamemode = GetGamemode();
|
|
|
|
|
int protocolVersion = GetProtocolVersion();
|
|
|
|
|
|
2026-03-23 00:13:03 +00:00
|
|
|
string healthStr = Config.ShowHealth ? ((int)Math.Ceiling(health)).ToString() : "?";
|
|
|
|
|
string maxHealthStr = Config.ShowHealth ? "20" : "?";
|
|
|
|
|
string foodStr = Config.ShowHealth ? foodLevel.ToString() : "?";
|
|
|
|
|
string xStr = Config.ShowCoordinates ? ((int)location.X).ToString() : "?";
|
|
|
|
|
string yStr = Config.ShowCoordinates ? ((int)location.Y).ToString() : "?";
|
|
|
|
|
string zStr = Config.ShowCoordinates ? ((int)location.Z).ToString() : "?";
|
|
|
|
|
|
|
|
|
|
string dimensionName = Config.ShowDimension ? "Unknown" : "Hidden";
|
|
|
|
|
if (Config.ShowDimension)
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
{
|
2026-03-23 00:13:03 +00:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var dim = World.GetDimension();
|
|
|
|
|
dimensionName = dim.Name ?? "Unknown";
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
2026-03-23 00:13:03 +00:00
|
|
|
// Clean up the dimension name for display
|
2026-03-23 01:05:48 +00:00
|
|
|
if (dimensionName.StartsWith("minecraft:", StringComparison.Ordinal))
|
2026-03-23 00:13:03 +00:00
|
|
|
dimensionName = dimensionName["minecraft:".Length..];
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
2026-03-23 00:13:03 +00:00
|
|
|
dimensionName = dimensionName switch
|
|
|
|
|
{
|
|
|
|
|
"overworld" => "Overworld",
|
|
|
|
|
"the_nether" => "The Nether",
|
|
|
|
|
"the_end" => "The End",
|
|
|
|
|
_ => dimensionName
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
catch
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
{
|
2026-03-23 00:13:03 +00:00
|
|
|
// World may not be available
|
|
|
|
|
}
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-23 00:13:03 +00:00
|
|
|
string gamemodeStr = Config.ShowGamemode
|
|
|
|
|
? gamemode switch
|
|
|
|
|
{
|
|
|
|
|
0 => "Survival",
|
|
|
|
|
1 => "Creative",
|
|
|
|
|
2 => "Adventure",
|
|
|
|
|
3 => "Spectator",
|
|
|
|
|
_ => "Unknown"
|
|
|
|
|
}
|
|
|
|
|
: "Hidden";
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
|
|
|
|
|
return template
|
|
|
|
|
.Replace("{server_host}", serverHost)
|
2026-03-23 00:08:08 +00:00
|
|
|
.Replace("{server_port}", serverPortStr)
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
.Replace("{username}", username)
|
2026-03-23 00:13:03 +00:00
|
|
|
.Replace("{health}", healthStr)
|
|
|
|
|
.Replace("{max_health}", maxHealthStr)
|
|
|
|
|
.Replace("{food}", foodStr)
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
.Replace("{dimension}", dimensionName)
|
|
|
|
|
.Replace("{gamemode}", gamemodeStr)
|
2026-03-23 00:13:03 +00:00
|
|
|
.Replace("{x}", xStr)
|
|
|
|
|
.Replace("{y}", yStr)
|
|
|
|
|
.Replace("{z}", zStr)
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
.Replace("{player_count}", onlinePlayers.Length.ToString())
|
|
|
|
|
.Replace("{protocol}", protocolVersion.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string TruncateForDiscord(string value, int maxLength)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(value))
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
|
|
|
|
return value.Length <= maxLength ? value : value[..(maxLength - 3)] + "...";
|
|
|
|
|
}
|
2026-03-23 03:06:00 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Flatpak Discord exposes the RPC socket under app/com.discordapp.Discord,
|
|
|
|
|
/// but the currently published DiscordRichPresence package does not probe that path.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private sealed class DiscordRpcPipeClient : INamedPipeClient
|
|
|
|
|
{
|
|
|
|
|
private const string DiscordPipePrefix = "discord-ipc-";
|
|
|
|
|
private const int MaximumPipeVariations = 10;
|
|
|
|
|
|
|
|
|
|
private static readonly string[] s_unixPackageDirectories =
|
|
|
|
|
[
|
|
|
|
|
// Official Discord clients
|
|
|
|
|
"app/com.discordapp.Discord",
|
|
|
|
|
"snap.discord",
|
|
|
|
|
|
|
|
|
|
// Community desktop clients / wrappers
|
|
|
|
|
"app/dev.vencord.Vesktop",
|
|
|
|
|
".flatpak/dev.vencord.Vesktop/xdg-run",
|
|
|
|
|
"app/org.equicord.equibop",
|
|
|
|
|
"app/io.github.equicord.equibop",
|
|
|
|
|
"app/xyz.armcord.ArmCord",
|
|
|
|
|
"app/io.github.spacingbat3.webcord"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
private readonly byte[] _buffer = new byte[PipeFrame.MAX_SIZE];
|
|
|
|
|
private readonly Queue<PipeFrame> _frameQueue = new();
|
|
|
|
|
private readonly object _frameQueueLock = new();
|
|
|
|
|
private readonly object _streamLock = new();
|
|
|
|
|
|
|
|
|
|
private int _connectedPipe;
|
|
|
|
|
private NamedPipeClientStream? _stream;
|
|
|
|
|
private volatile bool _isClosed = true;
|
|
|
|
|
private volatile bool _isDisposed;
|
|
|
|
|
|
|
|
|
|
public ILogger Logger { get; set; } = new NullLogger();
|
|
|
|
|
|
|
|
|
|
public bool IsConnected
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_isClosed)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
lock (_streamLock)
|
|
|
|
|
return _stream is { IsConnected: true };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Obsolete("The connected pipe is not neccessary information.")]
|
|
|
|
|
public int ConnectedPipe => _connectedPipe;
|
|
|
|
|
|
|
|
|
|
public bool Connect(int pipe)
|
|
|
|
|
{
|
|
|
|
|
Logger.Trace("DiscordRpcPipeClient.Connect({0})", pipe);
|
|
|
|
|
|
|
|
|
|
if (_isDisposed)
|
|
|
|
|
throw new ObjectDisposedException(nameof(DiscordRpcPipeClient));
|
|
|
|
|
|
|
|
|
|
if (pipe > 9)
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(pipe), "Argument cannot be greater than 9");
|
|
|
|
|
|
|
|
|
|
int startPipe = pipe >= 0 ? pipe : 0;
|
|
|
|
|
|
|
|
|
|
foreach (string pipeName in GetPipeCandidates(startPipe))
|
|
|
|
|
{
|
|
|
|
|
if (AttemptConnection(pipeName))
|
|
|
|
|
{
|
|
|
|
|
BeginReadStream();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool ReadFrame(out PipeFrame frame)
|
|
|
|
|
{
|
|
|
|
|
if (_isDisposed)
|
|
|
|
|
throw new ObjectDisposedException(nameof(DiscordRpcPipeClient));
|
|
|
|
|
|
|
|
|
|
lock (_frameQueueLock)
|
|
|
|
|
{
|
|
|
|
|
if (_frameQueue.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
frame = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
frame = _frameQueue.Dequeue();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool WriteFrame(PipeFrame frame)
|
|
|
|
|
{
|
|
|
|
|
if (_isDisposed)
|
|
|
|
|
throw new ObjectDisposedException(nameof(DiscordRpcPipeClient));
|
|
|
|
|
|
|
|
|
|
if (_isClosed || !IsConnected)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("Failed to write frame because the stream is closed");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
frame.WriteStream(_stream);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (IOException io)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("Failed to write frame because of a IO Exception: {0}", io.Message);
|
|
|
|
|
}
|
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Failed to write frame as the stream was already disposed");
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Failed to write frame because of a invalid operation");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Close()
|
|
|
|
|
{
|
|
|
|
|
if (_isClosed)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Tried to close a already closed pipe.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
lock (_streamLock)
|
|
|
|
|
{
|
|
|
|
|
if (_stream is not null)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_stream.Flush();
|
|
|
|
|
_stream.Dispose();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream = null;
|
|
|
|
|
_isClosed = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Stream was closed, but no stream was available to begin with!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Tried to dispose already disposed stream");
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
_isClosed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if (_isDisposed)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!_isClosed)
|
|
|
|
|
Close();
|
|
|
|
|
|
|
|
|
|
lock (_streamLock)
|
|
|
|
|
{
|
|
|
|
|
_stream?.Dispose();
|
|
|
|
|
_stream = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_isDisposed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool AttemptConnection(string pipeName)
|
|
|
|
|
{
|
|
|
|
|
if (_isDisposed)
|
|
|
|
|
throw new ObjectDisposedException(nameof(DiscordRpcPipeClient));
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
lock (_streamLock)
|
|
|
|
|
{
|
|
|
|
|
Logger.Info("Attempting to connect to {0}", pipeName);
|
|
|
|
|
_stream = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
|
|
|
|
|
_stream.Connect(0);
|
|
|
|
|
|
|
|
|
|
Logger.Trace("Waiting for connection...");
|
|
|
|
|
while (!_stream.IsConnected)
|
|
|
|
|
Thread.Sleep(10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger.Info("Connected to {0}", pipeName);
|
|
|
|
|
_connectedPipe = int.Parse(pipeName[(pipeName.LastIndexOf('-') + 1)..], System.Globalization.CultureInfo.InvariantCulture);
|
|
|
|
|
_isClosed = false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("Failed connection to {0}. {1}", pipeName, e.Message);
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger.Trace("Done. Result: {0}", _isClosed);
|
|
|
|
|
return !_isClosed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BeginReadStream()
|
|
|
|
|
{
|
|
|
|
|
if (_isClosed)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
lock (_streamLock)
|
|
|
|
|
{
|
|
|
|
|
if (_stream is not { IsConnected: true })
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Logger.Trace("Beginning Read of {0} bytes", _buffer.Length);
|
|
|
|
|
_stream.BeginRead(_buffer, 0, _buffer.Length, EndReadStream, _stream.IsConnected);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Attempted to start reading from a disposed pipe");
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Attempted to start reading from a closed pipe");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("An exception occurred while starting to read a stream: {0}", e.Message);
|
|
|
|
|
Logger.Error(e.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void EndReadStream(IAsyncResult callback)
|
|
|
|
|
{
|
|
|
|
|
Logger.Trace("Ending Read");
|
|
|
|
|
int bytes;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
lock (_streamLock)
|
|
|
|
|
{
|
|
|
|
|
if (_stream is not { IsConnected: true })
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bytes = _stream.EndRead(callback);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (IOException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Attempted to end reading from a closed pipe");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
catch (NullReferenceException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Attempted to read from a null pipe");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warning("Attempted to end reading from a disposed pipe");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("An exception occurred while ending a read of a stream: {0}", e.Message);
|
|
|
|
|
Logger.Error(e.StackTrace);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger.Trace("Read {0} bytes", bytes);
|
|
|
|
|
|
|
|
|
|
if (bytes > 0)
|
|
|
|
|
{
|
|
|
|
|
using MemoryStream memory = new(_buffer, 0, bytes);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
PipeFrame frame = new();
|
|
|
|
|
if (frame.ReadStream(memory))
|
|
|
|
|
{
|
|
|
|
|
Logger.Trace("Read a frame: {0}", frame.Opcode);
|
|
|
|
|
lock (_frameQueueLock)
|
|
|
|
|
_frameQueue.Enqueue(frame);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("Pipe failed to read from the data received by the stream.");
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("An exception has occurred while trying to parse the pipe data: {0}", e.Message);
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Error("Empty frame was read on {0}, aborting.", Environment.OSVersion);
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!_isClosed && IsConnected)
|
|
|
|
|
{
|
|
|
|
|
Logger.Trace("Starting another read");
|
|
|
|
|
BeginReadStream();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<string> GetPipeCandidates(int startPipe)
|
|
|
|
|
{
|
|
|
|
|
if (OperatingSystem.IsWindows())
|
|
|
|
|
{
|
|
|
|
|
for (int i = startPipe; i < MaximumPipeVariations; i++)
|
|
|
|
|
yield return $"{DiscordPipePrefix}{i}";
|
|
|
|
|
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (string runtimeDir in GetUnixRuntimeDirectories())
|
|
|
|
|
{
|
|
|
|
|
for (int index = startPipe; index < MaximumPipeVariations; index++)
|
|
|
|
|
{
|
|
|
|
|
string pipeFileName = $"{DiscordPipePrefix}{index}";
|
|
|
|
|
|
|
|
|
|
foreach (string packageDirectory in s_unixPackageDirectories)
|
|
|
|
|
{
|
|
|
|
|
string packagePipe = Path.Combine(runtimeDir, packageDirectory, pipeFileName);
|
|
|
|
|
if (File.Exists(packagePipe))
|
|
|
|
|
yield return packagePipe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string defaultPipe = Path.Combine(runtimeDir, pipeFileName);
|
|
|
|
|
if (File.Exists(defaultPipe))
|
|
|
|
|
yield return defaultPipe;
|
|
|
|
|
|
|
|
|
|
foreach (string packageDirectory in s_unixPackageDirectories)
|
|
|
|
|
{
|
|
|
|
|
string packagePipe = Path.Combine(runtimeDir, packageDirectory, pipeFileName);
|
|
|
|
|
if (!File.Exists(packagePipe))
|
|
|
|
|
yield return packagePipe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(defaultPipe))
|
|
|
|
|
yield return defaultPipe;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<string> GetUnixRuntimeDirectories()
|
|
|
|
|
{
|
|
|
|
|
HashSet<string> yielded = new(StringComparer.Ordinal);
|
|
|
|
|
|
|
|
|
|
string[] candidates =
|
|
|
|
|
[
|
|
|
|
|
Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR") ?? string.Empty,
|
|
|
|
|
Environment.GetEnvironmentVariable("TMPDIR") ?? string.Empty,
|
|
|
|
|
Environment.GetEnvironmentVariable("TMP") ?? string.Empty,
|
|
|
|
|
Environment.GetEnvironmentVariable("TEMP") ?? string.Empty,
|
|
|
|
|
Path.GetTempPath(),
|
|
|
|
|
"/tmp"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
foreach (string candidate in candidates)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(candidate))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
string normalized = candidate.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
|
|
|
|
if (yielded.Add(normalized))
|
|
|
|
|
yield return normalized;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Add Discord Rich Presence ChatBot integration
- Add DiscordRichPresence NuGet package (v1.143.0)
- Create DiscordRpc.cs ChatBot with configurable presence display
- Wire config in Settings.cs ChatBotConfig class
- Register bot in McClient.cs RegisterBots()
- Add translation strings to Translations.resx and Designer
- Add config comments to ConfigComments.resx and Designer
- Support placeholders: {server_host}, {server_port}, {username},
{health}, {max_health}, {food}, {dimension}, {gamemode},
{x}, {y}, {z}, {player_count}, {protocol}
Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/43388021-4264-47e6-8403-7a1bca66d86f
2026-03-23 00:03:55 +00:00
|
|
|
}
|
|
|
|
|
}
|