Update JavaDeserialiser.cs

Added TC_ENUM and associated class.
Added TC_CLASS to ReadObject().
Removed unnecessary spaces on empty lines.
Unify code styling.
This commit is contained in:
123DontMessWitMe 2025-07-13 07:34:58 -04:00
parent 4d838ecb6b
commit 86af8c8f27

View File

@ -15,52 +15,54 @@
or implied. See the Licenses for the specific language governing or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses. permissions and limitations under the Licenses.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text; using System.Text;
namespace MCGalaxy.Levels.IO namespace MCGalaxy.Levels.IO {
{ public class JClassDesc {
public class JClassDesc
{
public string Name; public string Name;
public byte Flags; public byte Flags;
public JFieldDesc[] Fields; public JFieldDesc[] Fields;
public JClassDesc SuperClass; public JClassDesc SuperClass;
} }
public class JClassData public class JClassData {
{
public object[] Values; public object[] Values;
} }
public class JObject public class JClass {
{ public JClassDesc Desc;
}
public class JObject {
public JClassDesc Desc; public JClassDesc Desc;
public JClassData[] ClassData; public JClassData[] ClassData;
} }
public class JArray public class JArray {
{
public JClassDesc Desc; public JClassDesc Desc;
public object Values; public object Values;
} }
public class JFieldDesc public class JFieldDesc {
{
public char Type; public char Type;
public string Name, ClassName; public string Name, ClassName;
} }
public class JEnum {
public JClassDesc Desc;
public object Name;
public override string ToString() { return Desc.Name + "." + Name; }
}
// Java serialised objects are quite complicated and annoying to parse // Java serialised objects are quite complicated and annoying to parse
// http://www.javaworld.com/article/2072752/the-java-serialization-algorithm-revealed.html // http://www.javaworld.com/article/2072752/the-java-serialization-algorithm-revealed.html
// https://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html // https://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html
// Good reference tool for comparison // Good reference tool for comparison
// https://github.com/NickstaDB/SerializationDumper // https://github.com/NickstaDB/SerializationDumper
public sealed class JavaReader public sealed class JavaReader {
{
public BinaryReader src; public BinaryReader src;
public List<object> handles = new List<object>(); public List<object> handles = new List<object>();
public byte[] ReadBytes(int count) { return src.ReadBytes(count); } public byte[] ReadBytes(int count) { return src.ReadBytes(count); }
@ -85,8 +87,12 @@ namespace MCGalaxy.Levels.IO
const byte TC_CLASS = 0x76; const byte TC_CLASS = 0x76;
const byte TC_BLOCKDATA = 0x77; const byte TC_BLOCKDATA = 0x77;
const byte TC_ENDBLOCKDATA = 0x78; const byte TC_ENDBLOCKDATA = 0x78;
const byte TC_RESET = 0x79; const byte TC_RESET = 0x79; // Unimplemented
const byte TC_BLOCKDATALONG = 0x7A; const byte TC_BLOCKDATALONG = 0x7A; // Unimplemented
const byte TC_EXCEPTION = 0x7B; // Unimplemented
const byte TC_LONGSTRING = 0x7C; // Unimplemented
const byte TC_PROXYCLASSDESC = 0x7D; // Unimplemented
const byte TC_ENUM = 0x7E;
const int baseWireHandle = 0x7E0000; const int baseWireHandle = 0x7E0000;
const byte SC_WRITE_METHOD = 0x01, SC_SERIALIZABLE = 0x02; const byte SC_WRITE_METHOD = 0x01, SC_SERIALIZABLE = 0x02;
@ -99,6 +105,8 @@ namespace MCGalaxy.Levels.IO
case TC_REFERENCE: return PrevObject(); case TC_REFERENCE: return PrevObject();
case TC_OBJECT: return NewObject(); case TC_OBJECT: return NewObject();
case TC_ARRAY: return NewArray(); case TC_ARRAY: return NewArray();
case TC_ENUM: return NewEnum();
case TC_CLASS: return NewClass();
} }
throw new InvalidDataException("Invalid typecode: " + typeCode); throw new InvalidDataException("Invalid typecode: " + typeCode);
} }
@ -130,8 +138,7 @@ namespace MCGalaxy.Levels.IO
} }
obj.ClassData = new JClassData[descs.Count]; obj.ClassData = new JClassData[descs.Count];
for (int i = descs.Count - 1; i >= 0; i--) for (int i = descs.Count - 1; i >= 0; i--) {
{
obj.ClassData[i] = ClassData(descs[i]); obj.ClassData[i] = ClassData(descs[i]);
} }
return obj; return obj;
@ -148,8 +155,7 @@ namespace MCGalaxy.Levels.IO
array.Values = ReadBytes(size); array.Values = ReadBytes(size);
} else { } else {
object[] values = new object[size]; object[] values = new object[size];
for (int i = 0; i < values.Length; i++) for (int i = 0; i < values.Length; i++) {
{
values[i] = Value(type); values[i] = Value(type);
} }
array.Values = values; array.Values = values;
@ -166,8 +172,7 @@ namespace MCGalaxy.Levels.IO
// read class desc info // read class desc info
desc.Flags = ReadUInt8(); desc.Flags = ReadUInt8();
desc.Fields = new JFieldDesc[ReadUInt16()]; desc.Fields = new JFieldDesc[ReadUInt16()];
for (int i = 0; i < desc.Fields.Length; i++) for (int i = 0; i < desc.Fields.Length; i++) {
{
desc.Fields[i] = FieldDesc(); desc.Fields[i] = FieldDesc();
} }
@ -176,6 +181,21 @@ namespace MCGalaxy.Levels.IO
return desc; return desc;
} }
JEnum NewEnum() { // TC_ENUM classDesc newHandle enumConstantName
JEnum je = new JEnum();
je.Desc = ClassDesc(); // classDesc
handles.Add(je); // newHandle
je.Name = ReadObject(); // enumConstantName
return je;
}
JClass NewClass() { // TC_CLASS classDesc newHandle
JClass jc = new JClass();
jc.Desc = ClassDesc(); // classDesc
handles.Add(jc); // newHandle
return jc;
}
JClassDesc ClassDesc() { JClassDesc ClassDesc() {
byte typeCode = ReadUInt8(); byte typeCode = ReadUInt8();
if (typeCode == TC_CLASSDESC) return NewClassDesc(); if (typeCode == TC_CLASSDESC) return NewClassDesc();
@ -235,8 +255,7 @@ namespace MCGalaxy.Levels.IO
void SkipAnnotation() { void SkipAnnotation() {
byte typeCode; byte typeCode;
while ((typeCode = ReadUInt8()) != TC_ENDBLOCKDATA) while ((typeCode = ReadUInt8()) != TC_ENDBLOCKDATA) {
{
if (typeCode == TC_BLOCKDATA) { if (typeCode == TC_BLOCKDATA) {
ReadBytes(ReadUInt8()); ReadBytes(ReadUInt8());
} else { } else {