Esempio n. 1
0
        public override Level Read(Stream src, string name, bool metadata)
        {
            using (GZipStream s = new GZipStream(src, CompressionMode.Decompress)) {
                Level     lvl = new Level(name, 0, 0, 0);
                DatReader r   = new DatReader();
                r.src = new BinaryReader(s);

                int signature = r.ReadInt32();
                // Format version 0 - preclassic to classic 0.12
                //  (technically this format doesn't have a signature,
                //   but 99% of such maps will start with these 4 bytes)
                if (signature == 0x01010101)
                {
                    return(ReadFormat0(lvl, s));
                }

                // All valid .dat maps must start with these 4 bytes
                if (signature != 0x271BB788)
                {
                    throw new InvalidDataException("Invalid .dat map signature");
                }

                switch (r.ReadUInt8())
                {
                // Format version 1 - classic 0.13
                case 0x01: return(ReadFormat1(lvl, r));

                // Format version 2 - classic 0.15 to 0.30
                case 0x02: return(ReadFormat2(lvl, r));
                }
                throw new InvalidDataException("Invalid .dat map version");
            }
        }
Esempio n. 2
0
        public override Level Read(Stream src, string name, bool metadata)
        {
            using (GZipStream s = new GZipStream(src, CompressionMode.Decompress)) {
                Level     lvl = new Level(name, 0, 0, 0);
                DatReader r   = new DatReader();
                r.src = new BinaryReader(s);

                if (r.ReadInt32() != 0x271BB788 || r.ReadUInt8() != 0x02)
                {
                    throw new InvalidDataException("Unexpected constant in .dat file");
                }

                if (r.ReadUInt16() != 0xACED)
                {
                    throw new InvalidDataException("Invalid stream magic");
                }
                if (r.ReadUInt16() != 0x0005)
                {
                    throw new InvalidDataException("Invalid stream version");
                }

                JObject obj = (JObject)ReadObject(r);
                ParseRootObject(lvl, obj);
                return(lvl);
            }
        }
Esempio n. 3
0
        static JClassDesc NewClass(DatReader r)
        {
            JClassDesc classDesc = ClassDesc(r);

            r.handles.Add(classDesc);
            return(classDesc);
        }
Esempio n. 4
0
        static string NewString(DatReader r)
        {
            string value = r.ReadUtf8();

            r.handles.Add(value);
            return(value);
        }
Esempio n. 5
0
        static void SkipAnnotation(DatReader r)
        {
            byte typeCode;

            while ((typeCode = r.ReadUInt8()) != TC_ENDBLOCKDATA)
            {
                ReadContent(r, typeCode);
            }
        }
Esempio n. 6
0
        static object PrevObject(DatReader r)
        {
            int handle = r.ReadInt32() - baseWireHandle;

            if (handle >= 0 && handle < r.handles.Count)
            {
                return(r.handles[handle]);
            }
            throw new InvalidDataException("Invalid stream handle: " + handle);
        }
Esempio n. 7
0
        static Level ReadFormat1(Level lvl, DatReader r)
        {
            r.ReadUtf8();  // level name
            r.ReadUtf8();  // level author
            r.ReadInt64(); // created timestamp (currentTimeMillis)

            lvl.Width  = r.ReadUInt16();
            lvl.Length = r.ReadUInt16();
            lvl.Height = r.ReadUInt16();
            lvl.blocks = r.ReadBytes(lvl.Width * lvl.Height * lvl.Length); // TODO readfully
            SetupClassic013(lvl);
            return(lvl);
        }
Esempio n. 8
0
 static object ReadContent(DatReader r, byte typeCode)
 {
     if (typeCode == TC_BLOCKDATA)
     {
         return(r.ReadBytes(r.ReadUInt8()));
     }
     else if (typeCode == TC_BLOCKDATALONG)
     {
         return(r.ReadBytes(r.ReadInt32()));
     }
     else
     {
         return(ReadObject(r, typeCode));
     }
 }
Esempio n. 9
0
        static object ReadObject(DatReader r, byte typeCode)
        {
            switch (typeCode)
            {
            case TC_STRING:    return(NewString(r));

            case TC_NULL:      return(null);

            case TC_REFERENCE: return(PrevObject(r));

            case TC_OBJECT:    return(NewObject(r));

            case TC_ARRAY:     return(NewArray(r));
            }
            throw new InvalidDataException("Invalid typecode: " + typeCode);
        }
Esempio n. 10
0
        static void SkipAnnotation(DatReader r)
        {
            byte typeCode;

            while ((typeCode = r.ReadUInt8()) != TC_ENDBLOCKDATA)
            {
                if (typeCode == TC_BLOCKDATA)
                {
                    r.ReadBytes(r.ReadUInt8());
                }
                else
                {
                    ReadObject(r, typeCode);
                }
            }
        }
Esempio n. 11
0
        // Really annoying map format to parse, because it's just a Java serialised object
        //  http://www.javaworld.com/article/2072752/the-java-serialization-algorithm-revealed.html
        //  https://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html
        // Good reference tool for comparison
        //  https://github.com/NickstaDB/SerializationDumper
        static Level ReadFormat2(Level lvl, DatReader r)
        {
            if (r.ReadUInt16() != 0xACED)
            {
                throw new InvalidDataException("Invalid stream magic");
            }
            if (r.ReadUInt16() != 0x0005)
            {
                throw new InvalidDataException("Invalid stream version");
            }

            JObject obj = (JObject)ReadObject(r);

            ParseRootObject(lvl, obj);
            return(lvl);
        }
Esempio n. 12
0
        static unsafe object Value(DatReader r, char type)
        {
            if (type == 'B')
            {
                return(r.ReadUInt8());
            }
            if (type == 'C')
            {
                return((char)r.ReadUInt16());
            }
            if (type == 'D')
            {
                long tmp = r.ReadInt64(); return(*(double *)(&tmp));
            }
            if (type == 'F')
            {
                int tmp = r.ReadInt32(); return(*(float *)(&tmp));
            }
            if (type == 'I')
            {
                return(r.ReadInt32());
            }
            if (type == 'J')
            {
                return(r.ReadInt64());
            }
            if (type == 'S')
            {
                return(r.ReadInt16());
            }
            if (type == 'Z')
            {
                return(r.ReadUInt8() != 0);
            }
            if (type == 'L')
            {
                return(ReadObject(r));
            }
            if (type == '[')
            {
                return(ReadObject(r));
            }

            throw new InvalidDataException("Invalid value code: " + type);
        }
Esempio n. 13
0
        static JClassDesc ClassDesc(DatReader r)
        {
            byte typeCode = r.ReadUInt8();

            if (typeCode == TC_CLASSDESC)
            {
                return(NewClassDesc(r));
            }
            if (typeCode == TC_NULL)
            {
                return(null);
            }
            if (typeCode == TC_REFERENCE)
            {
                return((JClassDesc)PrevObject(r));
            }

            throw new InvalidDataException("Invalid type code: " + typeCode);
        }
Esempio n. 14
0
        static JClassDesc NewClassDesc(DatReader r)
        {
            JClassDesc desc = new JClassDesc();

            desc.Name = r.ReadUtf8();
            r.ReadInt64(); // serial UID
            r.handles.Add(desc);

            // read class desc info
            desc.Flags  = r.ReadUInt8();
            desc.Fields = new JFieldDesc[r.ReadUInt16()];
            for (int i = 0; i < desc.Fields.Length; i++)
            {
                desc.Fields[i] = FieldDesc(r);
            }

            SkipAnnotation(r);
            desc.SuperClass = ClassDesc(r);
            return(desc);
        }
Esempio n. 15
0
        static JClassData ClassData(DatReader r, JClassDesc desc)
        {
            if ((desc.Flags & SC_SERIALIZABLE) == 0)
            {
                throw new InvalidDataException("Invalid class data flags: " + desc.Flags);
            }

            JClassData data = new JClassData();

            data.Values = new object[desc.Fields.Length];
            for (int i = 0; i < data.Values.Length; i++)
            {
                data.Values[i] = Value(r, desc.Fields[i].Type);
            }

            if ((desc.Flags & SC_WRITE_METHOD) != 0)
            {
                SkipAnnotation(r);
            }
            return(data);
        }
Esempio n. 16
0
        static object ReadObject(DatReader r, byte typeCode)
        {
            switch (typeCode)
            {
            case TC_STRING:    return(NewString(r));

            case TC_RESET: r.handles.Clear(); return(null);

            case TC_NULL:      return(null);

            case TC_REFERENCE: return(PrevObject(r));

            case TC_CLASS:     return(NewClass(r));

            case TC_OBJECT:    return(NewObject(r));

            case TC_ARRAY:     return(NewArray(r));

            case TC_CLASSDESC: return(NewClassDesc(r));
            }
            throw new InvalidDataException("Invalid typecode: " + typeCode);
        }
Esempio n. 17
0
        static JFieldDesc FieldDesc(DatReader r)
        {
            JFieldDesc desc = new JFieldDesc();
            byte       type = r.ReadUInt8();

            desc.Type = (char)type;

            if (type == 'B' || type == 'C' || type == 'D' || type == 'F' || type == 'I' || type == 'J' || type == 'S' || type == 'Z')
            {
                desc.Name = r.ReadUtf8();
            }
            else if (type == '[' || type == 'L')
            {
                desc.Name      = r.ReadUtf8();
                desc.ClassName = (string)ReadObject(r);
            }
            else
            {
                throw new InvalidDataException("Invalid field type: " + type);
            }
            return(desc);
        }
Esempio n. 18
0
        static JObject NewObject(DatReader r)
        {
            JObject obj = new JObject();

            obj.Desc = ClassDesc(r);
            r.handles.Add(obj);

            List <JClassDesc> descs = new List <JClassDesc>();
            JClassDesc        tmp   = obj.Desc;

            // most superclass data is first
            while (tmp != null)
            {
                descs.Add(tmp);
                tmp = tmp.SuperClass;
            }

            obj.ClassData = new JClassData[descs.Count];
            for (int i = descs.Count - 1; i >= 0; i--)
            {
                obj.ClassData[i] = ClassData(r, descs[i]);
            }
            return(obj);
        }
Esempio n. 19
0
        static JArray NewArray(DatReader r)
        {
            JArray array = new JArray();

            array.Desc = ClassDesc(r);
            r.handles.Add(array);
            char type = array.Desc.Name[1];
            int  size = r.ReadInt32();

            if (type == 'B')
            {
                array.Values = r.ReadBytes(size);
            }
            else
            {
                object[] values = new object[size];
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = Value(r, type);
                }
                array.Values = values;
            }
            return(array);
        }
Esempio n. 20
0
 static object ReadObject(DatReader r)
 {
     return(ReadObject(r, r.ReadUInt8()));
 }