Пример #1
0
        public static void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            VerifyConnection(connectionId);
            Condition.IsNull(ConnectionList[connectionId].Request);

            #region Combinations

            Combination.NWise(1, connectionId, sessionId, previousSessionId, signed, flags, user);
            #endregion

            #region Other contraints

            // Do not estabilish 2nd session if no session exist yet
            Condition.IfThen(GlobalSessionTable.Count == 0,
                             sessionId != ModelSessionId.AlternativeSessionId &&
                             user == ModelUser.DefaultUser);

            // Do not establish new session if there's one in the requested connection
            Condition.IfThen(ConnectionList[connectionId].Session != null, sessionId != ModelSessionId.ZeroSessionId);

            // Do not establish new session if 2 sessions exist
            Condition.IfThen(GlobalSessionTable.Count == 2, sessionId != ModelSessionId.ZeroSessionId);

            // Do not set previousSessionId to session1 if currently establish session1
            Condition.IfThen(GlobalSessionTable.Count == 0 &&
                             sessionId == ModelSessionId.ZeroSessionId,
                             previousSessionId != ModelSessionId.MainSessionId);

            // If session id is zero, it's the same that the binding flag is set or not.
            Condition.IfThen(sessionId == ModelSessionId.ZeroSessionId, flags == ModelFlags.NotBinding);

            // Restrict the condition to no session exist yet as we only simulate one session in this Model
            Condition.IsNull(ConnectionList[connectionId].Session);

            // If we need to skip SessionSetup when it's re-auth an existing one
            if (ReAuthentication == ModelAllowReauthentication.NotAllowReauthentication)
            {
                Condition.IsTrue(ConnectionList[connectionId].Session == null ||
                                 ConnectionList[connectionId].Session.State != ModelSessionState.Valid);
            }

            #endregion

            ConnectionList[connectionId].Request = new ModelSessionSetupRequest(
                connectionId,
                sessionId,
                previousSessionId,
                signed == ModelSigned.SignFlagSet,
                flags,
                user);
        }
Пример #2
0
 private void SetFlag(ModelFlags flag, bool value)
 {
     if (value)
     {
         _modelFlags |= flag;
     }
     else
     {
         _modelFlags &= ~flag;
     }
 }
Пример #3
0
 public override System.Collections.Generic.Queue <Moonfish.Tags.BlamPointer> ReadFields(System.IO.BinaryReader binaryReader)
 {
     System.Collections.Generic.Queue <Moonfish.Tags.BlamPointer> pointerQueue = new System.Collections.Generic.Queue <Moonfish.Tags.BlamPointer>(base.ReadFields(binaryReader));
     this.Name = binaryReader.ReadStringID();
     this.NextSiblingNodeIndex             = binaryReader.ReadShortBlockIndex1();
     this.FirstChildNodeIndex              = binaryReader.ReadShortBlockIndex1();
     this.ParentNodeIndex                  = binaryReader.ReadShortBlockIndex1();
     this.AnimationGraphNodeModelFlags     = ((ModelFlags)(binaryReader.ReadByte()));
     this.AnimationGraphNodeNodeJointFlags = ((NodeJointFlags)(binaryReader.ReadByte()));
     this.BaseVector  = binaryReader.ReadVector3();
     this.VectorRange = binaryReader.ReadSingle();
     this.ZPos        = binaryReader.ReadSingle();
     return(pointerQueue);
 }
Пример #4
0
        private void SetFlag(ModelFlags flag, ModelFlags changedState, bool value)
        {
            var prev = GetFlag(flag); if (value)

            {
                _modelFlags |= flag;
            }
            else
            {
                _modelFlags &= ~flag;
            } if (prev != value)
            {
                _modelFlags |= changedState;
            }
        }
Пример #5
0
 public ModelSessionSetupRequest(
     ModelConnectionId connectionId,
     ModelSessionId sessionId,
     ModelSessionId previousSessionId,
     bool isSigned,
     ModelFlags flags,
     ModelUser user
     )
     : base(0)
 {
     this.connectionId      = connectionId;
     this.sessionId         = sessionId;
     this.previousSessionId = previousSessionId;
     this.isSigned          = isSigned;
     this.flags             = flags;
     this.user = user;
 }
Пример #6
0
 public MTBLEntry(int apiVersion, EventHandler handler, ulong modelIID, ulong baseFileNameHash, WidthAndMappingFlags widthAndMappingFlags, byte minimumWallHeight, byte numberOfLevels, byte unused, float thumbnailBoundsMinX, float thumbnailBoundsMinZ, float thumbnailBoundsMinY, float thumbnailBoundsMaxX, float thumbnailBoundsMaxZ, float thumbnailBoundsMaxY, ModelFlags modelFlags, ulong vfxHash)
     : base(apiVersion, handler)
 {
     this.modelIID             = modelIID;
     this.baseFileNameHash     = baseFileNameHash;
     this.widthAndMappingFlags = widthAndMappingFlags;
     this.minimumWallHeight    = minimumWallHeight;
     this.numberOfLevels       = numberOfLevels;
     this.unused = unused;
     this.thumbnailBoundsMinX = thumbnailBoundsMinX;
     this.thumbnailBoundsMinZ = thumbnailBoundsMinZ;
     this.thumbnailBoundsMinY = thumbnailBoundsMinY;
     this.thumbnailBoundsMaxX = thumbnailBoundsMaxX;
     this.thumbnailBoundsMaxZ = thumbnailBoundsMaxZ;
     this.thumbnailBoundsMaxY = thumbnailBoundsMaxY;
     this.modelFlags          = modelFlags;
     this.vfxHash             = vfxHash;
 }
Пример #7
0
            void Parse(Stream s)
            {
                var br = new BinaryReader(s);

                this.offset               = s.Position;
                this.modelIID             = br.ReadUInt64();
                this.baseFileNameHash     = br.ReadUInt64();
                this.widthAndMappingFlags = (WidthAndMappingFlags)br.ReadByte();
                this.minimumWallHeight    = br.ReadByte();
                this.numberOfLevels       = br.ReadByte();
                this.unused               = br.ReadByte();
                this.thumbnailBoundsMinX  = br.ReadSingle();
                this.thumbnailBoundsMinZ  = br.ReadSingle();
                this.thumbnailBoundsMinY  = br.ReadSingle();
                this.thumbnailBoundsMaxX  = br.ReadSingle();
                this.thumbnailBoundsMaxZ  = br.ReadSingle();
                this.thumbnailBoundsMaxY  = br.ReadSingle();
                this.modelFlags           = (ModelFlags)br.ReadUInt32();
                this.vfxHash              = br.ReadUInt64();
            }
 public ModelSessionSetupRequest(
     ModelConnectionId connectionId,
     ModelSessionId sessionId,
     ModelSessionId previousSessionId,
     bool isSigned,
     ModelFlags flags,
     ModelUser user
     )
     : base(0)
 {
     this.connectionId = connectionId;
     this.sessionId = sessionId;
     this.previousSessionId = previousSessionId;
     this.isSigned = isSigned;
     this.flags = flags;
     this.user = user;
 }
Пример #9
0
 private bool GetFlag(ModelFlags flag) => (_modelFlags & flag) != 0;
Пример #10
0
 internal void ClearSortUsageMode() => _modelFlags &= ~ModelFlags.SortUsageMode;
Пример #11
0
 internal void ClearChangedFlags() => _modelFlags  &= ~ModelFlags.AnyFilterSortChanged;
        public void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            ulong adapterSessionId;
            ulong adapterPreviousSessionId;
            Packet_Header_Flags_Values headerFlags;
            SESSION_SETUP_Request_Flags sessionSetupFlags;
            AccountCredential credential;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];

                // For sessionId is 0 which indicates session creation
                // assign a new one
                if (sessionId == ModelSessionId.ZeroSessionId)
                {
                    if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId))
                    {
                        sessionId = ModelSessionId.MainSessionId;
                    }
                    else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId))
                    {
                        sessionId = ModelSessionId.AlternativeSessionId;
                    }
                }
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}",
                sessionId, adapterSessionId);

            #endregion

            #region previousSessionId
            if (sessionTable.ContainsKey(previousSessionId))
            {
                adapterPreviousSessionId = sessionTable[previousSessionId];
            }
            else
            {
                Random r = new Random();
                adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}",
                sessionId, adapterPreviousSessionId);

            #endregion

            #region isSigned

            headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region flags

            switch (flags)
            {
                case ModelFlags.Binding:
                    {
                        sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING;
                        break;
                    }
                case ModelFlags.NotBinding:
                    {
                        sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE;
                        break;
                    }
                default:
                    throw new ArgumentException("flags");
            }

            #endregion

            #region user

            switch (user)
            {
                case ModelUser.DefaultUser:
                    {
                        credential = testConfig.AccountCredential;
                        break;
                    }
                case ModelUser.DiffUser:
                    {
                        credential = testConfig.NonAdminAccountCredential;
                        break;
                    }
                default:
                    throw new ArgumentException("user");
            }

            #endregion

            #region MultipleChannel
            // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family
            bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect);
            #endregion

            PrintCurrentSessionTable("Before SessionSetup Request");

            #region Send Request

            uint status;
            SESSION_SETUP_Response? sessionSetupResponse = null;
            string serverName = testConfig.SutComputerName;
            SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage;
            bool useServerGssToken = testConfig.UseServerGssToken;

            // Use desired explored sessionId
            ulong oldSessionId = connectionList[connectionId].SessionId;
            connectionList[connectionId].SessionId = adapterSessionId;

            // alternative connection and never session setup
            if (connectionId == ModelConnectionId.AlternativeConnection
                && sessionId == ModelSessionId.MainSessionId
                && connectionList[connectionId].SessionKey == null
                && connectionList.ContainsKey(ModelConnectionId.MainConnection))
            {
                connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true);
            }

            status = connectionList[connectionId].SessionSetup(
                headerFlags,
                sessionSetupFlags,
                adapterPreviousSessionId,
                securityPackageType,
                serverName,
                credential,
                useServerGssToken,
                isMultipleChannelSupported,
                (header, response) =>
                {
                    sessionSetupResponse = response;
                });

            if (status != Smb2Status.STATUS_SUCCESS
                && status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)
            {
                // Restore original sessionId if request failed
                connectionList[connectionId].SessionId = oldSessionId;
            }

            #endregion

            // Insert session to session table
            if (!sessionTable.ContainsKey(sessionId)
                && (status == Smb2Status.STATUS_SUCCESS
                || status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED))
            {
                sessionTable.Add(sessionId, connectionList[connectionId].SessionId);
            }

            PrintCurrentSessionTable("After SessionSetup Request");

            SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
        }
        public void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            ulong adapterSessionId;
            ulong adapterPreviousSessionId;
            Packet_Header_Flags_Values  headerFlags;
            SESSION_SETUP_Request_Flags sessionSetupFlags;
            AccountCredential           credential;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];

                // For sessionId is 0 which indicates session creation
                // assign a new one
                if (sessionId == ModelSessionId.ZeroSessionId)
                {
                    if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId))
                    {
                        sessionId = ModelSessionId.MainSessionId;
                    }
                    else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId))
                    {
                        sessionId = ModelSessionId.AlternativeSessionId;
                    }
                }
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}",
                sessionId, adapterSessionId);

            #endregion

            #region previousSessionId
            if (sessionTable.ContainsKey(previousSessionId))
            {
                adapterPreviousSessionId = sessionTable[previousSessionId];
            }
            else
            {
                Random r = new Random();
                adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}",
                sessionId, adapterPreviousSessionId);

            #endregion

            #region isSigned

            headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region flags

            switch (flags)
            {
            case ModelFlags.Binding:
            {
                sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING;
                break;
            }

            case ModelFlags.NotBinding:
            {
                sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE;
                break;
            }

            default:
                throw new ArgumentException("flags");
            }

            #endregion

            #region user

            switch (user)
            {
            case ModelUser.DefaultUser:
            {
                credential = testConfig.AccountCredential;
                break;
            }

            case ModelUser.DiffUser:
            {
                credential = testConfig.NonAdminAccountCredential;
                break;
            }

            default:
                throw new ArgumentException("user");
            }

            #endregion

            #region MultipleChannel
            // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family
            bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect);
            #endregion

            PrintCurrentSessionTable("Before SessionSetup Request");

            #region Send Request

            uint status;
            SESSION_SETUP_Response?sessionSetupResponse = null;
            string serverName = testConfig.SutComputerName;
            SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage;
            bool useServerGssToken = testConfig.UseServerGssToken;

            // Use desired explored sessionId
            ulong oldSessionId = connectionList[connectionId].SessionId;
            connectionList[connectionId].SessionId = adapterSessionId;

            // alternative connection and never session setup
            if (connectionId == ModelConnectionId.AlternativeConnection &&
                sessionId == ModelSessionId.MainSessionId &&
                connectionList[connectionId].SessionKey == null &&
                connectionList.ContainsKey(ModelConnectionId.MainConnection))
            {
                connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true);
            }

            status = connectionList[connectionId].SessionSetup(
                headerFlags,
                sessionSetupFlags,
                adapterPreviousSessionId,
                securityPackageType,
                serverName,
                credential,
                useServerGssToken,
                isMultipleChannelSupported,
                (header, response) =>
            {
                sessionSetupResponse = response;
            });

            if (status != Smb2Status.STATUS_SUCCESS &&
                status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)
            {
                // Restore original sessionId if request failed
                connectionList[connectionId].SessionId = oldSessionId;
            }

            #endregion

            // Insert session to session table
            if (!sessionTable.ContainsKey(sessionId) &&
                (status == Smb2Status.STATUS_SUCCESS ||
                 status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED))
            {
                sessionTable.Add(sessionId, connectionList[connectionId].SessionId);
            }

            PrintCurrentSessionTable("After SessionSetup Request");

            SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
        }
Пример #14
0
        public void Save(string path)
        {
            int nameLength, padding;

            CalculateExtents();

            using (BinaryWriter bw = new BinaryWriter(new FileStream(path, FileMode.Create)))
            {
                bw.Write(new byte[] { 0x45, 0x23 });    // Magic Number
                bw.Write(new byte[] { 2, 6 });          // Version (6.2)

                bw.Write(new byte[] { 0, 0, 0, 0 });    // Checksum, to calculate
                bw.Write((int)ModelFlags);

                int prepDataSize = 4 + (Faces.Count * 16) + 4 + (Vertices.Count * 44) + 2;

                for (int i = 0; i < Meshes.Count; i++)
                {
                    MDLMaterialGroup mesh = Meshes[i];

                    prepDataSize += 52;
                    prepDataSize += (4 * mesh.StripList.Count);

                    prepDataSize += 12;
                    prepDataSize += (4 * mesh.TriList.Count);
                }

                bw.Write(prepDataSize);            // PREP data size

                bw.Write(Faces.Count);             // USER face count
                bw.Write(Vertices.Count);          // USER vert count

                bw.Write(0);                       // Back filled post save

                bw.Write(Extents.Radius);
                bw.Write(Extents.Min.X);
                bw.Write(Extents.Min.Y);
                bw.Write(Extents.Min.Z);
                bw.Write(Extents.Max.X);
                bw.Write(Extents.Max.Y);
                bw.Write(Extents.Max.Z);
                bw.Write(Extents.Centre.X);
                bw.Write(Extents.Centre.Y);
                bw.Write(Extents.Centre.Z);

                bw.Write((short)Meshes.Count);

                for (int i = 0; i < Meshes.Count; i++)
                {
                    nameLength = Meshes[i].Name.Length;
                    padding    = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength + 4;

                    bw.Write(nameLength);
                    bw.WriteString(Meshes[i].Name);
                    bw.Write(new byte[padding]);
                }

                bw.Write(Faces.Count);

                for (int i = 0; i < Faces.Count; i++)
                {
                    bw.Write((short)Faces[i].MaterialID);
                    bw.Write((short)0);
                    bw.Write(Faces[i].Verts[0]);
                    bw.Write(Faces[i].Verts[1]);
                    bw.Write(Faces[i].Verts[2]);
                }

                bw.Write(Vertices.Count);

                for (int i = 0; i < Vertices.Count; i++)
                {
                    bw.Write(Vertices[i].Position.X);
                    bw.Write(Vertices[i].Position.Y);
                    bw.Write(Vertices[i].Position.Z);

                    bw.Write(Vertices[i].Normal.X);
                    bw.Write(Vertices[i].Normal.Y);
                    bw.Write(Vertices[i].Normal.Z);

                    bw.Write(Vertices[i].UV.X);
                    bw.Write(Vertices[i].UV.Y);

                    bw.Write(Vertices[i].UV2.X);
                    bw.Write(Vertices[i].UV2.Y);

                    bw.Write(Vertices[i].Colour.R);
                    bw.Write(Vertices[i].Colour.G);
                    bw.Write(Vertices[i].Colour.B);
                    bw.Write(Vertices[i].Colour.A);
                }

                bw.Write((short)Meshes.Count);

                for (int i = 0; i < Meshes.Count; i++)
                {
                    MDLMaterialGroup mesh = Meshes[i];

                    bw.Write(mesh.Extents.Centre.X);
                    bw.Write(mesh.Extents.Centre.Y);
                    bw.Write(mesh.Extents.Centre.Z);
                    bw.Write(mesh.Extents.Radius);
                    bw.Write(mesh.Extents.Min.X);
                    bw.Write(mesh.Extents.Min.Y);
                    bw.Write(mesh.Extents.Min.Z);
                    bw.Write(mesh.Extents.Max.X);
                    bw.Write(mesh.Extents.Max.Y);
                    bw.Write(mesh.Extents.Max.Z);

                    // TriangleStrips
                    bw.Write(mesh.StripOffset);
                    bw.Write(mesh.StripVertCount);
                    bw.Write(mesh.StripList.Count);

                    for (int j = 0; j < mesh.StripList.Count; j++)
                    {
                        bw.Write((uint)mesh.StripList[j].Index | (mesh.StripList[j].Degenerate ? 0x80000000 : 0x0));
                    }

                    bw.Write(mesh.TriListOffset);
                    bw.Write(mesh.TriListVertCount);
                    bw.Write(mesh.TriList.Count);

                    for (int j = 0; j < mesh.TriList.Count; j++)
                    {
                        bw.Write(mesh.TriList[j].Index);
                    }
                }

                if (ModelFlags.HasFlag(Flags.USERData))
                {
                    bw.Write(0);

                    for (int i = 0; i < Vertices.Count; i++)
                    {
                        bw.Write(Vertices[i].Position.X);
                        bw.Write(Vertices[i].Position.Y);
                        bw.Write(Vertices[i].Position.Z);
                        bw.Write(1);
                    }

                    for (int i = 0; i < Faces.Count; i++)
                    {
                        Vector3 v12 = Vertices[Faces[i].Verts[1]].Normal - Vertices[Faces[i].Verts[0]].Normal;
                        Vector3 v13 = Vertices[Faces[i].Verts[2]].Normal - Vertices[Faces[i].Verts[0]].Normal;
                        Vector3 n   = Vector3.Cross(v12, v13).Normalised;
                        float   d   = Vector3.Dot(n, Vertices[Faces[i].Verts[0]].Normal);

                        bw.Write(d);
                        bw.Write(n.X);
                        bw.Write(n.Y);
                        bw.Write(n.Z);
                        bw.Write(Vertices[Faces[i].Verts[0]].Normal.X);
                        bw.Write(Vertices[Faces[i].Verts[0]].Normal.Y);
                        bw.Write(Vertices[Faces[i].Verts[0]].Normal.Z);
                        bw.Write(Vertices[Faces[i].Verts[1]].Normal.X);
                        bw.Write(Vertices[Faces[i].Verts[1]].Normal.Y);
                        bw.Write(Vertices[Faces[i].Verts[1]].Normal.Z);
                        bw.Write(Vertices[Faces[i].Verts[2]].Normal.X);
                        bw.Write(Vertices[Faces[i].Verts[2]].Normal.Y);
                        bw.Write(Vertices[Faces[i].Verts[2]].Normal.Z);
                        bw.Write(Faces[i].MaterialID);
                        bw.Write(0);
                        bw.Write(Faces[i].Verts[0]);
                        bw.Write(Faces[i].Verts[1]);
                        bw.Write(Faces[i].Verts[2]);
                        bw.Write(Vertices[Faces[i].Verts[0]].Colour.R); bw.Write(Vertices[Faces[i].Verts[0]].Colour.G); bw.Write(Vertices[Faces[i].Verts[0]].Colour.B); bw.Write(Vertices[Faces[i].Verts[0]].Colour.A);
                        bw.Write(Vertices[Faces[i].Verts[1]].Colour.R); bw.Write(Vertices[Faces[i].Verts[1]].Colour.G); bw.Write(Vertices[Faces[i].Verts[1]].Colour.B); bw.Write(Vertices[Faces[i].Verts[1]].Colour.A);
                        bw.Write(Vertices[Faces[i].Verts[2]].Colour.R); bw.Write(Vertices[Faces[i].Verts[2]].Colour.G); bw.Write(Vertices[Faces[i].Verts[2]].Colour.B); bw.Write(Vertices[Faces[i].Verts[2]].Colour.A);
                        bw.Write(Vertices[Faces[i].Verts[0]].UV.X);
                        bw.Write(Vertices[Faces[i].Verts[0]].UV.Y);
                        bw.Write(Vertices[Faces[i].Verts[0]].UV2.X);
                        bw.Write(Vertices[Faces[i].Verts[0]].UV2.Y);
                        bw.Write(Vertices[Faces[i].Verts[1]].UV.X);
                        bw.Write(Vertices[Faces[i].Verts[1]].UV.Y);
                        bw.Write(Vertices[Faces[i].Verts[1]].UV2.X);
                        bw.Write(Vertices[Faces[i].Verts[1]].UV2.Y);
                        bw.Write(Vertices[Faces[i].Verts[2]].UV.X);
                        bw.Write(Vertices[Faces[i].Verts[2]].UV.Y);
                        bw.Write(Vertices[Faces[i].Verts[2]].UV2.X);
                        bw.Write(Vertices[Faces[i].Verts[2]].UV2.Y);
                        bw.Write((byte)0);
                        bw.Write(0);
                    }

                    for (int i = 0; i < Faces.Count; i++)
                    {
                        bw.Write(i);
                    }

                    bw.Write(Vertices.Count);

                    for (int i = 0; i < Vertices.Count; i++)
                    {
                        bw.Write(i);
                    }

                    if (ModelFlags.HasFlag(Flags.USERSkinData))
                    {
                    }
                }
            }

            using (BinaryWriter bw = new BinaryWriter(new FileStream(path, FileMode.Open)))
            {
                bw.Seek(24, SeekOrigin.Begin);
                bw.Write((int)(bw.BaseStream.Length - 28));
            }
        }