Add support for Minecraft Settings

- Add Minecraft vanilla settings from Settings screen
 - These settings are sent to server when joining
 - Allows to customize skin layers shown to other players
 - Most other settings are ignored by servers
 - Update language file from 1.9 to 1.10 version
 - Minor aesthetic changes in INI file comments

Suggestion by TNT-UP in issue #161 and Splodger1 in MC Forum.
This commit is contained in:
ORelio 2016-08-26 12:19:25 +02:00
parent b1d4f85b23
commit 61ce935c63
5 changed files with 192 additions and 38 deletions

View file

@ -370,6 +370,15 @@ namespace MinecraftClient
{
if (!String.IsNullOrWhiteSpace(Settings.BrandInfo))
handler.SendBrandInfo(Settings.BrandInfo.Trim());
if (Settings.MCSettings_Enabled)
handler.SendClientSettings(
Settings.MCSettings_Locale,
Settings.MCSettings_RenderDistance,
Settings.MCSettings_Difficulty,
Settings.MCSettings_ChatMode,
Settings.MCSettings_ChatColors,
Settings.MCSettings_Skin_All,
Settings.MCSettings_MainHand);
foreach (ChatBot bot in bots)
bot.AfterGameJoined();
}

View file

@ -626,6 +626,11 @@ namespace MinecraftClient.Protocol.Handlers
return false; //Only supported since MC 1.7
}
public bool SendClientSettings(string language, byte viewDistance, byte difficulty, byte chatMode, bool chatColors, byte skinParts, byte mainHand)
{
return false; //Currently not implemented
}
public bool SendLocationUpdate(Location location, bool onGround)
{
return false; //Currently not implemented

View file

@ -1469,6 +1469,42 @@ namespace MinecraftClient.Protocol.Handlers
return SendPluginChannelPacket("MC|Brand", getString(brandInfo));
}
/// <summary>
/// Inform the server of the client's Minecraft settings
/// </summary>
/// <param name="language">Client language eg en_US</param>
/// <param name="viewDistance">View distance, in chunks</param>
/// <param name="difficulty">Game difficulty (client-side...)</param>
/// <param name="chatMode">Chat mode (allows muting yourself)</param>
/// <param name="chatColors">Show chat colors</param>
/// <param name="skinParts">Show skin layers</param>
/// <param name="mainHand">1.9+ main hand</param>
/// <returns>True if client settings were successfully sent</returns>
public bool SendClientSettings(string language, byte viewDistance, byte difficulty, byte chatMode, bool chatColors, byte skinParts, byte mainHand)
{
try
{
List<byte> fields = new List<byte>();
fields.AddRange(getString(language));
fields.Add(viewDistance);
fields.AddRange(protocolversion >= MC19Version
? getVarInt(chatMode)
: new byte[] { chatMode });
fields.Add(chatColors ? (byte)1 : (byte)0);
if (protocolversion < MC18Version)
{
fields.Add(difficulty);
fields.Add((byte)(skinParts & 0x1)); //show cape
}
else fields.Add(skinParts);
if (protocolversion >= MC19Version)
fields.AddRange(getVarInt(mainHand));
SendPacket(protocolversion >= MC19Version ? 0x04 : 0x15, fields);
}
catch (SocketException) { }
return false;
}
/// <summary>
/// Send a location update to the server
/// </summary>

View file

@ -20,14 +20,12 @@ namespace MinecraftClient.Protocol
/// Start the login procedure once connected to the server
/// </summary>
/// <returns>True if login was successful</returns>
bool Login();
/// <summary>
/// Disconnect from the server
/// </summary>
/// <param name="message">Reason</param>
void Disconnect();
/// <summary>
@ -35,14 +33,12 @@ namespace MinecraftClient.Protocol
/// </summary>
/// <param name="message">Text to send</param>
/// <returns>True if successfully sent</returns>
bool SendChatMessage(string message);
/// <summary>
/// Allow to respawn after death
/// </summary>
/// <returns>True if packet successfully sent</returns>
bool SendRespawnPacket();
/// <summary>
@ -50,15 +46,26 @@ namespace MinecraftClient.Protocol
/// </summary>
/// <param name="brandInfo">Client string describing the client</param>
/// <returns>True if brand info was successfully sent</returns>
bool SendBrandInfo(string brandInfo);
/// <summary>
/// Inform the server of the client's Minecraft settings
/// </summary>
/// <param name="language">Client language eg en_US</param>
/// <param name="viewDistance">View distance, in chunks</param>
/// <param name="difficulty">Game difficulty (client-side...)</param>
/// <param name="chatMode">Chat mode (allows muting yourself)</param>
/// <param name="chatColors">Show chat colors</param>
/// <param name="skinParts">Show skin layers</param>
/// <param name="mainHand">1.9+ main hand</param>
/// <returns>True if client settings were successfully sent</returns>
bool SendClientSettings(string language, byte viewDistance, byte difficulty, byte chatMode, bool chatColors, byte skinParts, byte mainHand);
/// <summary>
/// Send a location update telling that we moved to that location
/// </summary>
/// <param name="location">The new location</param>
/// <returns>True if packet was successfully sent</returns>
bool SendLocationUpdate(Location location, bool onGround);
/// <summary>
@ -68,7 +75,6 @@ namespace MinecraftClient.Protocol
/// <param name="channel">Channel to send packet on</param>
/// <param name="data">packet Data</param>
/// <returns>True if message was successfully sent</returns>
bool SendPluginChannelPacket(string channel, byte[] data);
}
}

View file

@ -39,9 +39,40 @@ namespace MinecraftClient
public static string ProxyUsername = "";
public static string ProxyPassword = "";
//Minecraft Settings
public static bool MCSettings_Enabled = true;
public static string MCSettings_Locale = "en_US";
public static byte MCSettings_Difficulty = 0;
public static byte MCSettings_RenderDistance = 8;
public static byte MCSettings_ChatMode = 0;
public static bool MCSettings_ChatColors = true;
public static byte MCSettings_MainHand = 0;
public static bool MCSettings_Skin_Hat = true;
public static bool MCSettings_Skin_Cape = true;
public static bool MCSettings_Skin_Jacket = false;
public static bool MCSettings_Skin_Sleeve_Left = false;
public static bool MCSettings_Skin_Sleeve_Right = false;
public static bool MCSettings_Skin_Pants_Left = false;
public static bool MCSettings_Skin_Pants_Right = false;
public static byte MCSettings_Skin_All
{
get
{
return (byte) (
((MCSettings_Skin_Cape ? 1 : 0) << 0)
| ((MCSettings_Skin_Jacket ? 1 : 0) << 1)
| ((MCSettings_Skin_Sleeve_Left ? 1 : 0) << 2)
| ((MCSettings_Skin_Sleeve_Right ? 1 : 0) << 3)
| ((MCSettings_Skin_Pants_Left ? 1 : 0) << 4)
| ((MCSettings_Skin_Pants_Right ? 1 : 0) << 5)
| ((MCSettings_Skin_Hat ? 1 : 0) << 6)
);
}
}
//Other Settings
public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\3d\3d7f778ea0a3baaf826ae75a094d77c46410902f"; //MC 1.9 en_GB.lang
public static string TranslationsFile_Website_Index = "https://s3.amazonaws.com/Minecraft.Download/indexes/1.9.json";
public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\ed\eda1518b15c711cf6e75d99003bd87753f67fac4"; //MC 1.10 en_GB.lang
public static string TranslationsFile_Website_Index = "https://s3.amazonaws.com/Minecraft.Download/indexes/1.10.json";
public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net";
public static TimeSpan splitMessageDelay = TimeSpan.FromSeconds(2);
public static List<string> Bots_Owners = new List<string>();
@ -119,7 +150,7 @@ namespace MinecraftClient
private static readonly Dictionary<string, KeyValuePair<string, string>> Accounts = new Dictionary<string, KeyValuePair<string, string>>();
private static readonly Dictionary<string, KeyValuePair<string, ushort>> Servers = new Dictionary<string, KeyValuePair<string, ushort>>();
private enum ParseMode { Default, Main, AppVars, Proxy, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond };
private enum ParseMode { Default, Main, AppVars, Proxy, MCSettings, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond };
/// <summary>
/// Load settings from the give INI file
@ -153,6 +184,7 @@ namespace MinecraftClient
case "chatlog": pMode = ParseMode.ChatLog; break;
case "hangman": pMode = ParseMode.Hangman; break;
case "main": pMode = ParseMode.Main; break;
case "mcsettings": pMode = ParseMode.MCSettings; break;
case "scriptscheduler": pMode = ParseMode.ScriptScheduler; break;
case "remotecontrol": pMode = ParseMode.RemoteControl; break;
case "proxy": pMode = ParseMode.Proxy; break;
@ -395,6 +427,56 @@ namespace MinecraftClient
case "matchesfile": AutoRespond_Matches = argValue; break;
}
break;
case ParseMode.MCSettings:
switch (argName.ToLower())
{
case "enabled": MCSettings_Enabled = str2bool(argValue); break;
case "locale": MCSettings_Locale = argValue; break;
case "difficulty":
switch (argValue.ToLower())
{
case "peaceful": MCSettings_Difficulty = 0; break;
case "easy": MCSettings_Difficulty = 1; break;
case "normal": MCSettings_Difficulty = 2; break;
case "difficult": MCSettings_Difficulty = 3; break;
}
break;
case "renderdistance":
MCSettings_RenderDistance = (byte)str2int(argValue);
switch (argValue.ToLower())
{
case "tiny": MCSettings_RenderDistance = 2; break;
case "short": MCSettings_RenderDistance = 4; break;
case "medium": MCSettings_RenderDistance = 8; break;
case "far": MCSettings_RenderDistance = 16; break;
}
break;
case "chatmode":
switch (argValue.ToLower())
{
case "enabled": MCSettings_ChatMode = 0; break;
case "commands": MCSettings_ChatMode = 1; break;
case "disabled": MCSettings_ChatMode = 2; break;
}
break;
case "chatcolors": MCSettings_ChatColors = str2bool(argValue); break;
case "skin_cape": MCSettings_Skin_Cape = str2bool(argValue); break;
case "skin_jacket": MCSettings_Skin_Jacket = str2bool(argValue); break;
case "skin_sleeve_left": MCSettings_Skin_Sleeve_Left = str2bool(argValue); break;
case "skin_sleeve_right": MCSettings_Skin_Sleeve_Right = str2bool(argValue); break;
case "skin_pants_left": MCSettings_Skin_Pants_Left = str2bool(argValue); break;
case "skin_pants_right": MCSettings_Skin_Pants_Right = str2bool(argValue); break;
case "skin_hat": MCSettings_Skin_Hat = str2bool(argValue); break;
case "main_hand":
switch (argValue.ToLower())
{
case "left": MCSettings_MainHand = 0; break;
case "right": MCSettings_MainHand = 1; break;
}
break;
}
break;
}
}
}
@ -418,7 +500,7 @@ namespace MinecraftClient
+ "[Main]\r\n"
+ "\r\n"
+ "# General settings\r\n"
+ "#leave blank to prompt user on startup\r\n"
+ "# Leave blank to prompt user on startup\r\n"
+ "# Use \"-\" as password for offline mode\r\n"
+ "\r\n"
+ "login=\r\n"
@ -429,18 +511,18 @@ namespace MinecraftClient
+ "\r\n"
+ "language=en_GB\r\n"
+ "consoletitle=%username%@%serverip% - Minecraft Console Client\r\n"
+ "internalcmdchar=slash #use 'none', 'slash' or 'backslash'\r\n"
+ "splitmessagedelay=2 #seconds between each part of a long message\r\n"
+ "botowners=Player1,Player2,Player3 #use name list or myfile.txt with one name per line\r\n"
+ "botmessagedelay=2 #seconds to delay between message a bot makes to avoid accidental spam\r\n"
+ "mcversion=auto #use 'auto' or '1.X.X' values\r\n"
+ "brandinfo=mcc #use 'mcc','vanilla', or 'none'\r\n"
+ "chatbotlogfile= #leave empty for no logfile\r\n"
+ "privatemsgscmdname=tell #used by RemoteControl bot\r\n"
+ "showsystemmessages=true #system messages for server ops\r\n"
+ "showxpbarmessages=true #messages displayed above xp bar\r\n"
+ "terrainandmovements=false #uses more ram, cpu, bandwidth\r\n"
+ "sessioncache=memory #use 'none', 'memory' or 'disk'\r\n"
+ "internalcmdchar=slash # Use 'none', 'slash' or 'backslash'\r\n"
+ "splitmessagedelay=2 # Seconds between each part of a long message\r\n"
+ "botowners=Player1,Player2,Player3 # Use name list or myfile.txt with one name per line\r\n"
+ "botmessagedelay=2 # Seconds to delay between message a bot makes to avoid accidental spam\r\n"
+ "mcversion=auto # Use 'auto' or '1.X.X' values\r\n"
+ "brandinfo=mcc # Use 'mcc','vanilla', or 'none'\r\n"
+ "chatbotlogfile= # Leave empty for no logfile\r\n"
+ "privatemsgscmdname=tell # Used by RemoteControl bot\r\n"
+ "showsystemmessages=true # System messages for server ops\r\n"
+ "showxpbarmessages=true # Messages displayed above xp bar\r\n"
+ "terrainandmovements=false # Uses more ram, cpu, bandwidth\r\n"
+ "sessioncache=memory # Use 'none', 'memory' or 'disk' (disk is experimental)\r\n"
+ "accountlist=accounts.txt\r\n"
+ "serverlist=servers.txt\r\n"
+ "playerheadicon=true\r\n"
@ -455,18 +537,34 @@ namespace MinecraftClient
+ "# %username% and %serverip% are reserved variables.\r\n"
+ "\r\n"
+ "[Proxy]\r\n"
+ "enabled=false #use 'false', 'true', or 'login' for login only\r\n"
+ "enabled=false # Use 'false', 'true', or 'login' for login only\r\n"
+ "type=HTTP # Supported types: HTTP, SOCKS4, SOCKS4a, SOCKS5\r\n"
+ "server=0.0.0.0:0000\r\n"
+ "username=\r\n"
+ "password=\r\n"
+ "\r\n"
+ "[ChatFormat]\r\n"
+ "builtins=true #support for handling vanilla and common message formats\r\n"
+ "#public=^<([a-zA-Z0-9_]+)> (.+)$ #uncomment and adapt if necessary\r\n"
+ "#private=^([a-zA-Z0-9_]+) whispers to you: (.+)$ #vanilla example\r\n"
+ "builtins=true # Support for common message formats\r\n"
+ "# public=^<([a-zA-Z0-9_]+)> (.+)$ # Uncomment and adapt if necessary\r\n"
+ "# private=^([a-zA-Z0-9_]+) whispers to you: (.+)$ # Vanilla private message example\r\n"
+ "# tprequest=^([a-zA-Z0-9_]+) has requested (?:to|that you) teleport to (?:you|them)\\.$\r\n"
+ "\r\n"
+ "[MCSettings]\r\n"
+ "enabled=true # If disabled, client settings are not sent to the server\r\n"
+ "locale=en_US # Use any language implemented in Minecraft\r\n"
+ "renderdistance=medium # tiny, short, medium, far, or chunk amount [0 - 255]\r\n"
+ "difficulty=normal # MC 1.7- difficulty. peaceful, easy, normal, difficult\r\n"
+ "chatmode=enabled # enabled, commands, disabled. Allows to mute yourself...\r\n"
+ "chatcolors=true # Allows disabling chat colors server-side\r\n"
+ "main_hand=left # MC 1.9+ main hand. left or right\r\n"
+ "skin_cape=true\r\n"
+ "skin_hat=true\r\n"
+ "skin_jacket=false\r\n"
+ "skin_sleeve_left=false\r\n"
+ "skin_sleeve_right=false\r\n"
+ "skin_pants_left=false\r\n"
+ "skin_pants_right=false"
+ "\r\n"
+ "# Bot Settings\r\n"
+ "\r\n"
+ "[Alerts]\r\n"