mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Fix sign command
This commit is contained in:
commit
0a43c871ba
3 changed files with 587 additions and 61 deletions
561
MinecraftClient/Protocol/Handlers/Packet/s2c/DeclareCommands.cs
Normal file
561
MinecraftClient/Protocol/Handlers/Packet/s2c/DeclareCommands.cs
Normal file
|
|
@ -0,0 +1,561 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MinecraftClient.Protocol.Handlers.packet.s2c
|
||||||
|
{
|
||||||
|
internal static class DeclareCommands
|
||||||
|
{
|
||||||
|
private static int RootIdx;
|
||||||
|
private static CommandNode[] Nodes = Array.Empty<CommandNode>();
|
||||||
|
|
||||||
|
public static void Read(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
int count = dataTypes.ReadNextVarInt(packetData);
|
||||||
|
Nodes = new CommandNode[count];
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
byte flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
|
||||||
|
int childCount = dataTypes.ReadNextVarInt(packetData);
|
||||||
|
int[] childs = new int[childCount];
|
||||||
|
for (int j = 0; j < childCount; ++j)
|
||||||
|
childs[j] = dataTypes.ReadNextVarInt(packetData);
|
||||||
|
|
||||||
|
int redirectNode = ((flags & 0x08) > 0) ? dataTypes.ReadNextVarInt(packetData) : -1;
|
||||||
|
|
||||||
|
string? name = ((flags & 0x03) == 1 || (flags & 0x03) == 2) ? dataTypes.ReadNextString(packetData) : null;
|
||||||
|
|
||||||
|
int paserId = ((flags & 0x03) == 2) ? dataTypes.ReadNextVarInt(packetData) : -1;
|
||||||
|
Paser? paser = null;
|
||||||
|
if ((flags & 0x03) == 2)
|
||||||
|
{
|
||||||
|
paser = paserId switch
|
||||||
|
{
|
||||||
|
1 => new PaserFloat(dataTypes, packetData),
|
||||||
|
2 => new PaserDouble(dataTypes, packetData),
|
||||||
|
3 => new PaserInteger(dataTypes, packetData),
|
||||||
|
4 => new PaserLong(dataTypes, packetData),
|
||||||
|
5 => new PaserString(dataTypes, packetData),
|
||||||
|
6 => new PaserEntity(dataTypes, packetData),
|
||||||
|
8 => new PaserBlockPos(dataTypes, packetData),
|
||||||
|
9 => new PaserColumnPos(dataTypes, packetData),
|
||||||
|
10 => new PaserVec3(dataTypes, packetData),
|
||||||
|
11 => new PaserVec2(dataTypes, packetData),
|
||||||
|
18 => new PaserMessage(dataTypes, packetData),
|
||||||
|
27 => new PaserRotation(dataTypes, packetData),
|
||||||
|
29 => new PaserScoreHolder(dataTypes, packetData),
|
||||||
|
43 => new PaserResourceOrTag(dataTypes, packetData),
|
||||||
|
44 => new PaserResource(dataTypes, packetData),
|
||||||
|
_ => new PaserEmpty(dataTypes, packetData),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
string? suggestionsType = ((flags & 0x10) > 0) ? dataTypes.ReadNextString(packetData) : null;
|
||||||
|
|
||||||
|
Nodes[i] = new(flags, childs, redirectNode, name, paser, suggestionsType);
|
||||||
|
}
|
||||||
|
RootIdx = dataTypes.ReadNextVarInt(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Tuple<string, string>> CollectSignArguments(string command)
|
||||||
|
{
|
||||||
|
List<Tuple<string, string>> needSigned = new();
|
||||||
|
CollectSignArguments(RootIdx, command, needSigned);
|
||||||
|
return needSigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CollectSignArguments(int NodeIdx, string command, List<Tuple<string, string>> arguments)
|
||||||
|
{
|
||||||
|
CommandNode node = Nodes[NodeIdx];
|
||||||
|
string last_arg = command;
|
||||||
|
switch (node.Flags & 0x03)
|
||||||
|
{
|
||||||
|
case 0: // root
|
||||||
|
break;
|
||||||
|
case 1: // literal
|
||||||
|
{
|
||||||
|
string[] arg = command.Split(' ', 2, StringSplitOptions.None);
|
||||||
|
if (!(arg.Length == 2 && node.Name! == arg[0]))
|
||||||
|
return;
|
||||||
|
last_arg = arg[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // argument
|
||||||
|
{
|
||||||
|
int argCnt = (node.Paser == null) ? 1 : node.Paser.GetArgCnt();
|
||||||
|
string[] arg = command.Split(' ', argCnt + 1, StringSplitOptions.None);
|
||||||
|
if ((node.Flags & 0x04) > 0)
|
||||||
|
{
|
||||||
|
if (node.Paser != null && node.Paser.GetName() == "minecraft:message")
|
||||||
|
arguments.Add(new(node.Name!, command));
|
||||||
|
}
|
||||||
|
if (!(arg.Length == argCnt + 1))
|
||||||
|
return;
|
||||||
|
last_arg = arg[^1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Nodes[NodeIdx].RedirectNode >= 0)
|
||||||
|
NodeIdx = Nodes[NodeIdx].RedirectNode;
|
||||||
|
|
||||||
|
foreach (int childIdx in Nodes[NodeIdx].Clildren)
|
||||||
|
CollectSignArguments(childIdx, last_arg, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CommandNode
|
||||||
|
{
|
||||||
|
public byte Flags;
|
||||||
|
public int[] Clildren;
|
||||||
|
public int RedirectNode;
|
||||||
|
public string? Name;
|
||||||
|
public Paser? Paser;
|
||||||
|
public string? SuggestionsType;
|
||||||
|
|
||||||
|
|
||||||
|
public CommandNode(byte Flags,
|
||||||
|
int[] Clildren,
|
||||||
|
int RedirectNode = -1,
|
||||||
|
string? Name = null,
|
||||||
|
Paser? Paser = null,
|
||||||
|
string? SuggestionsType = null)
|
||||||
|
{
|
||||||
|
this.Flags = Flags;
|
||||||
|
this.Clildren = Clildren;
|
||||||
|
this.RedirectNode = RedirectNode;
|
||||||
|
this.Name = Name;
|
||||||
|
this.Paser = Paser;
|
||||||
|
this.SuggestionsType = SuggestionsType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class Paser
|
||||||
|
{
|
||||||
|
public abstract string GetName();
|
||||||
|
|
||||||
|
public abstract int GetArgCnt();
|
||||||
|
|
||||||
|
public abstract bool Check(string text);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserEmpty : Paser
|
||||||
|
{
|
||||||
|
|
||||||
|
public PaserEmpty(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserFloat : Paser
|
||||||
|
{
|
||||||
|
private byte Flags;
|
||||||
|
private float Min = float.MinValue, Max = float.MaxValue;
|
||||||
|
|
||||||
|
public PaserFloat(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
if ((Flags & 0x01) > 0)
|
||||||
|
Min = dataTypes.ReadNextFloat(packetData);
|
||||||
|
if ((Flags & 0x02) > 0)
|
||||||
|
Max = dataTypes.ReadNextFloat(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "brigadier:float";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserDouble : Paser
|
||||||
|
{
|
||||||
|
private byte Flags;
|
||||||
|
private double Min = double.MinValue, Max = double.MaxValue;
|
||||||
|
|
||||||
|
public PaserDouble(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
if ((Flags & 0x01) > 0)
|
||||||
|
Min = dataTypes.ReadNextDouble(packetData);
|
||||||
|
if ((Flags & 0x02) > 0)
|
||||||
|
Max = dataTypes.ReadNextDouble(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "brigadier:double";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserInteger : Paser
|
||||||
|
{
|
||||||
|
private byte Flags;
|
||||||
|
private int Min = int.MinValue, Max = int.MaxValue;
|
||||||
|
|
||||||
|
public PaserInteger(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
if ((Flags & 0x01) > 0)
|
||||||
|
Min = dataTypes.ReadNextInt(packetData);
|
||||||
|
if ((Flags & 0x02) > 0)
|
||||||
|
Max = dataTypes.ReadNextInt(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "brigadier:integer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserLong : Paser
|
||||||
|
{
|
||||||
|
private byte Flags;
|
||||||
|
private long Min = long.MinValue, Max = long.MaxValue;
|
||||||
|
|
||||||
|
public PaserLong(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
if ((Flags & 0x01) > 0)
|
||||||
|
Min = dataTypes.ReadNextLong(packetData);
|
||||||
|
if ((Flags & 0x02) > 0)
|
||||||
|
Max = dataTypes.ReadNextLong(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "brigadier:long";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserString : Paser
|
||||||
|
{
|
||||||
|
private StringType Type;
|
||||||
|
|
||||||
|
private enum StringType { SINGLE_WORD, QUOTABLE_PHRASE, GREEDY_PHRASE };
|
||||||
|
|
||||||
|
public PaserString(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Type = (StringType)dataTypes.ReadNextVarInt(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "brigadier:string";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserEntity : Paser
|
||||||
|
{
|
||||||
|
private byte Flags;
|
||||||
|
|
||||||
|
public PaserEntity(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:entity";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserBlockPos : Paser
|
||||||
|
{
|
||||||
|
|
||||||
|
public PaserBlockPos(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:block_pos";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserColumnPos : Paser
|
||||||
|
{
|
||||||
|
|
||||||
|
public PaserColumnPos(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:column_pos";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserVec3 : Paser
|
||||||
|
{
|
||||||
|
|
||||||
|
public PaserVec3(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:vec3";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserVec2 : Paser
|
||||||
|
{
|
||||||
|
|
||||||
|
public PaserVec2(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:vec2";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserRotation : Paser
|
||||||
|
{
|
||||||
|
|
||||||
|
public PaserRotation(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:rotation";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserMessage : Paser
|
||||||
|
{
|
||||||
|
public PaserMessage(DataTypes dataTypes, Queue<byte> packetData) { }
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:message";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserScoreHolder : Paser
|
||||||
|
{
|
||||||
|
private byte Flags;
|
||||||
|
|
||||||
|
public PaserScoreHolder(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Flags = dataTypes.ReadNextByte(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:score_holder";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserRange : Paser
|
||||||
|
{
|
||||||
|
private bool Decimals;
|
||||||
|
|
||||||
|
public PaserRange(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Decimals = dataTypes.ReadNextBool(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:range";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserResourceOrTag : Paser
|
||||||
|
{
|
||||||
|
private string Registry;
|
||||||
|
|
||||||
|
public PaserResourceOrTag(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Registry = dataTypes.ReadNextString(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:resource_or_tag";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PaserResource : Paser
|
||||||
|
{
|
||||||
|
private string Registry;
|
||||||
|
|
||||||
|
public PaserResource(DataTypes dataTypes, Queue<byte> packetData)
|
||||||
|
{
|
||||||
|
Registry = dataTypes.ReadNextString(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Check(string text)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetArgCnt()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetName()
|
||||||
|
{
|
||||||
|
return "minecraft:resource";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ using MinecraftClient.Mapping;
|
||||||
using MinecraftClient.Mapping.BlockPalettes;
|
using MinecraftClient.Mapping.BlockPalettes;
|
||||||
using MinecraftClient.Mapping.EntityPalettes;
|
using MinecraftClient.Mapping.EntityPalettes;
|
||||||
using MinecraftClient.Protocol.Handlers.Forge;
|
using MinecraftClient.Protocol.Handlers.Forge;
|
||||||
|
using MinecraftClient.Protocol.Handlers.packet.s2c;
|
||||||
using MinecraftClient.Protocol.Handlers.PacketPalettes;
|
using MinecraftClient.Protocol.Handlers.PacketPalettes;
|
||||||
using MinecraftClient.Protocol.Keys;
|
using MinecraftClient.Protocol.Keys;
|
||||||
using MinecraftClient.Protocol.Message;
|
using MinecraftClient.Protocol.Message;
|
||||||
|
|
@ -450,6 +451,10 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PacketTypesIn.DeclareCommands:
|
||||||
|
if (protocolVersion >= MC_1_19_Version)
|
||||||
|
DeclareCommands.Read(dataTypes, packetData);
|
||||||
|
break;
|
||||||
case PacketTypesIn.ChatMessage:
|
case PacketTypesIn.ChatMessage:
|
||||||
int messageType = 0;
|
int messageType = 0;
|
||||||
|
|
||||||
|
|
@ -2239,57 +2244,6 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The signable argument names and their values from command
|
|
||||||
/// Signature will used in Vanilla's say, me, msg, teammsg, ban, banip, and kick commands.
|
|
||||||
/// https://gist.github.com/kennytv/ed783dd244ca0321bbd882c347892874#signed-command-arguments
|
|
||||||
/// You can find all the commands that need to be signed by searching for "MessageArgumentType.getSignedMessage" in the source code.
|
|
||||||
/// Don't forget to handle the redirected commands, e.g. /tm, /w
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command">Command</param>
|
|
||||||
/// <returns> List< Argument Name, Argument Value > </returns>
|
|
||||||
private List<Tuple<string, string>>? CollectCommandArguments(string command)
|
|
||||||
{
|
|
||||||
if (!isOnlineMode || !Config.Signature.SignMessageInCommand)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
List<Tuple<string, string>> needSigned = new();
|
|
||||||
|
|
||||||
string[] argStage1 = command.Split(' ', 2, StringSplitOptions.None);
|
|
||||||
if (argStage1.Length == 2)
|
|
||||||
{
|
|
||||||
/* /me <action>
|
|
||||||
/say <message>
|
|
||||||
/teammsg <message>
|
|
||||||
/tm <message> */
|
|
||||||
if (argStage1[0] == "me")
|
|
||||||
needSigned.Add(new("action", argStage1[1]));
|
|
||||||
else if (argStage1[0] == "say" || argStage1[0] == "teammsg" || argStage1[0] == "tm")
|
|
||||||
needSigned.Add(new("message", argStage1[1]));
|
|
||||||
else if (argStage1[0] == "msg" || argStage1[0] == "tell" || argStage1[0] == "w" ||
|
|
||||||
argStage1[0] == "ban" || argStage1[0] == "ban-ip" || argStage1[0] == "kick")
|
|
||||||
{
|
|
||||||
/* /msg <targets> <message>
|
|
||||||
/tell <targets> <message>
|
|
||||||
/w <targets> <message>
|
|
||||||
/ban <target> [<reason>]
|
|
||||||
/ban-ip <target> [<reason>]
|
|
||||||
/kick <target> [<reason>] */
|
|
||||||
string[] argStage2 = argStage1[1].Split(' ', 2, StringSplitOptions.None);
|
|
||||||
if (argStage2.Length == 2)
|
|
||||||
{
|
|
||||||
if (argStage1[0] == "msg" || argStage1[0] == "tell" || argStage1[0] == "w")
|
|
||||||
needSigned.Add(new("message", argStage2[1]));
|
|
||||||
else if (argStage1[0] == "ban" || argStage1[0] == "ban-ip" || argStage1[0] == "kick")
|
|
||||||
needSigned.Add(new("reason", argStage2[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return needSigned;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a chat command to the server - 1.19 and above
|
/// Send a chat command to the server - 1.19 and above
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -2320,8 +2274,10 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
DateTimeOffset timeNow = DateTimeOffset.UtcNow;
|
DateTimeOffset timeNow = DateTimeOffset.UtcNow;
|
||||||
fields.AddRange(dataTypes.GetLong(timeNow.ToUnixTimeMilliseconds()));
|
fields.AddRange(dataTypes.GetLong(timeNow.ToUnixTimeMilliseconds()));
|
||||||
|
|
||||||
List<Tuple<string, string>>? needSigned =
|
List<Tuple<string, string>>? needSigned = null; // List< Argument Name, Argument Value >
|
||||||
playerKeyPair != null ? CollectCommandArguments(command) : null; // List< Argument Name, Argument Value >
|
if (playerKeyPair != null && isOnlineMode && Config.Signature.SignMessageInCommand && protocolVersion >= MC_1_19_Version)
|
||||||
|
needSigned = DeclareCommands.CollectSignArguments(command);
|
||||||
|
|
||||||
if (needSigned == null || needSigned!.Count == 0)
|
if (needSigned == null || needSigned!.Count == 0)
|
||||||
{
|
{
|
||||||
fields.AddRange(dataTypes.GetLong(0)); // Salt: Long
|
fields.AddRange(dataTypes.GetLong(0)); // Salt: Long
|
||||||
|
|
@ -2333,12 +2289,12 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
byte[] salt = GenerateSalt();
|
byte[] salt = GenerateSalt();
|
||||||
fields.AddRange(salt); // Salt: Long
|
fields.AddRange(salt); // Salt: Long
|
||||||
fields.AddRange(dataTypes.GetVarInt(needSigned.Count)); // Signature Length: VarInt
|
fields.AddRange(dataTypes.GetVarInt(needSigned.Count)); // Signature Length: VarInt
|
||||||
foreach (var argument in needSigned)
|
foreach ((string argName, string message) in needSigned)
|
||||||
{
|
{
|
||||||
fields.AddRange(dataTypes.GetString(argument.Item1)); // Argument name: String
|
fields.AddRange(dataTypes.GetString(argName)); // Argument name: String
|
||||||
byte[] sign = (protocolVersion >= MC_1_19_2_Version) ?
|
byte[] sign = (protocolVersion >= MC_1_19_2_Version) ?
|
||||||
playerKeyPair!.PrivateKey.SignMessage(argument.Item2, uuid, timeNow, ref salt, acknowledgment!.lastSeen) :
|
playerKeyPair!.PrivateKey.SignMessage(message, uuid, timeNow, ref salt, acknowledgment!.lastSeen) :
|
||||||
playerKeyPair!.PrivateKey.SignMessage(argument.Item2, uuid, timeNow, ref salt);
|
playerKeyPair!.PrivateKey.SignMessage(message, uuid, timeNow, ref salt);
|
||||||
fields.AddRange(dataTypes.GetVarInt(sign.Length)); // Signature length: VarInt
|
fields.AddRange(dataTypes.GetVarInt(sign.Length)); // Signature length: VarInt
|
||||||
fields.AddRange(sign); // Signature: Byte Array
|
fields.AddRange(sign); // Signature: Byte Array
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,20 @@ namespace MinecraftClient.Protocol
|
||||||
/// <returns>Returns the translated text</returns>
|
/// <returns>Returns the translated text</returns>
|
||||||
public static string ParseSignedChat(ChatMessage message, List<string>? links = null)
|
public static string ParseSignedChat(ChatMessage message, List<string>? links = null)
|
||||||
{
|
{
|
||||||
string chatContent = (Config.Signature.ShowModifiedChat && message.unsignedContent != null) ? message.unsignedContent : message.content;
|
|
||||||
string content = ParseText(chatContent, links);
|
|
||||||
if (string.IsNullOrEmpty(content))
|
|
||||||
content = chatContent;
|
|
||||||
string sender = message.displayName!;
|
string sender = message.displayName!;
|
||||||
|
string content;
|
||||||
|
if (Config.Signature.ShowModifiedChat && message.unsignedContent != null)
|
||||||
|
{
|
||||||
|
content = ParseText(message.unsignedContent!);
|
||||||
|
if (string.IsNullOrEmpty(content))
|
||||||
|
content = message.unsignedContent!;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content = message.isJson ? ParseText(message.content) : message.content;
|
||||||
|
if (string.IsNullOrEmpty(content))
|
||||||
|
content = message.content!;
|
||||||
|
}
|
||||||
|
|
||||||
string text;
|
string text;
|
||||||
List<string> usingData = new();
|
List<string> usingData = new();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue