mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Add FileInputBot for non-interactive debugging and fix NbtToString crash
FileInputBot (ChatBots/FileInputBot.cs): - New ChatBot that monitors a text file (default: mcc_input.txt) for commands, enabling MCC control from Cursor Shell or any non-interactive environment where stdin is not available - Activated by setting MCC_FILE_INPUT env var (e.g. MCC_FILE_INPUT=1) - Polls every ~500ms for new lines appended to the file - Lines starting with "/" are sent as server chat/commands - Other lines are executed as MCC internal commands (same as console input) - File path overridable via MCC_INPUT_FILE env var McClient.cs: - Load FileInputBot when MCC_FILE_INPUT environment variable is set ChatParser.cs - NbtToString: - Fix InvalidCastException when NBT "text" or nameless root tag values are Int32 instead of String (happens with 1.20.6 SystemChat packets containing numeric values in the chat component tree) - Replace direct (string) casts with ?.ToString() ?? string.Empty Made-with: Cursor
This commit is contained in:
parent
8eac21b4a4
commit
967f67190c
3 changed files with 110 additions and 6 deletions
105
MinecraftClient/ChatBots/FileInputBot.cs
Normal file
105
MinecraftClient/ChatBots/FileInputBot.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MinecraftClient.CommandHandler;
|
||||
using MinecraftClient.Scripting;
|
||||
|
||||
namespace MinecraftClient.ChatBots
|
||||
{
|
||||
/// <summary>
|
||||
/// Debug-only ChatBot that monitors a text file for commands.
|
||||
/// Write lines to the file from any external tool (e.g. Cursor Shell)
|
||||
/// and this bot will execute them as MCC internal commands.
|
||||
///
|
||||
/// Usage from Cursor Shell:
|
||||
/// Add-Content mcc_input.txt "inventory"
|
||||
/// Add-Content mcc_input.txt "send /give @s diamond_sword 1"
|
||||
///
|
||||
/// Lines starting with "/" are sent as server chat; others are treated
|
||||
/// as MCC internal commands (same as typing in the MCC console).
|
||||
/// </summary>
|
||||
public class FileInputBot : ChatBot
|
||||
{
|
||||
private const string BotName = "FileInput";
|
||||
private string _filePath = string.Empty;
|
||||
private long _lastPosition;
|
||||
private int _tickCounter;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_filePath = Path.GetFullPath(
|
||||
Environment.GetEnvironmentVariable("MCC_INPUT_FILE") ?? "mcc_input.txt");
|
||||
|
||||
if (File.Exists(_filePath))
|
||||
_lastPosition = new FileInfo(_filePath).Length;
|
||||
else
|
||||
File.WriteAllText(_filePath, "");
|
||||
|
||||
LogToConsole(BotName, $"Watching: {_filePath}");
|
||||
LogToConsole(BotName, "Write commands to this file to execute them.");
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
// Poll every ~500ms (Update is called every ~100ms)
|
||||
if (++_tickCounter < 5)
|
||||
return;
|
||||
_tickCounter = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (!File.Exists(_filePath))
|
||||
return;
|
||||
|
||||
var info = new FileInfo(_filePath);
|
||||
if (info.Length <= _lastPosition)
|
||||
return;
|
||||
|
||||
string newContent;
|
||||
using (var fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
fs.Seek(_lastPosition, SeekOrigin.Begin);
|
||||
using var reader = new StreamReader(fs);
|
||||
newContent = reader.ReadToEnd();
|
||||
}
|
||||
_lastPosition = info.Length;
|
||||
|
||||
foreach (var rawLine in newContent.Split('\n'))
|
||||
{
|
||||
var line = rawLine.Trim();
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
|
||||
LogToConsole(BotName, $"> {line}");
|
||||
|
||||
if (line.StartsWith("/"))
|
||||
{
|
||||
SendText(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
CmdResult result = new();
|
||||
if (PerformInternalCommand(line, ref result))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(result.ToString()))
|
||||
LogToConsole(BotName, result.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not an internal command — send as chat
|
||||
SendText(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// File may be temporarily locked by the writer
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToConsole(BotName, $"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -425,8 +425,8 @@ 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()); }
|
||||
//Add your ChatBot here by uncommenting and adapting
|
||||
//BotLoad(new ChatBots.YourBot());
|
||||
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MCC_FILE_INPUT")))
|
||||
BotLoad(new FileInputBot());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -510,8 +510,7 @@ namespace MinecraftClient.Protocol.Message
|
|||
{
|
||||
if (nbt.Count == 1 && nbt.TryGetValue("", out object? rootMessage))
|
||||
{
|
||||
// Nameless root tag
|
||||
return (string)rootMessage;
|
||||
return rootMessage?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
string message = string.Empty;
|
||||
|
|
@ -526,7 +525,7 @@ namespace MinecraftClient.Protocol.Message
|
|||
{
|
||||
case "text":
|
||||
{
|
||||
message = (string)value;
|
||||
message = value?.ToString() ?? string.Empty;
|
||||
}
|
||||
break;
|
||||
case "extra":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue