Example #1
0
        public static ItemDefinitionFile Decode(byte[] data)
        {
            var file = new ItemDefinitionFile();

            using var reader = new BinaryReader(new MemoryStream(data));

            Opcode opcode;

            do
            {
                opcode = (Opcode)reader.ReadByte();

                switch (opcode)
                {
                case Opcode.End:
                    break;

                case Opcode.ModelId:
                    file.ModelId = reader.ReadAwkwardInt();
                    break;

                case Opcode.Name:
                    file.Name = reader.ReadNullTerminatedString();
                    break;

                case Opcode.ModelZoom:
                    file.ModelZoom = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.ModelRotation1:
                    file.ModelRotation1 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.ModelRotation2:
                    file.ModelRotation2 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.ModelOffset1:
                    file.ModelOffset1 = reader.ReadInt16BigEndian();
                    break;

                case Opcode.ModelOffset2:
                    file.ModelOffset2 = reader.ReadInt16BigEndian();
                    break;

                case Opcode.Stackable:
                    file.Stackable = true;
                    break;

                case Opcode.Value:
                    file.Value = reader.ReadInt32BigEndian();
                    break;

                case Opcode.EquipSlotId:
                    file.EquipSlotId = reader.ReadByte();
                    break;

                case Opcode.EquipId:
                    file.EquipId = reader.ReadByte();
                    break;

                case Opcode.MembersOnly:
                    file.MembersOnly = true;
                    break;

                case Opcode.UnknownShort1:
                    file.UnknownShort1 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.MaleEquip1:
                    file.MaleEquip1 = reader.ReadAwkwardInt();
                    break;

                case Opcode.MaleEquip2:
                    file.MaleEquip2 = reader.ReadAwkwardInt();
                    break;

                case Opcode.FemaleEquip1:
                    file.FemaleEquip1 = reader.ReadAwkwardInt();
                    break;

                case Opcode.FemaleEquip2:
                    file.FemaleEquip2 = reader.ReadAwkwardInt();
                    break;

                case Opcode.UnknownByte1:
                    file.UnknownByte1 = reader.ReadByte();
                    break;

                case Opcode.GroundOption1:
                    file.GroundOptions[0] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.GroundOption2:
                    file.GroundOptions[1] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.GroundOption3:
                    file.GroundOptions[2] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.GroundOption4:
                    file.GroundOptions[3] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.GroundOption5:
                    file.GroundOptions[4] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.InventoryOption1:
                    file.InventoryOptions[0] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.InventoryOption2:
                    file.InventoryOptions[1] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.InventoryOption3:
                    file.InventoryOptions[2] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.InventoryOption4:
                    file.InventoryOptions[3] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.InventoryOption5:
                    file.InventoryOptions[4] = reader.ReadNullTerminatedString();
                    break;

                case Opcode.ModelColors:
                    var modelColorCount = reader.ReadByte();
                    file.OriginalModelColors = new ushort[modelColorCount];
                    file.ModifiedModelColors = new ushort[modelColorCount];
                    for (var i = 0; i < modelColorCount; i++)
                    {
                        file.OriginalModelColors[i] = reader.ReadUInt16BigEndian();
                        file.ModifiedModelColors[i] = reader.ReadUInt16BigEndian();
                    }
                    break;

                case Opcode.TextureColors:
                    var textureColorCount = reader.ReadByte();
                    file.OriginalTextureColors = new ushort[textureColorCount];
                    file.ModifiedTextureColors = new ushort[textureColorCount];
                    for (var i = 0; i < textureColorCount; i++)
                    {
                        file.OriginalTextureColors[i] = reader.ReadUInt16BigEndian();
                        file.ModifiedTextureColors[i] = reader.ReadUInt16BigEndian();
                    }
                    break;

                case Opcode.UnknownByteArray1:
                    var unknownByteArray1Length = reader.ReadByte();
                    file.UnknownByteArray1 = new byte[unknownByteArray1Length];
                    for (var i = 0; i < unknownByteArray1Length; i++)
                    {
                        file.UnknownByteArray1[i] = reader.ReadByte();
                    }
                    break;

                case Opcode.UnknownInt1:
                    file.UnknownInt1 = reader.ReadUInt32BigEndian();
                    break;

                case Opcode.UnknownShort2:
                    file.UnknownShort2 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort3:
                    file.UnknownShort3 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.Unnoted:
                    file.Unnoted = true;
                    break;

                case Opcode.ColorEquip1:
                    file.ColorEquip1 = reader.ReadAwkwardInt();
                    break;

                case Opcode.ColorEquip2:
                    file.ColorEquip2 = reader.ReadAwkwardInt();
                    break;

                case Opcode.UnknownAwkwardInt1:
                    file.UnknownAwkwardInt1 = reader.ReadAwkwardInt();
                    break;

                case Opcode.UnknownAwkwardInt2:
                    file.UnknownAwkwardInt2 = reader.ReadAwkwardInt();
                    break;

                case Opcode.UnknownAwkwardInt3:
                    file.UnknownAwkwardInt3 = reader.ReadAwkwardInt();
                    break;

                case Opcode.UnknownAwkwardInt4:
                    file.UnknownAwkwardInt4 = reader.ReadAwkwardInt();
                    break;

                case Opcode.UnknownShort4:
                    file.UnknownShort4 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort5:
                    file.UnknownShort5 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownByte2:
                    file.UnknownByte2 = reader.ReadByte();
                    break;

                case Opcode.NoteId:
                    file.NoteId = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.NoteTemplateId:
                    file.NoteTemplateId = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.Stack1:
                    file.Stacks[0] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack2:
                    file.Stacks[1] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack3:
                    file.Stacks[2] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack4:
                    file.Stacks[3] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack5:
                    file.Stacks[4] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack6:
                    file.Stacks[5] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack7:
                    file.Stacks[6] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack8:
                    file.Stacks[7] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack9:
                    file.Stacks[8] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.Stack10:
                    file.Stacks[9] = new Tuple <ushort, ushort>(
                        reader.ReadUInt16BigEndian(),
                        reader.ReadUInt16BigEndian());
                    break;

                case Opcode.UnknownShort6:
                    file.UnknownShort6 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort7:
                    file.UnknownShort7 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort8:
                    file.UnknownShort8 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownByte3:
                    file.UnknownByte3 = reader.ReadByte();
                    break;

                case Opcode.UnknownByte4:
                    file.UnknownByte4 = reader.ReadByte();
                    break;

                case Opcode.TeamId:
                    file.TeamId = reader.ReadByte();
                    break;

                case Opcode.LendId:
                    file.LendId = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.LendTemplateId:
                    file.LendTemplateId = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownTribyte1:
                    file.UnknownTribyte1 = reader.ReadUInt24BigEndian();
                    break;

                case Opcode.UnknownTribyte2:
                    file.UnknownTribyte2 = reader.ReadUInt24BigEndian();
                    break;

                case Opcode.UnknownTribyte3:
                    file.UnknownTribyte3 = reader.ReadUInt24BigEndian();
                    break;

                case Opcode.UnknownTribyte4:
                    file.UnknownTribyte4 = reader.ReadUInt24BigEndian();
                    break;

                case Opcode.UnknownTribyte5:
                    file.UnknownTribyte5 = reader.ReadUInt24BigEndian();
                    break;

                case Opcode.UnknownTribyte6:
                    file.UnknownTribyte6 = reader.ReadUInt24BigEndian();
                    break;

                case Opcode.UnknownShortArray1:
                    var unknownShortArray1Length = reader.ReadByte();
                    file.UnknownShortArray1 = new ushort[unknownShortArray1Length];
                    for (var i = 0; i < unknownShortArray1Length; i++)
                    {
                        file.UnknownShortArray1[i] = reader.ReadUInt16BigEndian();
                    }
                    break;

                case Opcode.UnknownByte5:
                    file.UnknownByte5 = reader.ReadByte();
                    break;

                case Opcode.BindId:
                    file.BindId = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.BindTemplateId:
                    file.BindTemplateId = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort9:
                    file.UnknownShort9 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort10:
                    file.UnknownShort10 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort11:
                    file.UnknownShort11 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort12:
                    file.UnknownShort12 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort13:
                    file.UnknownShort13 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort14:
                    file.UnknownShort14 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort15:
                    file.UnknownShort15 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort16:
                    file.UnknownShort16 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort17:
                    file.UnknownShort17 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort18:
                    file.UnknownShort18 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.Is25Gp:
                    file.Is25Gp = true;
                    break;

                case Opcode.UnknownShort19:
                    file.UnknownShort19 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.UnknownShort20:
                    file.UnknownShort20 = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.ShardAmount:
                    file.ShardAmount = reader.ReadUInt16BigEndian();
                    break;

                case Opcode.ShardName:
                    file.ShardName = reader.ReadNullTerminatedString();
                    break;

                case Opcode.UnknownSwitch2:
                    file.UnknownSwitch2 = true;
                    break;

                case Opcode.Properties:
                    var propertyCount = reader.ReadByte();

                    for (var i = 0; i < propertyCount; i++)
                    {
                        var valueIsString = reader.ReadByte() != 0;
                        var key           = reader.ReadUInt24BigEndian();

                        var value = valueIsString
                                ? (object)reader.ReadNullTerminatedString()
                                : reader.ReadInt32BigEndian();

                        if (!file.Properties.ContainsKey((PropertyKey)key))
                        {
                            file.Properties.Add((PropertyKey)key, value);
                        }
                        else
                        {
                            // Duplicate properties are probably caused by improper tooling at Jagex HQ
                            file.Properties[(PropertyKey)key] = value;
                        }
                    }
                    break;

                default:
                    throw new DecodeException($"Unknown opcode {opcode}.");
                }
            }while (opcode != Opcode.End);

            if (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                throw new DecodeException($"Data remaining after decoding item definition. {reader.BaseStream.Length - reader.BaseStream.Position} bytes remain.");
            }

            return(file);
        }
        public static ItemDefinitionFile Decode(byte[] data)
        {
            var file = new ItemDefinitionFile();

            using var reader = new BinaryReader(new MemoryStream(data));

            Opcode opcode;

            do
            {
                opcode = (Opcode)reader.ReadByte();
                object?_ = opcode switch
                {
                    Opcode.End => null,
                    Opcode.ModelId => file.ModelId                   = reader.ReadAwkwardInt(),
                    Opcode.Name => file.Name                         = reader.ReadNullTerminatedString(),
                    Opcode.BuffEffect => file.BuffEffect             = reader.ReadNullTerminatedString(),
                    Opcode.ModelZoom => file.ModelZoom               = reader.ReadUInt16BigEndian(),
                    Opcode.ModelRotation1 => file.ModelRotation1     = reader.ReadUInt16BigEndian(),
                    Opcode.ModelRotation2 => file.ModelRotation2     = reader.ReadUInt16BigEndian(),
                    Opcode.ModelOffset1 => file.ModelOffset1         = reader.ReadInt16BigEndian(),
                    Opcode.ModelOffset2 => file.ModelOffset2         = reader.ReadInt16BigEndian(),
                    Opcode.Stackable => file.Stackable               = true,
                    Opcode.Value => file.Value                       = reader.ReadInt32BigEndian(),
                    Opcode.EquipSlot => file.EquipSlot               = reader.ReadByte(),
                    Opcode.EquipId => file.EquipId                   = reader.ReadByte(),
                    Opcode.Unknown15 => file.Unknown15               = true,
                    Opcode.MembersOnly => file.MembersOnly           = true,
                    Opcode.Unknown18 => file.Unknown18               = reader.ReadUInt16BigEndian(),
                    Opcode.MaleEquip1 => file.MaleEquip1             = reader.ReadAwkwardInt(),
                    Opcode.MaleEquip2 => file.MaleEquip2             = reader.ReadAwkwardInt(),
                    Opcode.FemaleEquip1 => file.FemaleEquip1         = reader.ReadAwkwardInt(),
                    Opcode.FemaleEquip2 => file.FemaleEquip2         = reader.ReadAwkwardInt(),
                    Opcode.Unknown27 => file.Unknown27               = reader.ReadByte(),
                    Opcode.GroundOption1 => file.GroundOption1       = reader.ReadNullTerminatedString(),
                    Opcode.GroundOption2 => file.GroundOption2       = reader.ReadNullTerminatedString(),
                    Opcode.GroundOption3 => file.GroundOption3       = reader.ReadNullTerminatedString(),
                    Opcode.GroundOption4 => file.GroundOption4       = reader.ReadNullTerminatedString(),
                    Opcode.GroundOption5 => file.GroundOption5       = reader.ReadNullTerminatedString(),
                    Opcode.InventoryOption1 => file.InventoryOption1 = reader.ReadNullTerminatedString(),
                    Opcode.InventoryOption2 => file.InventoryOption2 = reader.ReadNullTerminatedString(),
                    Opcode.InventoryOption3 => file.InventoryOption3 = reader.ReadNullTerminatedString(),
                    Opcode.InventoryOption4 => file.InventoryOption4 = reader.ReadNullTerminatedString(),
                    Opcode.InventoryOption5 => file.InventoryOption5 = reader.ReadNullTerminatedString(),
                    Opcode.ModelColors => file.ModelColors           = reader.ReadInterlacedUInt16BigEndianArrays(2, reader.ReadByte()),
                    Opcode.TextureColors => file.TextureColors       = reader.ReadInterlacedUInt16BigEndianArrays(2, reader.ReadByte()),
                    Opcode.Unknown42 => file.Unknown42               = reader.ReadBytesExactly(reader.ReadByte()),
                    Opcode.Unknown43 => file.Unknown43               = reader.ReadUInt32BigEndian(),
                    Opcode.Unknown44 => file.Unknown44               = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown45 => file.Unknown45               = reader.ReadUInt16BigEndian(),
                    Opcode.Exchangeable => file.Exchangeable         = true,
                    Opcode.GeBuyLimit => file.GeBuyLimit             = reader.ReadInt32BigEndian(),
                    Opcode.ColorEquip1 => file.ColorEquip1           = reader.ReadAwkwardInt(),
                    Opcode.ColorEquip2 => file.ColorEquip2           = reader.ReadAwkwardInt(),
                    Opcode.Unknown90 => file.Unknown90               = reader.ReadAwkwardInt(),
                    Opcode.Unknown91 => file.Unknown91               = reader.ReadAwkwardInt(),
                    Opcode.Unknown92 => file.Unknown92               = reader.ReadAwkwardInt(),
                    Opcode.Unknown93 => file.Unknown93               = reader.ReadAwkwardInt(),
                    Opcode.Category => file.Category                 = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown95 => file.Unknown95               = reader.ReadUInt16BigEndian(),
                    Opcode.DummyType => file.DummyType               = reader.ReadByte(),
                    Opcode.NoteId => file.NoteId                     = reader.ReadUInt16BigEndian(),
                    Opcode.NoteTemplateId => file.NoteTemplateId     = reader.ReadUInt16BigEndian(),
                    Opcode.Stack1 => file.Stack1                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack2 => file.Stack2                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack3 => file.Stack3                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack4 => file.Stack4                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack5 => file.Stack5                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack6 => file.Stack6                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack7 => file.Stack7                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack8 => file.Stack8                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack9 => file.Stack9                     = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Stack10 => file.Stack10                   = new Tuple <ushort, ushort>(reader.ReadUInt16BigEndian(), reader.ReadUInt16BigEndian()),
                    Opcode.Unknown110 => file.Unknown110             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown111 => file.Unknown111             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown112 => file.Unknown112             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown113 => file.Unknown113             = reader.ReadByte(),
                    Opcode.Unknown114 => file.Unknown114             = reader.ReadByte(),
                    Opcode.TeamId => file.TeamId                     = reader.ReadByte(),
                    Opcode.LendId => file.LendId                     = reader.ReadUInt16BigEndian(),
                    Opcode.LendTemplateId => file.LendTemplateId     = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown125 => file.Unknown125             = reader.ReadUInt24BigEndian(),
                    Opcode.Unknown126 => file.Unknown126             = reader.ReadUInt24BigEndian(),
                    Opcode.Unknown127 => file.Unknown127             = reader.ReadUInt24BigEndian(),
                    Opcode.Unknown128 => file.Unknown128             = reader.ReadUInt24BigEndian(),
                    Opcode.Unknown129 => file.Unknown129             = reader.ReadUInt24BigEndian(),
                    Opcode.Unknown130 => file.Unknown130             = reader.ReadUInt24BigEndian(),
                    Opcode.Unknown132 => file.Unknown132             = reader.ReadUInt16BigEndians(reader.ReadByte()),
                    Opcode.Unknown134 => file.Unknown134             = reader.ReadByte(),
                    Opcode.BindId => file.BindId                     = reader.ReadUInt16BigEndian(),
                    Opcode.BindTemplateId => file.BindTemplateId     = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown142 => file.Unknown142             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown143 => file.Unknown143             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown144 => file.Unknown144             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown145 => file.Unknown145             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown146 => file.Unknown146             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown150 => file.Unknown150             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown151 => file.Unknown151             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown152 => file.Unknown152             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown153 => file.Unknown153             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown154 => file.Unknown154             = reader.ReadUInt16BigEndian(),
                    Opcode.Is25Gp => file.Is25Gp                     = true,
                    Opcode.Unknown161 => file.Unknown161             = reader.ReadUInt16BigEndian(),
                    Opcode.Unknown162 => file.Unknown162             = reader.ReadUInt16BigEndian(),
                    Opcode.ShardAmount => file.ShardAmount           = reader.ReadUInt16BigEndian(),
                    Opcode.ShardName => file.ShardName               = reader.ReadNullTerminatedString(),
                    Opcode.Unknown165 => file.Unknown165             = true,
                    Opcode.Unknown167 => file.Unknown167             = true,
                    Opcode.Unknown168 => file.Unknown168             = true,
                    Opcode.Properties => file.Properties             = ItemDefinitionFile.ReadProperties(reader),
                    _ => throw new DecodeException($"Unknown opcode {opcode}."),
                };
            }while (opcode != Opcode.End);

            if (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                throw new DecodeException($"Data remaining after decoding item definition. {reader.BaseStream.Length - reader.BaseStream.Position} bytes remain.");
            }

            return(file);
        }