mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Fix 1.7+ server list ping by properly parsing Json
Separate Json and ChatParser classes Use Json parser for retrieving Json fields Will avoid wrong "name" field from being used
This commit is contained in:
parent
a7f0897f09
commit
67affc6270
4 changed files with 202 additions and 159 deletions
|
|
@ -19,31 +19,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
public static string ParseText(string json)
|
||||
{
|
||||
int cursorpos = 0;
|
||||
JSONData jsonData = String2Data(json, ref cursorpos);
|
||||
return JSONData2String(jsonData, "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An internal class to store unserialized JSON data
|
||||
/// The data can be an object, an array or a string
|
||||
/// </summary>
|
||||
|
||||
private class JSONData
|
||||
{
|
||||
public enum DataType { Object, Array, String };
|
||||
private DataType type;
|
||||
public DataType Type { get { return type; } }
|
||||
public Dictionary<string, JSONData> Properties;
|
||||
public List<JSONData> DataArray;
|
||||
public string StringValue;
|
||||
public JSONData(DataType datatype)
|
||||
{
|
||||
type = datatype;
|
||||
Properties = new Dictionary<string, JSONData>();
|
||||
DataArray = new List<JSONData>();
|
||||
StringValue = String.Empty;
|
||||
}
|
||||
return JSONData2String(Json.ParseJson(json), "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -210,135 +186,27 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
else return "[" + rulename + "] " + String.Join(" ", using_data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a JSON string to build a JSON object
|
||||
/// </summary>
|
||||
/// <param name="toparse">String to parse</param>
|
||||
/// <param name="cursorpos">Cursor start (set to 0 for function init)</param>
|
||||
/// <returns></returns>
|
||||
|
||||
private static JSONData String2Data(string toparse, ref int cursorpos)
|
||||
{
|
||||
try
|
||||
{
|
||||
JSONData data;
|
||||
switch (toparse[cursorpos])
|
||||
{
|
||||
//Object
|
||||
case '{':
|
||||
data = new JSONData(JSONData.DataType.Object);
|
||||
cursorpos++;
|
||||
while (toparse[cursorpos] != '}')
|
||||
{
|
||||
if (toparse[cursorpos] == '"')
|
||||
{
|
||||
JSONData propertyname = String2Data(toparse, ref cursorpos);
|
||||
if (toparse[cursorpos] == ':') { cursorpos++; } else { /* parse error ? */ }
|
||||
JSONData propertyData = String2Data(toparse, ref cursorpos);
|
||||
data.Properties[propertyname.StringValue] = propertyData;
|
||||
}
|
||||
else cursorpos++;
|
||||
}
|
||||
cursorpos++;
|
||||
break;
|
||||
|
||||
//Array
|
||||
case '[':
|
||||
data = new JSONData(JSONData.DataType.Array);
|
||||
cursorpos++;
|
||||
while (toparse[cursorpos] != ']')
|
||||
{
|
||||
if (toparse[cursorpos] == ',') { cursorpos++; }
|
||||
JSONData arrayItem = String2Data(toparse, ref cursorpos);
|
||||
data.DataArray.Add(arrayItem);
|
||||
}
|
||||
cursorpos++;
|
||||
break;
|
||||
|
||||
//String
|
||||
case '"':
|
||||
data = new JSONData(JSONData.DataType.String);
|
||||
cursorpos++;
|
||||
while (toparse[cursorpos] != '"')
|
||||
{
|
||||
if (toparse[cursorpos] == '\\')
|
||||
{
|
||||
try //Unicode character \u0123
|
||||
{
|
||||
if (toparse[cursorpos + 1] == 'u'
|
||||
&& isHex(toparse[cursorpos + 2])
|
||||
&& isHex(toparse[cursorpos + 3])
|
||||
&& isHex(toparse[cursorpos + 4])
|
||||
&& isHex(toparse[cursorpos + 5]))
|
||||
{
|
||||
//"abc\u0123abc" => "0123" => 0123 => Unicode char n°0123 => Add char to string
|
||||
data.StringValue += char.ConvertFromUtf32(int.Parse(toparse.Substring(cursorpos + 2, 4), System.Globalization.NumberStyles.HexNumber));
|
||||
cursorpos += 6; continue;
|
||||
}
|
||||
else cursorpos++; //Normal character escapement \"
|
||||
}
|
||||
catch (IndexOutOfRangeException) { cursorpos++; } // \u01<end of string>
|
||||
catch (ArgumentOutOfRangeException) { cursorpos++; } // Unicode index 0123 was invalid
|
||||
}
|
||||
data.StringValue += toparse[cursorpos];
|
||||
cursorpos++;
|
||||
}
|
||||
cursorpos++;
|
||||
break;
|
||||
|
||||
//Boolean : true
|
||||
case 't':
|
||||
data = new JSONData(JSONData.DataType.String);
|
||||
cursorpos++;
|
||||
if (toparse[cursorpos] == 'r') { cursorpos++; }
|
||||
if (toparse[cursorpos] == 'u') { cursorpos++; }
|
||||
if (toparse[cursorpos] == 'e') { cursorpos++; data.StringValue = "true"; }
|
||||
break;
|
||||
|
||||
//Boolean : false
|
||||
case 'f':
|
||||
data = new JSONData(JSONData.DataType.String);
|
||||
cursorpos++;
|
||||
if (toparse[cursorpos] == 'a') { cursorpos++; }
|
||||
if (toparse[cursorpos] == 'l') { cursorpos++; }
|
||||
if (toparse[cursorpos] == 's') { cursorpos++; }
|
||||
if (toparse[cursorpos] == 'e') { cursorpos++; data.StringValue = "false"; }
|
||||
break;
|
||||
|
||||
//Unknown data
|
||||
default:
|
||||
cursorpos++;
|
||||
return String2Data(toparse, ref cursorpos);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
return new JSONData(JSONData.DataType.String);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use a JSON Object to build the corresponding string
|
||||
/// </summary>
|
||||
/// <param name="data">JSON object to convert</param>
|
||||
/// <param name="colorcode">Allow parent color code to affect child elements (set to "" for function init)</param>
|
||||
/// <returns>returns the Minecraft-formatted string</returns>
|
||||
|
||||
private static string JSONData2String(JSONData data, string colorcode)
|
||||
|
||||
private static string JSONData2String(Json.JSONData data, string colorcode)
|
||||
{
|
||||
string extra_result = "";
|
||||
switch (data.Type)
|
||||
{
|
||||
case JSONData.DataType.Object:
|
||||
case Json.JSONData.DataType.Object:
|
||||
if (data.Properties.ContainsKey("color"))
|
||||
{
|
||||
colorcode = color2tag(JSONData2String(data.Properties["color"], ""));
|
||||
}
|
||||
if (data.Properties.ContainsKey("extra"))
|
||||
{
|
||||
JSONData[] extras = data.Properties["extra"].DataArray.ToArray();
|
||||
foreach (JSONData item in extras)
|
||||
Json.JSONData[] extras = data.Properties["extra"].DataArray.ToArray();
|
||||
foreach (Json.JSONData item in extras)
|
||||
extra_result = extra_result + JSONData2String(item, colorcode) + "§r";
|
||||
}
|
||||
if (data.Properties.ContainsKey("text"))
|
||||
|
|
@ -352,7 +220,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
data.Properties["with"] = data.Properties["using"];
|
||||
if (data.Properties.ContainsKey("with"))
|
||||
{
|
||||
JSONData[] array = data.Properties["with"].DataArray.ToArray();
|
||||
Json.JSONData[] array = data.Properties["with"].DataArray.ToArray();
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
using_data.Add(JSONData2String(array[i], colorcode));
|
||||
|
|
@ -362,29 +230,21 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
else return extra_result;
|
||||
|
||||
case JSONData.DataType.Array:
|
||||
case Json.JSONData.DataType.Array:
|
||||
string result = "";
|
||||
foreach (JSONData item in data.DataArray)
|
||||
foreach (Json.JSONData item in data.DataArray)
|
||||
{
|
||||
result += JSONData2String(item, colorcode);
|
||||
}
|
||||
return result;
|
||||
|
||||
case JSONData.DataType.String:
|
||||
case Json.JSONData.DataType.String:
|
||||
return colorcode + data.StringValue;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Small function for checking if a char is an hexadecimal char (0-9 A-F a-f)
|
||||
/// </summary>
|
||||
/// <param name="c">Char to test</param>
|
||||
/// <returns>True if hexadecimal</returns>
|
||||
|
||||
private static bool isHex(char c) { return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); }
|
||||
|
||||
/// <summary>
|
||||
/// Do a HTTP request to get a webpage or text data from a server file
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue