mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Merge pull request #2965 from MCCTeam/copilot/implement-discord-rpc-integration
This commit is contained in:
commit
9db4ad86b4
11 changed files with 793 additions and 3 deletions
|
|
@ -9,9 +9,19 @@ This skill uses a fixed set of stable commands for local offline integration tes
|
|||
- `inventory player list`
|
||||
- `/gamemode creative`
|
||||
- `inventory creativegive 36 Diamond 16`
|
||||
- `inventory creativegive 37 IronSword 1`
|
||||
- `inventory creativegive 38 GoldenApple 8`
|
||||
- `inventory creativeclear 38`
|
||||
- `entity`
|
||||
- `/time query daytime`
|
||||
- `look up`
|
||||
- `look down`
|
||||
- `look east`
|
||||
- `/gamemode survival`
|
||||
- `respawn`
|
||||
- `/tp CursorBot 0 -60 0`
|
||||
- `smoke_test_from_mcc_full_spectrum`
|
||||
- `integration_test_chat_response`
|
||||
|
||||
Notes:
|
||||
- Lines starting with `/` are sent to the server as chat/commands.
|
||||
|
|
@ -24,6 +34,11 @@ Notes:
|
|||
- `gamerule logAdminCommands true`
|
||||
- `time set day`
|
||||
- `weather clear`
|
||||
- `say Hello from the server console`
|
||||
- `msg CursorBot This is a private whisper`
|
||||
- `effect give CursorBot minecraft:speed 30 1`
|
||||
- `effect give CursorBot minecraft:regeneration 10 1`
|
||||
- `kill CursorBot`
|
||||
|
||||
## Representative entity coverage
|
||||
|
||||
|
|
@ -34,6 +49,21 @@ Notes:
|
|||
- `execute as CursorBot at @s run summon minecraft:villager ~-2 ~ ~`
|
||||
- `execute as CursorBot at @s run summon minecraft:allay ~-4 ~ ~`
|
||||
- `execute as CursorBot at @s run summon minecraft:armor_stand ~ ~ ~2`
|
||||
- `execute as CursorBot at @s run summon minecraft:item_display ~-6 ~ ~ {item:{id:"minecraft:diamond",count:1}}`
|
||||
- `execute as CursorBot at @s run summon minecraft:spider ~10 ~ ~`
|
||||
- `execute as CursorBot at @s run summon minecraft:pig ~-8 ~ ~`
|
||||
|
||||
## Block placement coverage
|
||||
|
||||
- `execute as CursorBot at @s run fill ~1 ~ ~1 ~3 ~2 ~3 minecraft:stone`
|
||||
- `execute as CursorBot at @s run setblock ~5 ~ ~5 minecraft:chest`
|
||||
- `execute as CursorBot at @s run setblock ~5 ~1 ~5 minecraft:furnace`
|
||||
- `execute as CursorBot at @s run setblock ~6 ~ ~5 minecraft:crafting_table`
|
||||
|
||||
## Dimension change coverage
|
||||
|
||||
- `execute in minecraft:the_nether run tp CursorBot 0 64 0`
|
||||
- `execute in minecraft:overworld run tp CursorBot 0 -60 0`
|
||||
|
||||
## Representative particle coverage
|
||||
|
||||
|
|
@ -41,13 +71,21 @@ Notes:
|
|||
- `execute as CursorBot at @s run particle minecraft:end_rod ~ ~1 ~ 0.5 0.5 0.5 0.01 20 force`
|
||||
- `execute as CursorBot at @s run particle minecraft:explosion ~ ~1 ~ 0 0 0 0 1 force`
|
||||
- `execute as CursorBot at @s run particle minecraft:totem_of_undying ~ ~1 ~ 0.5 0.5 0.5 0.1 20 force`
|
||||
- `execute as CursorBot at @s run particle minecraft:flame ~ ~1 ~ 0.2 0.2 0.2 0.02 30 force`
|
||||
- `execute as CursorBot at @s run particle minecraft:heart ~ ~2 ~ 0.3 0.3 0.3 0 5 force`
|
||||
|
||||
## Representative sound coverage
|
||||
|
||||
- `execute as CursorBot at @s run playsound minecraft:entity.lightning_bolt.thunder master CursorBot ~ ~ ~ 1 1 0`
|
||||
- `execute as CursorBot at @s run playsound minecraft:block.note_block.bell master CursorBot ~ ~ ~ 1 1 0`
|
||||
- `execute as CursorBot at @s run playsound minecraft:entity.experience_orb.pickup master CursorBot ~ ~ ~ 1 1 0`
|
||||
|
||||
## Explosion coverage
|
||||
|
||||
- `execute as CursorBot at @s run summon minecraft:tnt ~3 ~ ~`
|
||||
- `execute as CursorBot at @s run summon minecraft:tnt ~6 ~ ~`
|
||||
|
||||
## Kill and respawn cycle
|
||||
|
||||
- `kill CursorBot` (via RCON, requires survival mode)
|
||||
- `respawn` (via MCC command after death)
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ run_server_command "time set day"
|
|||
run_server_command "weather clear"
|
||||
sleep 2
|
||||
|
||||
# ── Phase 1: Basic status and info commands ──
|
||||
run_mcc_command "health"
|
||||
run_mcc_command "list"
|
||||
run_mcc_command "inventory player list"
|
||||
|
|
@ -165,6 +166,34 @@ run_mcc_command "entity"
|
|||
run_mcc_command "/time query daytime"
|
||||
run_mcc_command "smoke_test_from_mcc_full_spectrum"
|
||||
|
||||
# ── Phase 2: Movement and look commands ──
|
||||
run_mcc_command "/tp CursorBot 0 -60 0"
|
||||
sleep 3
|
||||
run_mcc_command "look up"
|
||||
sleep 1
|
||||
run_mcc_command "look down"
|
||||
sleep 1
|
||||
run_mcc_command "look east"
|
||||
sleep 1
|
||||
|
||||
# ── Phase 3: Advanced inventory operations ──
|
||||
run_mcc_command "inventory creativegive 37 IronSword 1"
|
||||
run_mcc_command "inventory creativegive 38 GoldenApple 8"
|
||||
run_mcc_command "inventory player list"
|
||||
run_mcc_command "inventory creativeclear 38"
|
||||
run_mcc_command "inventory player list"
|
||||
|
||||
# ── Phase 4: Block placement and interaction ──
|
||||
run_server_command "execute as CursorBot at @s run fill ~1 ~ ~1 ~3 ~2 ~3 minecraft:stone"
|
||||
sleep 2
|
||||
run_server_command "execute as CursorBot at @s run setblock ~5 ~ ~5 minecraft:chest"
|
||||
sleep 1
|
||||
run_server_command "execute as CursorBot at @s run setblock ~5 ~1 ~5 minecraft:furnace"
|
||||
sleep 1
|
||||
run_server_command "execute as CursorBot at @s run setblock ~6 ~ ~5 minecraft:crafting_table"
|
||||
sleep 1
|
||||
|
||||
# ── Phase 5: Entity spawning (expanded coverage) ──
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:cow ~2 ~ ~"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:zombie ~4 ~ ~"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:creeper ~6 ~ ~"
|
||||
|
|
@ -172,41 +201,99 @@ run_server_command "execute as CursorBot at @s run summon minecraft:skeleton ~8
|
|||
run_server_command "execute as CursorBot at @s run summon minecraft:villager ~-2 ~ ~"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:allay ~-4 ~ ~"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:armor_stand ~ ~ ~2"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:item_display ~-6 ~ ~ {item:{id:\"minecraft:diamond\",count:1}}"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:spider ~10 ~ ~"
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:pig ~-8 ~ ~"
|
||||
|
||||
sleep 2
|
||||
run_mcc_command "entity"
|
||||
|
||||
# ── Phase 6: Effects and environment ──
|
||||
run_server_command "effect give CursorBot minecraft:speed 30 1"
|
||||
sleep 2
|
||||
run_mcc_command "health"
|
||||
run_server_command "effect give CursorBot minecraft:regeneration 10 1"
|
||||
sleep 2
|
||||
run_mcc_command "health"
|
||||
|
||||
# ── Phase 7: Gamemode cycling ──
|
||||
run_mcc_command "/gamemode survival"
|
||||
sleep 2
|
||||
run_mcc_command "health"
|
||||
run_mcc_command "/gamemode creative"
|
||||
sleep 2
|
||||
|
||||
# ── Phase 8: Dimension change (nether) ──
|
||||
run_server_command "execute in minecraft:the_nether run tp CursorBot 0 64 0"
|
||||
sleep 4
|
||||
run_mcc_command "health"
|
||||
run_server_command "execute in minecraft:overworld run tp CursorBot 0 -60 0"
|
||||
sleep 4
|
||||
|
||||
# ── Phase 9: Server chat and whisper ──
|
||||
run_server_command "say Hello from the server console"
|
||||
sleep 2
|
||||
run_server_command "msg CursorBot This is a private whisper"
|
||||
sleep 2
|
||||
run_mcc_command "integration_test_chat_response"
|
||||
|
||||
# ── Phase 10: Particles, sounds, and explosions ──
|
||||
run_server_command "execute as CursorBot at @s run particle minecraft:happy_villager ~ ~1 ~ 0.5 0.5 0.5 0 12 force"
|
||||
run_server_command "execute as CursorBot at @s run particle minecraft:end_rod ~ ~1 ~ 0.5 0.5 0.5 0.01 20 force"
|
||||
run_server_command "execute as CursorBot at @s run particle minecraft:explosion ~ ~1 ~ 0 0 0 0 1 force"
|
||||
run_server_command "execute as CursorBot at @s run particle minecraft:totem_of_undying ~ ~1 ~ 0.5 0.5 0.5 0.1 20 force"
|
||||
run_server_command "execute as CursorBot at @s run particle minecraft:flame ~ ~1 ~ 0.2 0.2 0.2 0.02 30 force"
|
||||
run_server_command "execute as CursorBot at @s run particle minecraft:heart ~ ~2 ~ 0.3 0.3 0.3 0 5 force"
|
||||
|
||||
run_server_command "execute as CursorBot at @s run playsound minecraft:entity.lightning_bolt.thunder master CursorBot ~ ~ ~ 1 1 0"
|
||||
run_server_command "execute as CursorBot at @s run playsound minecraft:block.note_block.bell master CursorBot ~ ~ ~ 1 1 0"
|
||||
run_server_command "execute as CursorBot at @s run playsound minecraft:entity.experience_orb.pickup master CursorBot ~ ~ ~ 1 1 0"
|
||||
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:tnt ~3 ~ ~"
|
||||
sleep 2
|
||||
run_server_command "execute as CursorBot at @s run summon minecraft:tnt ~6 ~ ~"
|
||||
|
||||
# ── Phase 11: Kill and respawn cycle ──
|
||||
run_mcc_command "/gamemode survival"
|
||||
sleep 2
|
||||
run_server_command "kill CursorBot"
|
||||
sleep 4
|
||||
run_mcc_command "respawn"
|
||||
sleep 4
|
||||
run_mcc_command "health"
|
||||
run_mcc_command "/gamemode creative"
|
||||
sleep 2
|
||||
|
||||
sleep 6
|
||||
capture_server_logs
|
||||
|
||||
# ── Assertions: MCC log ──
|
||||
assert_contains "$MCC_LOG" "Server was successfully joined." "MCC never joined the server"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > inventory player list" "Inventory command was not executed"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > entity" "Entity command was not executed"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > /gamemode creative" "Creative mode command was not executed from MCC"
|
||||
assert_contains "$MCC_LOG" "Requested Diamond x16 in slot #36" "Creative inventory give did not succeed"
|
||||
assert_contains "$MCC_LOG" "smoke_test_from_mcc_full_spectrum" "Client-originated chat was not observed"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > look up" "Look command was not executed"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > /gamemode survival" "Survival mode switch was not executed"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > respawn" "Respawn command was not executed"
|
||||
assert_contains "$MCC_LOG" "[FileInput] > health" "Health command was not executed"
|
||||
assert_contains "$MCC_LOG" "integration_test_chat_response" "Chat response test message was not observed"
|
||||
assert_not_contains "$MCC_LOG" "Please enable InventoryHandling" "Inventory handling is still disabled"
|
||||
assert_not_contains "$MCC_LOG" "Please enable EntityHandling" "Entity handling is still disabled"
|
||||
assert_not_contains "$MCC_LOG" "You must be in Creative gamemode" "Creative mode was not active when creativegive ran"
|
||||
assert_not_contains "$MCC_LOG" "Failed to load settings" "MCC failed to reload its config"
|
||||
assert_not_contains "$MCC_LOG" "NullReferenceException" "A NullReferenceException occurred during the test"
|
||||
|
||||
# ── Assertions: Server log ──
|
||||
assert_contains "$SERVER_FILE_LOG" "CursorBot joined the game" "Server never saw CursorBot join"
|
||||
assert_contains "$SERVER_FILE_LOG" "smoke_test_from_mcc_full_spectrum" "Server never received the client chat message"
|
||||
assert_contains "$SERVER_FILE_LOG" "Displaying particle minecraft:happy_villager" "Particle events were not recorded on the server"
|
||||
assert_contains "$SERVER_FILE_LOG" "Played sound minecraft:block.note_block.bell to CursorBot" "Sound events were not recorded on the server"
|
||||
assert_contains "$SERVER_FILE_LOG" "Summoned new Primed TNT" "TNT summon did not occur on the server"
|
||||
assert_contains "$SERVER_FILE_LOG" "integration_test_chat_response" "Server never received the chat response test message"
|
||||
assert_contains "$SERVER_FILE_LOG" "Hello from the server console" "Server say command was not logged"
|
||||
assert_contains "$SERVER_FILE_LOG" "Killed CursorBot" "Server kill command did not execute"
|
||||
assert_not_contains "$SERVER_FILE_LOG" "Sending unknown packet 'clientbound/minecraft:disconnect'" "Server hit the disconnect packet regression during the test"
|
||||
|
||||
cat <<EOF
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ namespace MinecraftClient.ChatBots
|
|||
[TomlInlineComment("$ChatBot.DiscordBridge.MessageSendTimeout$")]
|
||||
public int Message_Send_Timeout = 3;
|
||||
|
||||
[TomlInlineComment("$ChatBot.DiscordBridge.AllowOtherBotMessages$")]
|
||||
public bool Allow_Other_Bot_Messages = false;
|
||||
|
||||
[TomlPrecedingComment("$ChatBot.DiscordBridge.Formats$")]
|
||||
public string PrivateMessageFormat = "**[Private Message]** {username}: {message}";
|
||||
public string PublicMessageFormat = "{username}: {message}";
|
||||
|
|
@ -372,12 +375,25 @@ namespace MinecraftClient.ChatBots
|
|||
if (e.Channel.Id != Config.ChannelId)
|
||||
return;
|
||||
|
||||
if (!Config.OwnersIds.Contains(e.Author.Id))
|
||||
// Always ignore own messages to prevent loops
|
||||
if (e.Author.Id == discordBotClient.CurrentUser.Id)
|
||||
return;
|
||||
|
||||
string message = e.Message.Content.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(message) || string.IsNullOrWhiteSpace(message))
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
return;
|
||||
|
||||
// Relay messages from other bots when configured, but never process commands from them.
|
||||
// Skip relay when direction is Discord-only (Discord -> MC disabled).
|
||||
if (e.Author.IsBot)
|
||||
{
|
||||
if (Config.Allow_Other_Bot_Messages && bridgeDirection != BridgeDirection.Discord)
|
||||
SendText(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Config.OwnersIds.Contains(e.Author.Id))
|
||||
return;
|
||||
|
||||
if (bridgeDirection == BridgeDirection.Discord)
|
||||
|
|
|
|||
332
MinecraftClient/ChatBots/DiscordRpc.cs
Normal file
332
MinecraftClient/ChatBots/DiscordRpc.cs
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
using System;
|
||||
using DiscordRPC;
|
||||
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;
|
||||
|
||||
[TomlInlineComment("$ChatBot.DiscordRpc.ShowServerAddress$")]
|
||||
public bool ShowServerAddress = true;
|
||||
|
||||
[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;
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DiscordRpcClient? _rpcClient;
|
||||
private int _tickCounter;
|
||||
private int _updateIntervalTicks;
|
||||
private Timestamps? _sessionTimestamps;
|
||||
private float _lastHealth;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Config.ApplicationId))
|
||||
{
|
||||
LogToConsole(Translations.bot_DiscordRpc_missing_app_id);
|
||||
UnloadBot();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_rpcClient = new DiscordRpcClient(Config.ApplicationId.Trim())
|
||||
{
|
||||
Logger = Settings.Config.Logging.DebugMessages
|
||||
? new ConsoleLogger(LogLevel.Trace)
|
||||
: new ConsoleLogger(LogLevel.None)
|
||||
};
|
||||
|
||||
_rpcClient.OnReady += (_, e) =>
|
||||
{
|
||||
LogToConsole(string.Format(Translations.bot_DiscordRpc_connected, e.User.Username));
|
||||
};
|
||||
|
||||
_rpcClient.OnConnectionFailed += (_, e) =>
|
||||
{
|
||||
LogToConsole(string.Format(Translations.bot_DiscordRpc_connection_failed, e.FailedPipe));
|
||||
};
|
||||
|
||||
_rpcClient.Initialize();
|
||||
_updateIntervalTicks = Settings.DoubleToTick(Config.UpdateIntervalSeconds);
|
||||
|
||||
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()
|
||||
{
|
||||
if (_rpcClient is { IsDisposed: false })
|
||||
{
|
||||
_rpcClient.ClearPresence();
|
||||
_rpcClient.Dispose();
|
||||
}
|
||||
|
||||
_rpcClient = null;
|
||||
}
|
||||
|
||||
public override void AfterGameJoined()
|
||||
{
|
||||
if (Config.ShowElapsedTime)
|
||||
_sessionTimestamps = Timestamps.Now;
|
||||
|
||||
_lastHealth = Handler.GetHealth();
|
||||
_tickCounter = 0;
|
||||
SetPresence();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
_tickCounter++;
|
||||
if (_tickCounter < _updateIntervalTicks)
|
||||
return;
|
||||
|
||||
_tickCounter = 0;
|
||||
SetPresence();
|
||||
}
|
||||
|
||||
public override void OnHealthUpdate(float health, int food)
|
||||
{
|
||||
_lastHealth = health;
|
||||
}
|
||||
|
||||
public override bool OnDisconnect(DisconnectReason reason, string message)
|
||||
{
|
||||
if (_rpcClient is { IsDisposed: false })
|
||||
_rpcClient.ClearPresence();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetPresence()
|
||||
{
|
||||
if (_rpcClient is null or { IsDisposed: true })
|
||||
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
|
||||
if (Config.ShowElapsedTime && _sessionTimestamps is not null)
|
||||
presence.Timestamps = _sessionTimestamps;
|
||||
|
||||
// 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,
|
||||
Max = playerCount
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
_rpcClient.SetPresence(presence);
|
||||
}
|
||||
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;
|
||||
|
||||
string serverHost = Config.ShowServerAddress ? GetServerHost() : "Hidden";
|
||||
int serverPort = GetServerPort();
|
||||
string serverPortStr = Config.ShowServerAddress ? serverPort.ToString() : "****";
|
||||
string username = GetUsername();
|
||||
float health = Handler.GetHealth();
|
||||
int foodLevel = Handler.GetSaturation();
|
||||
Location location = GetCurrentLocation();
|
||||
string[] onlinePlayers = GetOnlinePlayers();
|
||||
int gamemode = GetGamemode();
|
||||
int protocolVersion = GetProtocolVersion();
|
||||
|
||||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dim = World.GetDimension();
|
||||
dimensionName = dim.Name ?? "Unknown";
|
||||
|
||||
// Clean up the dimension name for display
|
||||
if (dimensionName.StartsWith("minecraft:", StringComparison.Ordinal))
|
||||
dimensionName = dimensionName["minecraft:".Length..];
|
||||
|
||||
dimensionName = dimensionName switch
|
||||
{
|
||||
"overworld" => "Overworld",
|
||||
"the_nether" => "The Nether",
|
||||
"the_end" => "The End",
|
||||
_ => dimensionName
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
// World may not be available
|
||||
}
|
||||
}
|
||||
|
||||
string gamemodeStr = Config.ShowGamemode
|
||||
? gamemode switch
|
||||
{
|
||||
0 => "Survival",
|
||||
1 => "Creative",
|
||||
2 => "Adventure",
|
||||
3 => "Spectator",
|
||||
_ => "Unknown"
|
||||
}
|
||||
: "Hidden";
|
||||
|
||||
return template
|
||||
.Replace("{server_host}", serverHost)
|
||||
.Replace("{server_port}", serverPortStr)
|
||||
.Replace("{username}", username)
|
||||
.Replace("{health}", healthStr)
|
||||
.Replace("{max_health}", maxHealthStr)
|
||||
.Replace("{food}", foodStr)
|
||||
.Replace("{dimension}", dimensionName)
|
||||
.Replace("{gamemode}", gamemodeStr)
|
||||
.Replace("{x}", xStr)
|
||||
.Replace("{y}", yStr)
|
||||
.Replace("{z}", zStr)
|
||||
.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)] + "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -430,6 +430,7 @@ namespace MinecraftClient
|
|||
if (Config.ChatBot.ScriptScheduler.Enabled) { BotLoad(new ScriptScheduler()); }
|
||||
if (Config.ChatBot.TelegramBridge.Enabled) { BotLoad(new TelegramBridge()); }
|
||||
if (Config.ChatBot.ItemsCollector.Enabled) { BotLoad(new ItemsCollector()); }
|
||||
if (Config.ChatBot.DiscordRpc.Enabled) { BotLoad(new DiscordRpc()); }
|
||||
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MCC_FILE_INPUT")))
|
||||
BotLoad(new FileInputBot());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Brigadier.NET" Version="1.2.13" />
|
||||
<PackageReference Include="DiscordRichPresence" Version="1.143.0" />
|
||||
<PackageReference Include="DnsClient" Version="1.8.0" />
|
||||
<PackageReference Include="DSharpPlus" Version="4.5.1" />
|
||||
<PackageReference Include="DynamicExpresso.Core" Version="2.19.3" />
|
||||
|
|
|
|||
|
|
@ -772,7 +772,16 @@ namespace MinecraftClient {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Automatically farms crops for you (plants, breaks and bonemeals them).
|
||||
/// Looks up a localized string similar to When enabled, messages from other Discord bots in the channel will be relayed to Minecraft chat..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordBridge_AllowOtherBotMessages {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordBridge.AllowOtherBotMessages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Automatically farms cropsfor you (plants, breaks and bonemeals them).
|
||||
///Crop types available: Beetroot, Carrot, Melon, Netherwart, Pumpkin, Potato, Wheat.
|
||||
///Usage: "/farmer start" command and "/farmer stop" command.
|
||||
///NOTE: This a newly added bot, it is not perfect and was only tested in 1.19.2, there are some minor issues like not being able to bonemeal carrots/potatoes sometimes.
|
||||
|
|
@ -898,6 +907,152 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show a Discord Rich Presence status with your current Minecraft session info.
|
||||
///Setup:
|
||||
///1. Go to https://discord.com/developers/applications and log in with your Discord account. [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Your Discord Application ID..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ApplicationId {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ApplicationId", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The top line of the Rich Presence display. Supports placeholders..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_PresenceDetails {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.PresenceDetails", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The second line of the Rich Presence display. Supports placeholders..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_PresenceState {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.PresenceState", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The key of the large image asset uploaded to your Discord application..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_LargeImageKey {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.LargeImageKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tooltip text for the large image. Supports placeholders..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_LargeImageText {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.LargeImageText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The key of the small image asset uploaded to your Discord application (leave empty to hide)..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_SmallImageKey {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.SmallImageKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tooltip text for the small image. Supports placeholders..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_SmallImageText {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.SmallImageText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show the server address (host and port) in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowServerAddress {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowServerAddress", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show the player coordinates in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowCoordinates {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowCoordinates", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show health and food level in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowHealth {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowHealth", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show the current dimension in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowDimension {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowDimension", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show the current gamemode in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowGamemode {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowGamemode", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show elapsed session time in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowElapsedTime {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowElapsedTime", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show the online player count as a party size in the Discord presence..
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_ShowPlayerCount {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.ShowPlayerCount", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to How often (in seconds) to refresh the Discord presence. Minimum: 1.
|
||||
/// </summary>
|
||||
internal static string ChatBot_DiscordRpc_UpdateIntervalSeconds {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.DiscordRpc.UpdateIntervalSeconds", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Relay messages between players and servers, like a mail plugin
|
||||
///This bot can store messages when the recipients are offline, and send them when they join the server
|
||||
|
|
|
|||
|
|
@ -390,6 +390,9 @@ For Discord message formatting, check the following: https://mccteam.github.io/r
|
|||
<data name="ChatBot.DiscordBridge.Token" xml:space="preserve">
|
||||
<value>Your Discord Bot token.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordBridge.AllowOtherBotMessages" xml:space="preserve">
|
||||
<value>When enabled, messages from other Discord bots in the channel will be relayed to Minecraft chat. The bridge always ignores its own messages to prevent loops.</value>
|
||||
</data>
|
||||
<data name="ChatBot.Farmer" xml:space="preserve">
|
||||
<value>Automatically farms crops for you (plants, breaks and bonemeals them).
|
||||
Crop types available: Beetroot, Carrot, Melon, Netherwart, Pumpkin, Potato, Wheat.
|
||||
|
|
@ -828,6 +831,60 @@ If the connection to the Minecraft game server is blocked by the firewall, set E
|
|||
<data name="ChatBot.ItemsCollector" xml:space="preserve">
|
||||
<value>A Chat Bot that collects items on the ground</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc" xml:space="preserve">
|
||||
<value>Show a Discord Rich Presence status with your current Minecraft session info.
|
||||
Setup:
|
||||
1. Go to https://discord.com/developers/applications and log in with your Discord account.
|
||||
2. Click "New Application", give it a name (e.g. "MCC") and confirm.
|
||||
3. On the application page, copy the "Application ID" and paste it in the "ApplicationId" field below.
|
||||
4. (Optional) Go to "Rich Presence" -> "Art Assets" to upload custom images for LargeImageKey/SmallImageKey.
|
||||
Note: This does NOT require a Bot Token, only an Application ID. Discord must be running on the same machine as MCC.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ApplicationId" xml:space="preserve">
|
||||
<value>Your Discord Application ID. Create one at https://discord.com/developers/applications</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.PresenceDetails" xml:space="preserve">
|
||||
<value>The top line of the Rich Presence display. Supports placeholders.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.PresenceState" xml:space="preserve">
|
||||
<value>The second line of the Rich Presence display. Supports placeholders.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.LargeImageKey" xml:space="preserve">
|
||||
<value>The key of the large image asset uploaded to your Discord application.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.LargeImageText" xml:space="preserve">
|
||||
<value>Tooltip text for the large image. Supports placeholders.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.SmallImageKey" xml:space="preserve">
|
||||
<value>The key of the small image asset uploaded to your Discord application (leave empty to hide).</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.SmallImageText" xml:space="preserve">
|
||||
<value>Tooltip text for the small image. Supports placeholders.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowServerAddress" xml:space="preserve">
|
||||
<value>Show the server address (host and port) in the Discord presence. When disabled, {server_host} and {server_port} are masked.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowCoordinates" xml:space="preserve">
|
||||
<value>Show the player coordinates in the Discord presence. When disabled, {x}, {y}, {z} are masked.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowHealth" xml:space="preserve">
|
||||
<value>Show health and food level in the Discord presence. When disabled, {health}, {max_health}, {food} are masked.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowDimension" xml:space="preserve">
|
||||
<value>Show the current dimension in the Discord presence. When disabled, {dimension} is masked.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowGamemode" xml:space="preserve">
|
||||
<value>Show the current gamemode in the Discord presence. When disabled, {gamemode} is masked.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowElapsedTime" xml:space="preserve">
|
||||
<value>Show elapsed session time in the Discord presence.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.ShowPlayerCount" xml:space="preserve">
|
||||
<value>Show the online player count as a party size in the Discord presence.</value>
|
||||
</data>
|
||||
<data name="ChatBot.DiscordRpc.UpdateIntervalSeconds" xml:space="preserve">
|
||||
<value>How often (in seconds) to refresh the Discord presence. Minimum: 1</value>
|
||||
</data>
|
||||
<data name="ChatBot.WebSocketBot" xml:space="preserve">
|
||||
<value>Remotely control the client using Web Sockets.\n# This is useful if you want to implement an application that can remotely and asynchronously execute procedures in MCC.\n# Example implementation written in JavaScript: https://github.com/milutinke/MCC.js.git\n# The protocol specification will be available in the documentation soon.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -1095,6 +1095,69 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please provide a valid Discord Application ID!.
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_missing_app_id {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.missing_app_id", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connected to Discord as {0}.
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_connected {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.connected", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Failed to connect to Discord (pipe {0}). Is Discord running?.
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_connection_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.connection_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Discord Rich Presence initialized successfully..
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_initialized {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.initialized", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Failed to initialize Discord Rich Presence: {0}.
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_init_error {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.init_error", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error updating Discord presence: {0}.
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_update_error {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.update_error", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid update interval, must be at least 1 second. Using default of 10 seconds..
|
||||
/// </summary>
|
||||
internal static string bot_DiscordRpc_invalid_interval {
|
||||
get {
|
||||
return ResourceManager.GetString("bot.DiscordRpc.invalid_interval", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The bot is already farming!.
|
||||
/// </summary>
|
||||
|
|
@ -2089,6 +2152,15 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DiscordRpc.
|
||||
/// </summary>
|
||||
internal static string botname_DiscordRpc {
|
||||
get {
|
||||
return ResourceManager.GetString("botname.DiscordRpc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Farmer.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -463,6 +463,27 @@ cooldown: {6}</value>
|
|||
<data name="bot.DiscordBridge.unknown_error" xml:space="preserve">
|
||||
<value>An unknown error has occured!</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.missing_app_id" xml:space="preserve">
|
||||
<value>Please provide a valid Discord Application ID! Get one at https://discord.com/developers/applications</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.connected" xml:space="preserve">
|
||||
<value>Connected to Discord as {0}</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.connection_failed" xml:space="preserve">
|
||||
<value>Failed to connect to Discord (pipe {0}). Is Discord running?</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.initialized" xml:space="preserve">
|
||||
<value>Discord Rich Presence initialized successfully.</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.init_error" xml:space="preserve">
|
||||
<value>Failed to initialize Discord Rich Presence: {0}</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.update_error" xml:space="preserve">
|
||||
<value>Error updating Discord presence: {0}</value>
|
||||
</data>
|
||||
<data name="bot.DiscordRpc.invalid_interval" xml:space="preserve">
|
||||
<value>Invalid update interval, must be at least 1 second. Using default of 10 seconds.</value>
|
||||
</data>
|
||||
<data name="bot.farmer.already_running" xml:space="preserve">
|
||||
<value>The bot is already farming!</value>
|
||||
</data>
|
||||
|
|
@ -770,6 +791,9 @@ Add the ID of this chat to "Authorized_Chat_Ids" field in the configuration file
|
|||
<data name="botname.DiscordBridge" xml:space="preserve">
|
||||
<value>DiscordBridge</value>
|
||||
</data>
|
||||
<data name="botname.DiscordRpc" xml:space="preserve">
|
||||
<value>DiscordRpc</value>
|
||||
</data>
|
||||
<data name="botname.Farmer" xml:space="preserve">
|
||||
<value>Farmer</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -1466,6 +1466,13 @@ namespace MinecraftClient
|
|||
ChatBots.ItemsCollector.Config.OnSettingUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
[TomlPrecedingComment("$ChatBot.DiscordRpc$")]
|
||||
public ChatBots.DiscordRpc.Configs DiscordRpc
|
||||
{
|
||||
get { return ChatBots.DiscordRpc.Config; }
|
||||
set { ChatBots.DiscordRpc.Config = value; ChatBots.DiscordRpc.Config.OnSettingUpdate(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue