private TagResourceReference ConvertStructureBspTagResources(ScenarioStructureBsp bsp)
        {
            StructureBspTagResources resourceDefinition = BlamCache.ResourceCache.GetStructureBspTagResources(bsp.CollisionBspResource);

            // probably can remove all the code here

            if (resourceDefinition == null)
            {
                return(null);
            }

            if (BlamCache.Version < CacheVersion.Halo3ODST)
            {
                // convert surface planes
                foreach (var instance in resourceDefinition.InstancedGeometry)
                {
                    foreach (var surfacePlane in instance.SurfacePlanes)
                    {
                        surfacePlane.PlaneCountNew = surfacePlane.PlaneCountOld;
                        surfacePlane.PlaneIndexNew = surfacePlane.PlaneIndexOld;
                    }

                    foreach (var mopps in instance.CollisionMoppCodes)
                    {
                        mopps.Data.Elements = HavokConverter.ConvertMoppCodes(BlamCache.Version, CacheContext.Version, mopps.Data.Elements);
                    }
                }
            }

            bsp.CollisionBspResource = CacheContext.ResourceCache.CreateStructureBspResource(resourceDefinition);

            return(bsp.CollisionBspResource);
        }
Exemple #2
0
        public GeometryToObjectConverter(
            GameCacheHaloOnlineBase destCache, Stream destStream, GameCache sourceCache,
            Stream sourceStream, Scenario scenario, int structureBspIndex)
        {
            DestCache         = destCache;
            DestStream        = destStream;
            SourceCache       = sourceCache;
            SourceStream      = sourceStream;
            StructureBspIndex = structureBspIndex;
            PortTag           = new PortTagCommand(destCache, sourceCache);
            PortTag.SetFlags(PortTagCommand.PortingFlags.Default);

            Scenario          = scenario;
            StructureBspIndex = structureBspIndex;
            StructureBsp      = SourceCache.Deserialize <ScenarioStructureBsp>(SourceStream, Scenario.StructureBsps[structureBspIndex].StructureBsp);
            sLdT = SourceCache.Deserialize <ScenarioLightmap>(SourceStream, Scenario.Lightmap);

            if (SourceCache.Version >= CacheVersion.Halo3ODST)
            {
                Lbsp = SourceCache.Deserialize <ScenarioLightmapBspData>(SourceStream, sLdT.LightmapDataReferences[StructureBspIndex]);
            }
            else
            {
                Lbsp = sLdT.Lightmaps[StructureBspIndex];
            }

            var resourceDefinition = SourceCache.ResourceCache.GetRenderGeometryApiResourceDefinition(Lbsp.Geometry.Resource);

            Lbsp.Geometry.SetResourceBuffers(resourceDefinition);

            StructureBspResources = SourceCache.ResourceCache.GetStructureBspTagResources(StructureBsp.CollisionBspResource);
        }
Exemple #3
0
        public MoppDataCommand(ScenarioStructureBsp bsp) :
            base(true,

                 "MoppData",
                 "Modify Mopp data",

                 "MoppData <export/import/parse> <output/input file>",

                 "")
        {
            Definition = bsp;
        }
        public DumpMoppCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp bsp) :
            base(true,

                 "DumpMopp",
                 "Dumps bsp mopp.",

                 "DumpMopp <Output File>",

                 "")
        {
            CacheContext = cacheContext;
            Definition   = bsp;
        }
        public MoppDataCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp bsp) :
            base(true,

                 "MoppData",
                 "Modify Mopp data",

                 "MoppData <export/import/parse> <output/input file>",

                 "")
        {
            CacheContext = cacheContext;
            Definition   = bsp;
        }
        public ExtractPathfindingGeometryCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) :
            base(true,

                 "ExtractPathfindingGeometry",
                 "",

                 "ExtractPathfindingGeometry <OBJ File>",

                 "")
        {
            CacheContext = cacheContext;
            Definition   = definition;
        }
Exemple #7
0
        public ExtractCollisionGeometryCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) :
            base(false,

                 "ExtractCollisionGeometry",
                 "",

                 "ExtractCollisionGeometry <OBJ File>",

                 "")
        {
            CacheContext = cacheContext;
            Definition   = definition;
        }
Exemple #8
0
        public ExtractPathfindingGeometryCommand(GameCache cache, ScenarioStructureBsp definition) :
            base(true,

                 "ExtractPathfindingGeometry",
                 "",

                 "ExtractPathfindingGeometry <OBJ File>",

                 "")
        {
            Cache      = cache;
            Definition = definition;
        }
Exemple #9
0
        public GenerateJumpHintsCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) :
            base(true,

                 "GenerateJumpHints",
                 "Generates jump hint data for pre-ODST bsp pathfinding data.",

                 "GenerateJumpHints",

                 "Generates jump hint data for pre-ODST bsp pathfinding data.")
        {
            CacheContext = cacheContext;
            Definition   = definition;
        }
        public GenerateJumpHintsCommand(GameCache cache, CachedTag tag, ScenarioStructureBsp definition) :
            base(true,

                 "GenerateJumpHints",
                 "Generates jump hint data for pre-ODST bsp pathfinding data.",

                 "GenerateJumpHints",

                 "Generates jump hint data for pre-ODST bsp pathfinding data.")
        {
            Cache      = cache;
            Definition = definition;
            Tag        = tag;
        }
        public ExtractRenderGeometryCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition)
            : base(true,

                   "ExtractRenderGeometry",
                   "Extracts render geometry from the current scenario_structure_bsp definition.",

                   "ExtractRenderGeometry <filetype> <filename>",

                   "Extracts render geometry from the current scenario_structure_bsp definition.\n" +
                   "Supported file types: obj")
        {
            CacheContext = cacheContext;
            Definition   = definition;
        }
        public LocalizeTagResourcesCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition, CachedTagInstance tag) :
            base(true,

                 "LocalizeTagResources",
                 "",

                 "LocalizeTagResources",

                 "")
        {
            CacheContext = cacheContext;
            Definition   = definition;
            Tag          = tag;
        }
Exemple #13
0
        public CollisionTestCommand(HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp bsp)
            : base(true,

                   "CollisionTest",
                   "A test resource-loading command for 'sbsp' tag collision.",

                   "collision-test",

                   "A test resource-loading command for 'sbsp' tag collision.")
        {
            CacheContext = cacheContext;
            Tag          = tag;
            BSP          = bsp;
        }
Exemple #14
0
        public ResourceDataCommand(HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp definition)
            : base(false,

                   "ResourceData",
                   "SbspResource Extract/Import <Resource Type> <Filename>",

                   "ResourceData Extract/Import a sbsp resource.",

                   "Extract/Import a sbsp resource. Resource types: \n" +
                   "Geometry \n" +
                   "Geometry2 \n" +
                   "CollisionBspResource \n" +
                   "PathfindingResource \n")
        {
            CacheContext = cacheContext;
            Tag          = tag;
            Definition   = definition;
        }
        public static CommandContext Create(CommandContext parent, HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp bsp)
        {
            var groupName = cacheContext.GetString(tag.Group.Name);

            var context = new CommandContext(parent,
                                             string.Format("{0:X8}.{1}", tag.Index, groupName));

            Populate(context, cacheContext, tag, bsp);

            return(context);
        }
Exemple #16
0
        private PageableResource ConvertStructureBspTagResources(ScenarioStructureBsp bsp, Dictionary <ResourceLocation, Stream> resourceStreams)
        {
            //
            // Set up ElDorado resource reference
            //

            bsp.CollisionBspResource = new PageableResource
            {
                Page = new RawPage
                {
                    Index = -1
                },
                Resource = new TagResourceGen3
                {
                    ResourceType             = TagResourceTypeGen3.Collision,
                    DefinitionData           = new byte[0x30],
                    DefinitionAddress        = new CacheResourceAddress(CacheResourceAddressType.Definition, 0),
                    ResourceFixups           = new List <TagResourceGen3.ResourceFixup>(),
                    ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(),
                    Unknown2 = 1
                }
            };

            //
            // Port Blam resource definition
            //

            var resourceEntry = BlamCache.ResourceGestalt.TagResources[bsp.ZoneAssetIndex3.Index];

            bsp.CollisionBspResource.Resource.DefinitionAddress = resourceEntry.DefinitionAddress;
            bsp.CollisionBspResource.Resource.DefinitionData    = BlamCache.ResourceGestalt.FixupInformation.Skip(resourceEntry.FixupInformationOffset).Take(resourceEntry.FixupInformationLength).ToArray();

            StructureBspTagResources resourceDefinition = null;

            using (var definitionStream = new MemoryStream(bsp.CollisionBspResource.Resource.DefinitionData, true))
                using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian))
                    using (var definitionWriter = new EndianWriter(definitionStream, EndianFormat.BigEndian))
                    {
                        foreach (var fixup in resourceEntry.ResourceFixups)
                        {
                            var newFixup = new TagResourceGen3.ResourceFixup
                            {
                                BlockOffset = (uint)fixup.BlockOffset,
                                Address     = new CacheResourceAddress(
                                    fixup.Type == 4 ?
                                    CacheResourceAddressType.Resource :
                                    CacheResourceAddressType.Definition,
                                    fixup.Offset)
                            };

                            definitionStream.Position = newFixup.BlockOffset;
                            definitionWriter.Write(newFixup.Address.Value);

                            bsp.CollisionBspResource.Resource.ResourceFixups.Add(newFixup);
                        }

                        var dataContext = new DataSerializationContext(definitionReader, definitionWriter, CacheResourceAddressType.Definition);

                        definitionStream.Position = bsp.CollisionBspResource.Resource.DefinitionAddress.Offset;
                        resourceDefinition        = BlamCache.Deserializer.Deserialize <StructureBspTagResources>(dataContext);

                        //
                        // Apply game-specific fixes to the resource definition
                        //

                        if (BlamCache.Version < CacheVersion.Halo3ODST)
                        {
                            resourceDefinition.LargeCollisionBsps = new List <StructureBspTagResources.LargeCollisionBspBlock>();
                            resourceDefinition.HavokData          = new List <StructureBspTagResources.HavokDatum>();
                        }

                        foreach (var instance in resourceDefinition.InstancedGeometry)
                        {
                            instance.Unknown5 = new TagBlock <StructureBspTagResources.InstancedGeometryBlock.Unknown4Block>();
                            instance.Unknown2 = new TagBlock <StructureBspTagResources.InstancedGeometryBlock.Unknown2Block>();
                        }
                    }

            //
            // Load Blam resource data
            //

            var resourceData = BlamCache.GetRawFromID(bsp.ZoneAssetIndex3);

            if (resourceData == null)
            {
                CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, bsp.CollisionBspResource), resourceDefinition);
                return(bsp.CollisionBspResource);
            }

            //
            // Port Blam resource to ElDorado resource cache
            //

            using (var blamResourceStream = resourceData != null ? new MemoryStream(resourceData) : new MemoryStream())
                using (var resourceReader = new EndianReader(blamResourceStream, EndianFormat.BigEndian))
                    using (var dataStream = new MemoryStream())
                        using (var resourceWriter = new EndianWriter(dataStream, EndianFormat.LittleEndian))
                        {
                            var dataContext = new DataSerializationContext(resourceReader, resourceWriter);

                            foreach (var collisionBsp in resourceDefinition.CollisionBsps)
                            {
                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position     = collisionBsp.Bsp3dNodes.Address.Offset;
                                collisionBsp.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Bsp3dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp3dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position = collisionBsp.Planes.Address.Offset;
                                collisionBsp.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Planes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position = collisionBsp.Leaves.Address.Offset;
                                collisionBsp.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Leaves.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position          = collisionBsp.Bsp2dReferences.Address.Offset;
                                collisionBsp.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Bsp2dReferences.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dReference>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position     = collisionBsp.Bsp2dNodes.Address.Offset;
                                collisionBsp.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Bsp2dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position   = collisionBsp.Surfaces.Address.Offset;
                                collisionBsp.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Surfaces.Count; i++)
                                {
                                    var surface = BlamCache.Deserializer.Deserialize <CollisionGeometry.Surface>(dataContext);
                                    CacheContext.Serializer.Serialize(dataContext, surface);
                                }

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position = collisionBsp.Edges.Address.Offset;
                                collisionBsp.Edges.Address  = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Edges.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Edge>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position   = collisionBsp.Vertices.Address.Offset;
                                collisionBsp.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < collisionBsp.Vertices.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Vertex>(dataContext));
                                }
                            }

                            foreach (var largeCollisionBsp in resourceDefinition.LargeCollisionBsps)
                            {
                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position          = largeCollisionBsp.Bsp3dNodes.Address.Offset;
                                largeCollisionBsp.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Bsp3dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position      = largeCollisionBsp.Planes.Address.Offset;
                                largeCollisionBsp.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Planes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position      = largeCollisionBsp.Leaves.Address.Offset;
                                largeCollisionBsp.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Leaves.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position = largeCollisionBsp.Bsp2dReferences.Address.Offset;
                                largeCollisionBsp.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Bsp2dReferences.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position          = largeCollisionBsp.Bsp2dNodes.Address.Offset;
                                largeCollisionBsp.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Bsp2dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position        = largeCollisionBsp.Surfaces.Address.Offset;
                                largeCollisionBsp.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Surfaces.Count; i++)
                                {
                                    var surface = BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Surface>(dataContext);
                                    // surface.Material = PortGlobalMaterialIndex(CacheContext, BlamCache, surface.Material);
                                    CacheContext.Serializer.Serialize(dataContext, surface);
                                }

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position     = largeCollisionBsp.Edges.Address.Offset;
                                largeCollisionBsp.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Edges.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Edge>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position        = largeCollisionBsp.Vertices.Address.Offset;
                                largeCollisionBsp.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < largeCollisionBsp.Vertices.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Vertex>(dataContext));
                                }
                            }

                            foreach (var instance in resourceDefinition.InstancedGeometry)
                            {
                                StreamUtil.Align(dataStream, 0x10); // 0x8 > 0x10
                                blamResourceStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset;
                                instance.CollisionInfo.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp3dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position           = instance.CollisionInfo.Planes.Address.Offset;
                                instance.CollisionInfo.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position           = instance.CollisionInfo.Leaves.Address.Offset;
                                instance.CollisionInfo.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset;
                                instance.CollisionInfo.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dReference>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset;
                                instance.CollisionInfo.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position             = instance.CollisionInfo.Surfaces.Address.Offset;
                                instance.CollisionInfo.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++)
                                {
                                    var surface = BlamCache.Deserializer.Deserialize <CollisionGeometry.Surface>(dataContext);
                                    // surface.Material = PortGlobalMaterialIndex(CacheContext, BlamCache, surface.Material);
                                    CacheContext.Serializer.Serialize(dataContext, surface);
                                }

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position          = instance.CollisionInfo.Edges.Address.Offset;
                                instance.CollisionInfo.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Edge>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x10);
                                blamResourceStream.Position             = instance.CollisionInfo.Vertices.Address.Offset;
                                instance.CollisionInfo.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Vertex>(dataContext));
                                }

                                foreach (var collisionGeometry in instance.CollisionGeometries)
                                {
                                    StreamUtil.Align(dataStream, 0x10); // 0x8 > 0x10
                                    blamResourceStream.Position          = collisionGeometry.Bsp3dNodes.Address.Offset;
                                    collisionGeometry.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Bsp3dNodes.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp3dNode>(dataContext));
                                    }

                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position      = collisionGeometry.Planes.Address.Offset;
                                    collisionGeometry.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Planes.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext));
                                    }

                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position      = collisionGeometry.Leaves.Address.Offset;
                                    collisionGeometry.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Leaves.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext));
                                    }

                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position = collisionGeometry.Bsp2dReferences.Address.Offset;
                                    collisionGeometry.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Bsp2dReferences.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dReference>(dataContext));
                                    }

                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position          = collisionGeometry.Bsp2dNodes.Address.Offset;
                                    collisionGeometry.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Bsp2dNodes.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dNode>(dataContext));
                                    }

                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position        = collisionGeometry.Surfaces.Address.Offset;
                                    collisionGeometry.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Surfaces.Count; i++)
                                    {
                                        var surface = BlamCache.Deserializer.Deserialize <CollisionGeometry.Surface>(dataContext);
                                        // surface.Material = PortGlobalMaterialIndex(CacheContext, BlamCache, surface.Material);
                                        CacheContext.Serializer.Serialize(dataContext, surface);
                                    }

                                    StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                    blamResourceStream.Position     = collisionGeometry.Edges.Address.Offset;
                                    collisionGeometry.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Edges.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Edge>(dataContext));
                                    }

                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position        = collisionGeometry.Vertices.Address.Offset;
                                    collisionGeometry.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    for (var i = 0; i < collisionGeometry.Vertices.Count; i++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Vertex>(dataContext));
                                    }
                                }

                                foreach (var moppCode in instance.BspPhysics)
                                {
                                    StreamUtil.Align(dataStream, 0x10);
                                    blamResourceStream.Position = moppCode.Data.Address.Offset;
                                    moppCode.Data.Address       = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                    var moppData = resourceReader.ReadBytes(moppCode.Data.Count).Select(i => new CollisionMoppCode.Datum {
                                        Value = i
                                    }).ToList();
                                    if (BlamCache.Version < CacheVersion.Halo3ODST)
                                    {
                                        moppData = ConvertCollisionMoppData(moppData);
                                    }
                                    resourceWriter.Write(moppData.Select(i => i.Value).ToArray());
                                }

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position = instance.Unknown1.Address.Offset;
                                instance.Unknown1.Address   = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.Unknown1.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.InstancedGeometryBlock.Unknown1Block>(dataContext));
                                }

                                /*
                                 * StreamUtil.Align(dataStream, 0x4); // 0x4 > 0x10
                                 * blamResourceStream.Position = instance.Unknown2.Address.Offset;
                                 * instance.Unknown2.Address = new CacheAddress(CacheAddressType.Resource, (int)dataStream.Position);
                                 * for (var i = 0; i < instance.Unknown2.Count; i++)
                                 * {
                                 *  var element = BlamCache.Deserializer.Deserialize<StructureBspTagResources.InstancedGeometryBlock.Unknown2Block>(dataContext);
                                 *  if (BlamCache.Version <= CacheVersion.Halo3ODST)
                                 *  {
                                 *      element.Unknown1 = element.Unknown1_H3;
                                 *      element.Unknown2 = element.Unknown2_H3;
                                 *  }
                                 *  CacheContext.Serializer.Serialize(dataContext, element);
                                 */

                                StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10
                                blamResourceStream.Position = instance.Unknown3.Address.Offset;
                                instance.Unknown3.Address   = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);
                                for (var i = 0; i < instance.Unknown3.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.InstancedGeometryBlock.Unknown3Block>(dataContext));
                                }
                            }

                            dataStream.Position = 0;

                            CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, bsp.CollisionBspResource), resourceDefinition);

                            bsp.CollisionBspResource.ChangeLocation(ResourceLocation.ResourcesB);
                            var resource = bsp.CollisionBspResource;

                            if (resource == null)
                            {
                                throw new ArgumentNullException("resource");
                            }

                            if (!dataStream.CanRead)
                            {
                                throw new ArgumentException("The input stream is not open for reading", "dataStream");
                            }

                            var cache = CacheContext.GetResourceCache(ResourceLocation.ResourcesB);

                            if (!resourceStreams.ContainsKey(ResourceLocation.ResourcesB))
                            {
                                resourceStreams[ResourceLocation.ResourcesB] = FlagIsSet(PortingFlags.Memory) ?
                                                                               new MemoryStream() :
                                                                               (Stream)CacheContext.OpenResourceCacheReadWrite(ResourceLocation.ResourcesB);

                                if (FlagIsSet(PortingFlags.Memory))
                                {
                                    using (var resourceStream = CacheContext.OpenResourceCacheRead(ResourceLocation.ResourcesB))
                                        resourceStream.CopyTo(resourceStreams[ResourceLocation.ResourcesB]);
                                }
                            }

                            var dataSize = (int)(dataStream.Length - dataStream.Position);
                            var data     = new byte[dataSize];
                            dataStream.Read(data, 0, dataSize);

                            resource.Page.Index = cache.Add(resourceStreams[ResourceLocation.ResourcesB], data, out uint compressedSize);
                            resource.Page.CompressedBlockSize   = compressedSize;
                            resource.Page.UncompressedBlockSize = (uint)dataSize;
                            resource.DisableChecksum();
                        }

            return(bsp.CollisionBspResource);
        }
Exemple #17
0
        private static bool ImportResource(ScenarioStructureBsp Definition, HaloOnlineCacheContext CacheContext, IReadOnlyList <string> args)
        {
            if (args.Count != 4)
            {
                return(false);
            }

            var location         = args[1].Split(".".ToCharArray()).Length == 2 ? args[1].Split(".".ToCharArray())[0] : args[1]; // resources.dat or resources
            var resourceType     = args[2].ToLower();                                                                            // geometry2
            var filePath         = args[3];                                                                                      // sc140_000_geometry2.raw
            var resourceLocation = ResourceLocation.Resources;

            switch (location)
            {
            case "audio":
                resourceLocation = ResourceLocation.Audio;
                break;

            case "resources":
                resourceLocation = ResourceLocation.Resources;
                break;

            case "resources_b":
            case "video":
                resourceLocation = ResourceLocation.ResourcesB;
                break;

            case "textures":
                resourceLocation = ResourceLocation.Textures;
                break;

            case "textures_b":
                resourceLocation = ResourceLocation.TexturesB;
                break;

            case "lightmaps":
                resourceLocation = ResourceLocation.Lightmaps;
                break;

            case "render_models":
                resourceLocation = ResourceLocation.RenderModels;
                break;

            default:
                Console.WriteLine($"ERROR: Cache location is incorrect.");
                return(false);
            }

            using (var stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite))
            {
                switch (resourceType)
                {
                case "geometry":
                    Definition.Geometry.Resource.ChangeLocation(resourceLocation);
                    CacheContext.AddResource(Definition.Geometry.Resource, stream);
                    Console.WriteLine($"New Geometry resource index = {Definition.Geometry.Resource.Page.Index:X4}; {Definition.Geometry.Resource.Page.Index:D4}");
                    break;

                case "geometry2":
                    Definition.Geometry2.Resource.ChangeLocation(resourceLocation);
                    CacheContext.AddResource(Definition.Geometry2.Resource, stream);
                    Console.WriteLine($"New Geometry2 resource index = {Definition.Geometry2.Resource.Page.Index:X4}; {Definition.Geometry2.Resource.Page.Index:D4}");
                    break;

                case "collisionbspresource":
                    Definition.CollisionBspResource.ChangeLocation(resourceLocation);
                    CacheContext.AddResource(Definition.CollisionBspResource, stream);
                    Console.WriteLine($"New CollisionBspResource resource index = {Definition.CollisionBspResource.Page.Index:X4}; {Definition.CollisionBspResource.Page.Index:D4}");
                    break;

                case "pathfindingresource":
                    Definition.PathfindingResource.ChangeLocation(resourceLocation);
                    CacheContext.AddResource(Definition.PathfindingResource, stream);
                    Console.WriteLine($"New PathfindingResource resource index = {Definition.PathfindingResource.Page.Index:X4}; {Definition.PathfindingResource.Page.Index:D4}");
                    break;

                default:
                    Console.WriteLine("ERROR: Unrecognized resource type");
                    return(false);
                }
                Console.WriteLine("Done.");
            }

            return(true);
        }
 public static void Populate(CommandContext commandContext, HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp bsp)
 {
     commandContext.AddCommand(new CollisionTestCommand(cacheContext, tag, bsp));
     commandContext.AddCommand(new ResourceDataCommand(cacheContext, tag, bsp));
     commandContext.AddCommand(new ExtractCollisionGeometryCommand(cacheContext, bsp));
     commandContext.AddCommand(new ExtractRenderGeometryCommand(cacheContext, bsp));
     commandContext.AddCommand(new DumpRenderGeometryCommand(cacheContext, bsp.Geometry, "Decorator"));
     commandContext.AddCommand(new DumpRenderGeometryCommand(cacheContext, bsp.Geometry2, "Bsp"));
     commandContext.AddCommand(new DumpMoppCommand(cacheContext, bsp));
     commandContext.AddCommand(new MoppDataCommand(cacheContext, bsp));
 }
        private ScenarioStructureBsp ConvertScenarioStructureBsp(ScenarioStructureBsp sbsp, CachedTag instance, Dictionary <ResourceLocation, Stream> resourceStreams)
        {
            var converter = new RenderGeometryConverter(CacheContext, BlamCache);   // should be made static

            var blamDecoratorResourceDefinition = BlamCache.ResourceCache.GetRenderGeometryApiResourceDefinition(sbsp.DecoratorGeometry.Resource);
            var blamGeometryResourceDefinition  = BlamCache.ResourceCache.GetRenderGeometryApiResourceDefinition(sbsp.Geometry.Resource);

            var decoratorGeometry = converter.Convert(sbsp.DecoratorGeometry, blamDecoratorResourceDefinition);
            var geometry          = converter.Convert(sbsp.Geometry, blamGeometryResourceDefinition);

            foreach (var cluster in sbsp.Clusters)
            {
                List <ScenarioStructureBsp.Cluster.DecoratorGrid> newDecoratorGrids = new List <ScenarioStructureBsp.Cluster.DecoratorGrid>();

                foreach (var grid in cluster.DecoratorGrids)
                {
                    var buffer = blamDecoratorResourceDefinition.VertexBuffers[grid.Gen3Info.VertexBufferIndex].Definition;
                    var offset = grid.VertexBufferOffset;

                    grid.Vertices = new List <TinyPositionVertex>();
                    using (var stream = new MemoryStream(buffer.Data.Data))
                    {
                        var vertexStream = VertexStreamFactory.Create(BlamCache.Version, stream);
                        stream.Position = offset;

                        for (int i = 0; i < grid.Amount; i++)
                        {
                            grid.Vertices.Add(vertexStream.ReadTinyPositionVertex());
                        }
                    }

                    if (grid.Amount == 0)
                    {
                        newDecoratorGrids.Add(grid);
                    }
                    else
                    {
                        // Get the new grids
                        var newGrids = ConvertDecoratorGrid(grid.Vertices, grid);

                        // Add all to list
                        foreach (var newGrid in newGrids)
                        {
                            newDecoratorGrids.Add(newGrid);
                        }
                    }
                }
                cluster.DecoratorGrids = newDecoratorGrids;
            }

            // convert all the decorator vertex buffers
            foreach (var d3dBuffer in blamDecoratorResourceDefinition.VertexBuffers)
            {
                VertexBufferConverter.ConvertVertexBuffer(BlamCache.Version, CacheContext.Version, d3dBuffer.Definition);
                decoratorGeometry.VertexBuffers.Add(d3dBuffer);
            }

            sbsp.DecoratorGeometry.Resource = CacheContext.ResourceCache.CreateRenderGeometryApiResource(decoratorGeometry);
            sbsp.Geometry.Resource          = CacheContext.ResourceCache.CreateRenderGeometryApiResource(geometry);

            sbsp.CollisionBspResource = ConvertStructureBspTagResources(sbsp);
            sbsp.PathfindingResource  = ConvertStructureBspCacheFileTagResources(sbsp);

            sbsp.Unknown86 = 1;

            //
            // Set compatibility flag for H3 mopps for the engine to perform some fixups just in time
            //

            if (BlamCache.Version == CacheVersion.Halo3Retail || BlamCache.Version == CacheVersion.Halo3Beta)
            {
                sbsp.CompatibilityFlags |= ScenarioStructureBsp.StructureBspCompatibilityValue.UseMoppIndexPatch;
            }

            //
            // Temporary Fixes:
            //

            // Without this 005_intro crash on cortana sbsp
            sbsp.Geometry.MeshClusterVisibility = new List <RenderGeometry.MoppClusterVisiblity>();

            return(sbsp);
        }
        private PageableResource ConvertStructureBspCacheFileTagResources(ScenarioStructureBsp bsp, Dictionary <ResourceLocation, Stream> resourceStreams)
        {
            //
            // Set up ElDorado resource reference
            //

            bsp.PathfindingResource = new PageableResource
            {
                Page = new RawPage
                {
                    Index = -1
                },
                Resource = new TagResourceGen3
                {
                    ResourceType             = TagResourceTypeGen3.Pathfinding,
                    DefinitionData           = new byte[0x30],
                    DefinitionAddress        = new CacheResourceAddress(CacheResourceAddressType.Definition, 0),
                    ResourceFixups           = new List <TagResourceGen3.ResourceFixup>(),
                    ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(),
                    Unknown2 = 1
                }
            };

            //
            // Load Blam resource data
            //

            var resourceData = BlamCache.Version > CacheVersion.Halo3Retail ?
                               BlamCache.GetRawFromID(bsp.ZoneAssetIndex4) :
                               null;

            if (resourceData == null)
            {
                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                {
                    return(bsp.PathfindingResource);
                }

                resourceData = new byte[0x30];
            }

            //
            // Port Blam resource definition
            //

            StructureBspCacheFileTagResources resourceDefinition = null;

            if (BlamCache.Version >= CacheVersion.Halo3ODST)
            {
                var resourceEntry = BlamCache.ResourceGestalt.TagResources[bsp.ZoneAssetIndex4.Index];

                bsp.PathfindingResource.Resource.DefinitionAddress = resourceEntry.DefinitionAddress;
                bsp.PathfindingResource.Resource.DefinitionData    = BlamCache.ResourceGestalt.FixupInformation.Skip(resourceEntry.FixupInformationOffset).Take(resourceEntry.FixupInformationLength).ToArray();

                using (var definitionStream = new MemoryStream(bsp.PathfindingResource.Resource.DefinitionData, true))
                    using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian))
                        using (var definitionWriter = new EndianWriter(definitionStream, EndianFormat.BigEndian))
                        {
                            foreach (var fixup in resourceEntry.ResourceFixups)
                            {
                                var newFixup = new TagResourceGen3.ResourceFixup
                                {
                                    BlockOffset = (uint)fixup.BlockOffset,
                                    Address     = new CacheResourceAddress(
                                        fixup.Type == 4 ?
                                        CacheResourceAddressType.Resource :
                                        CacheResourceAddressType.Definition,
                                        fixup.Offset)
                                };

                                definitionStream.Position = newFixup.BlockOffset;
                                definitionWriter.Write(newFixup.Address.Value);

                                bsp.PathfindingResource.Resource.ResourceFixups.Add(newFixup);
                            }

                            var dataContext = new DataSerializationContext(definitionReader, definitionWriter, CacheResourceAddressType.Definition);

                            definitionStream.Position = bsp.PathfindingResource.Resource.DefinitionAddress.Offset;
                            resourceDefinition        = BlamCache.Deserializer.Deserialize <StructureBspCacheFileTagResources>(dataContext);
                        }
            }
            else
            {
                resourceDefinition = new StructureBspCacheFileTagResources()
                {
                    SurfacePlanes   = new TagBlock <ScenarioStructureBsp.SurfacesPlanes>(bsp.SurfacePlanes.Count, new CacheResourceAddress()),
                    Planes          = new TagBlock <ScenarioStructureBsp.Plane>(bsp.Planes.Count, new CacheResourceAddress()),
                    EdgeToSeams     = new TagBlock <ScenarioStructureBsp.EdgeToSeamMapping>(bsp.EdgeToSeams.Count, new CacheResourceAddress()),
                    PathfindingData = new List <StructureBspCacheFileTagResources.PathfindingDatum>() // TODO: copy from bsp.PathfindingData...
                };
            }

            //
            // Port Blam resource to ElDorado resource cache
            //

            using (var blamResourceStream = new MemoryStream(resourceData))
                using (var resourceReader = new EndianReader(blamResourceStream, EndianFormat.BigEndian))
                    using (var dataStream = new MemoryStream())
                        using (var resourceWriter = new EndianWriter(dataStream, EndianFormat.LittleEndian))
                        {
                            var dataContext = new DataSerializationContext(resourceReader, resourceWriter);

                            //
                            // Surfaces Planes
                            //

                            StreamUtil.Align(dataStream, 0x4);

                            if (BlamCache.Version >= CacheVersion.Halo3ODST)
                            {
                                blamResourceStream.Position = resourceDefinition.SurfacePlanes.Address.Offset;
                            }

                            resourceDefinition.SurfacePlanes = new TagBlock <ScenarioStructureBsp.SurfacesPlanes>(
                                (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.SurfacePlanes.Count : resourceDefinition.SurfacePlanes.Count),
                                new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));

                            for (var i = 0; i < resourceDefinition.SurfacePlanes.Count; i++)
                            {
                                var element = BlamCache.Version < CacheVersion.Halo3ODST ?
                                              bsp.SurfacePlanes[i] :
                                              BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.SurfacesPlanes>(dataContext);

                                if (BlamCache.Version < CacheVersion.Halo3ODST)
                                {
                                    element.PlaneIndexNew = element.PlaneIndexOld;
                                    element.PlaneCountNew = element.PlaneCountOld;
                                }

                                CacheContext.Serializer.Serialize(dataContext, element);
                            }

                            //
                            // UnknownRaw1sts
                            //

                            StreamUtil.Align(dataStream, 0x4);

                            if (BlamCache.Version >= CacheVersion.Halo3ODST)
                            {
                                blamResourceStream.Position = resourceDefinition.Planes.Address.Offset;
                            }

                            resourceDefinition.Planes = new TagBlock <ScenarioStructureBsp.Plane>(
                                (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.Planes.Count : resourceDefinition.Planes.Count),
                                new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));

                            for (var i = 0; i < resourceDefinition.Planes.Count; i++)
                            {
                                var element = BlamCache.Version < CacheVersion.Halo3ODST ?
                                              bsp.Planes[i] :
                                              BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.Plane>(dataContext);

                                CacheContext.Serializer.Serialize(dataContext, element);
                            }

                            //
                            // UnknownRaw7ths
                            //

                            StreamUtil.Align(dataStream, 0x4);

                            if (BlamCache.Version >= CacheVersion.Halo3ODST)
                            {
                                blamResourceStream.Position = resourceDefinition.EdgeToSeams.Address.Offset;
                            }

                            resourceDefinition.EdgeToSeams = new TagBlock <ScenarioStructureBsp.EdgeToSeamMapping>(
                                (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.EdgeToSeams.Count : resourceDefinition.EdgeToSeams.Count),
                                new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));

                            for (var i = 0; i < resourceDefinition.EdgeToSeams.Count; i++)
                            {
                                var element = BlamCache.Version < CacheVersion.Halo3ODST ?
                                              bsp.EdgeToSeams[i] :
                                              BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.EdgeToSeamMapping>(dataContext);

                                CacheContext.Serializer.Serialize(dataContext, element);
                            }

                            if (BlamCache.Version < CacheVersion.Halo3ODST && bsp.PathfindingData.Count != 0)
                            {
                                var pathfinding = new StructureBspCacheFileTagResources.PathfindingDatum()
                                {
                                    StructureChecksum = bsp.PathfindingData[0].StructureChecksum,
                                    ObjectReferences  = new List <StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference>(),
                                    Seams             = new List <StructureBspCacheFileTagResources.PathfindingDatum.Seam>(),
                                    JumpSeams         = new List <StructureBspCacheFileTagResources.PathfindingDatum.JumpSeam>()
                                };

                                foreach (var oldObjectReference in bsp.PathfindingData[0].ObjectReferences)
                                {
                                    var objectReference = new StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference
                                    {
                                        Flags          = oldObjectReference.Flags,
                                        Bsps           = new List <StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference.BspReference>(),
                                        ObjectUniqueID = oldObjectReference.ObjectUniqueID,
                                        OriginBspIndex = oldObjectReference.OriginBspIndex,
                                        ObjectType     = oldObjectReference.ObjectType.DeepClone(),
                                        Source         = oldObjectReference.Source
                                    };

                                    foreach (var bspRef in oldObjectReference.Bsps)
                                    {
                                        objectReference.Bsps.Add(new StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference.BspReference
                                        {
                                            BspIndex     = bspRef.BspIndex,
                                            NodeIndex    = bspRef.NodeIndex,
                                            Bsp2dRefs    = new TagBlock <ScenarioStructureBsp.PathfindingDatum.ObjectReference.BspReference.Bsp2dRef>(bspRef.Bsp2dRefs.Count, new CacheResourceAddress()),
                                            VertexOffset = bspRef.VertexOffset
                                        });
                                    }

                                    pathfinding.ObjectReferences.Add(objectReference);
                                }

                                foreach (var oldSeam in bsp.PathfindingData[0].Seams)
                                {
                                    pathfinding.Seams.Add(new StructureBspCacheFileTagResources.PathfindingDatum.Seam
                                    {
                                        LinkIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Seam.LinkIndexBlock>(
                                            oldSeam.LinkIndices.Count, new CacheResourceAddress())
                                    });
                                }

                                foreach (var oldJumpSeam in bsp.PathfindingData[0].JumpSeams)
                                {
                                    pathfinding.JumpSeams.Add(new StructureBspCacheFileTagResources.PathfindingDatum.JumpSeam
                                    {
                                        UserJumpIndex = oldJumpSeam.UserJumpIndex,
                                        DestOnly      = oldJumpSeam.DestOnly,
                                        Length        = oldJumpSeam.Length,
                                        JumpIndices   = new TagBlock <ScenarioStructureBsp.PathfindingDatum.JumpSeam.JumpIndexBlock>(
                                            oldJumpSeam.JumpIndices.Count, new CacheResourceAddress())
                                    });
                                }

                                resourceDefinition.PathfindingData.Add(pathfinding);
                            }

                            foreach (var pathfindingDatum in resourceDefinition.PathfindingData)
                            {
                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.Sectors.Address.Offset;
                                }
                                pathfindingDatum.Sectors = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Sector>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Sectors.Count : pathfindingDatum.Sectors.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.Sectors.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].Sectors[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Sector>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.Links.Address.Offset;
                                }
                                pathfindingDatum.Links = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Link>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Links.Count : pathfindingDatum.Links.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.Links.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].Links[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Link>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.References.Address.Offset;
                                }
                                pathfindingDatum.References = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Reference>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].References.Count : pathfindingDatum.References.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.References.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].References[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Reference>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.Bsp2dNodes.Address.Offset;
                                }
                                pathfindingDatum.Bsp2dNodes = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Bsp2dNode>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Bsp2dNodes.Count : pathfindingDatum.Bsp2dNodes.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.Bsp2dNodes.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].Bsp2dNodes[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Bsp2dNode>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.Vertices.Address.Offset;
                                }
                                pathfindingDatum.Vertices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Vertex>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Vertices.Count : pathfindingDatum.Vertices.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.Vertices.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].Vertices[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Vertex>(dataContext));
                                }

                                for (var objRefIdx = 0; objRefIdx < pathfindingDatum.ObjectReferences.Count; objRefIdx++)
                                {
                                    for (var bspRefIdx = 0; bspRefIdx < pathfindingDatum.ObjectReferences[objRefIdx].Bsps.Count; bspRefIdx++)
                                    {
                                        var bspRef = pathfindingDatum.ObjectReferences[objRefIdx].Bsps[bspRefIdx];

                                        StreamUtil.Align(dataStream, 0x4);
                                        if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                        {
                                            blamResourceStream.Position = bspRef.Bsp2dRefs.Address.Offset;
                                        }
                                        bspRef.Bsp2dRefs.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position);

                                        for (var bsp2dRefIdx = 0; bsp2dRefIdx < bspRef.Bsp2dRefs.Count; bsp2dRefIdx++)
                                        {
                                            var bsp2dRef = BlamCache.Version < CacheVersion.Halo3ODST ?
                                                           bsp.PathfindingData[0].ObjectReferences[objRefIdx].Bsps[bspRefIdx].Bsp2dRefs[bsp2dRefIdx] :
                                                           BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.ObjectReference.BspReference.Bsp2dRef>(dataContext);

                                            CacheContext.Serializer.Serialize(dataContext, bsp2dRef);
                                        }
                                    }
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.PathfindingHints.Address.Offset;
                                }
                                pathfindingDatum.PathfindingHints = new TagBlock <ScenarioStructureBsp.PathfindingDatum.PathfindingHint>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].PathfindingHints.Count : pathfindingDatum.PathfindingHints.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.PathfindingHints.Count; i++)
                                {
                                    var hint = BlamCache.Version < CacheVersion.Halo3ODST ?
                                               bsp.PathfindingData[0].PathfindingHints[i] :
                                               BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.PathfindingHint>(dataContext);

                                    if (BlamCache.Version < CacheVersion.Halo3ODST &&
                                        (hint.HintType == JumpLink || hint.HintType == WallJumpLink))
                                    {
                                        hint.Data[3] = (hint.Data[3] & ~ushort.MaxValue) | ((hint.Data[2] >> 16) & ushort.MaxValue);
                                        hint.Data[2] = (hint.Data[2] & ~(ushort.MaxValue << 16));                     //remove old landing sector
                                        hint.Data[2] = (hint.Data[2] | ((hint.Data[2] & (byte.MaxValue << 8)) << 8)); //move jump height flags
                                        hint.Data[2] = (hint.Data[2] & ~(byte.MaxValue << 8));                        //remove old flags
                                    }

                                    CacheContext.Serializer.Serialize(dataContext, hint);
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.InstancedGeometryReferences.Address.Offset;
                                }
                                pathfindingDatum.InstancedGeometryReferences = new TagBlock <ScenarioStructureBsp.PathfindingDatum.InstancedGeometryReference>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].InstancedGeometryReferences.Count : pathfindingDatum.InstancedGeometryReferences.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.InstancedGeometryReferences.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].InstancedGeometryReferences[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.InstancedGeometryReference>(dataContext));
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.GiantPathfinding.Address.Offset;
                                }
                                pathfindingDatum.GiantPathfinding = new TagBlock <ScenarioStructureBsp.PathfindingDatum.GiantPathfindingBlock>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].GiantPathfinding.Count : pathfindingDatum.GiantPathfinding.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.GiantPathfinding.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].GiantPathfinding[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.GiantPathfindingBlock>(dataContext));
                                }

                                for (var unk2Idx = 0; unk2Idx < pathfindingDatum.Seams.Count; unk2Idx++)
                                {
                                    var unknown2 = pathfindingDatum.Seams[unk2Idx];

                                    StreamUtil.Align(dataStream, 0x4);

                                    if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                    {
                                        blamResourceStream.Position = unknown2.LinkIndices.Address.Offset;
                                    }

                                    unknown2.LinkIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Seam.LinkIndexBlock>(
                                        (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Seams[unk2Idx].LinkIndices.Count : unknown2.LinkIndices.Count),
                                        new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));

                                    for (var unkIdx = 0; unkIdx < unknown2.LinkIndices.Count; unkIdx++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext,
                                                                          BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                          bsp.PathfindingData[0].Seams[unk2Idx].LinkIndices[unkIdx] :
                                                                          BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Seam.LinkIndexBlock>(dataContext));
                                    }
                                }

                                for (var unk3Idx = 0; unk3Idx < pathfindingDatum.JumpSeams.Count; unk3Idx++)
                                {
                                    var unknown3 = pathfindingDatum.JumpSeams[unk3Idx];

                                    StreamUtil.Align(dataStream, 0x4);

                                    if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                    {
                                        blamResourceStream.Position = unknown3.JumpIndices.Address.Offset;
                                    }

                                    unknown3.JumpIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.JumpSeam.JumpIndexBlock>(
                                        (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].JumpSeams[unk3Idx].JumpIndices.Count : unknown3.JumpIndices.Count),
                                        new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));

                                    for (var unk4Idx = 0; unk4Idx < unknown3.JumpIndices.Count; unk4Idx++)
                                    {
                                        CacheContext.Serializer.Serialize(dataContext,
                                                                          BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                          bsp.PathfindingData[0].JumpSeams[unk3Idx].JumpIndices[unk4Idx] :
                                                                          BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.JumpSeam.JumpIndexBlock>(dataContext));
                                    }
                                }

                                StreamUtil.Align(dataStream, 0x4);
                                if (BlamCache.Version >= CacheVersion.Halo3ODST)
                                {
                                    blamResourceStream.Position = pathfindingDatum.Doors.Address.Offset;
                                }
                                pathfindingDatum.Doors = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Door>(
                                    (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Doors.Count : pathfindingDatum.Doors.Count),
                                    new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position));
                                for (var i = 0; i < pathfindingDatum.Doors.Count; i++)
                                {
                                    CacheContext.Serializer.Serialize(dataContext,
                                                                      BlamCache.Version < CacheVersion.Halo3ODST ?
                                                                      bsp.PathfindingData[0].Doors[i] :
                                                                      BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Door>(dataContext));
                                }
                            }

                            CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, bsp.PathfindingResource), resourceDefinition);
                            resourceWriter.BaseStream.Position = 0;
                            dataStream.Position = 0;

                            bsp.PathfindingResource.ChangeLocation(ResourceLocation.ResourcesB);
                            var resource = bsp.PathfindingResource;

                            if (resource == null)
                            {
                                throw new ArgumentNullException("resource");
                            }

                            if (!dataStream.CanRead)
                            {
                                throw new ArgumentException("The input stream is not open for reading", "dataStream");
                            }

                            var cache = CacheContext.GetResourceCache(ResourceLocation.ResourcesB);

                            if (!resourceStreams.ContainsKey(ResourceLocation.ResourcesB))
                            {
                                resourceStreams[ResourceLocation.ResourcesB] = FlagIsSet(PortingFlags.Memory) ?
                                                                               new MemoryStream() :
                                                                               (Stream)CacheContext.OpenResourceCacheReadWrite(ResourceLocation.ResourcesB);

                                if (FlagIsSet(PortingFlags.Memory))
                                {
                                    using (var resourceStream = CacheContext.OpenResourceCacheRead(ResourceLocation.ResourcesB))
                                        resourceStream.CopyTo(resourceStreams[ResourceLocation.ResourcesB]);
                                }
                            }

                            var dataSize = (int)(dataStream.Length - dataStream.Position);
                            var data     = new byte[dataSize];
                            dataStream.Read(data, 0, dataSize);

                            resource.Page.Index = cache.Add(resourceStreams[ResourceLocation.ResourcesB], data, out uint compressedSize);
                            resource.Page.CompressedBlockSize   = compressedSize;
                            resource.Page.UncompressedBlockSize = (uint)dataSize;
                            resource.DisableChecksum();
                        }

            if (BlamCache.Version < CacheVersion.Halo3ODST)
            {
                bsp.SurfacePlanes.Clear();
                bsp.Planes.Clear();
                bsp.EdgeToSeams.Clear();
                bsp.PathfindingData.Clear();
            }

            return(bsp.PathfindingResource);
        }
Exemple #21
0
        private TagResourceReference ConvertStructureBspCacheFileTagResources(ScenarioStructureBsp bsp)
        {
            //
            // Set up ElDorado resource reference
            //

            if (BlamCache.Version < CacheVersion.Halo3ODST)
            {
                bsp.PathfindingResource = new TagResourceReference();
            }

            //
            // Load Blam resource data
            //

            var resourceDefinition = BlamCache.Version > CacheVersion.Halo3Retail ? BlamCache.ResourceCache.GetStructureBspCacheFileTagResources(bsp.PathfindingResource) : null;

            if (resourceDefinition == null && BlamCache.Version >= CacheVersion.Halo3ODST)
            {
                return(bsp.PathfindingResource);
            }

            //
            // Port Blam resource definition
            //

            if (BlamCache.Version < CacheVersion.Halo3ODST)
            {
                resourceDefinition = new StructureBspCacheFileTagResources()
                {
                    SurfacePlanes   = new TagBlock <SurfacesPlanes>(CacheAddressType.Data, bsp.SurfacePlanes),
                    Planes          = new TagBlock <PlaneReference>(CacheAddressType.Data, bsp.Planes),
                    EdgeToSeams     = new TagBlock <EdgeToSeamMapping>(CacheAddressType.Data, bsp.EdgeToSeams),
                    PathfindingData = new TagBlock <ResourcePathfinding>(CacheAddressType.Definition)
                };
                foreach (var pathfinding in bsp.PathfindingData)
                {
                    resourceDefinition.PathfindingData.Add(PathfindingConverter.CreateResourcePathfindingFromTag(pathfinding));
                }
                // convert hints
                foreach (var pathfindingDatum in resourceDefinition.PathfindingData)
                {
                    foreach (var hint in pathfindingDatum.PathfindingHints)
                    {
                        if (hint.HintType == PathfindingHint.HintTypeValue.JumpLink || hint.HintType == PathfindingHint.HintTypeValue.WallJumpLink)
                        {
                            hint.Data[3] = (hint.Data[3] & ~ushort.MaxValue) | ((hint.Data[2] >> 16) & ushort.MaxValue);
                            hint.Data[2] = (hint.Data[2] & ~(ushort.MaxValue << 16));                     //remove old landing sector
                            hint.Data[2] = (hint.Data[2] | ((hint.Data[2] & (byte.MaxValue << 8)) << 8)); //move jump height flags
                            hint.Data[2] = (hint.Data[2] & ~(byte.MaxValue << 8));                        //remove old flags
                        }
                    }
                }
                // fix surface planes
                foreach (var surfacePlane in resourceDefinition.SurfacePlanes)
                {
                    surfacePlane.PlaneCountNew = surfacePlane.PlaneCountOld;
                    surfacePlane.PlaneIndexNew = surfacePlane.PlaneIndexOld;
                }
            }

            bsp.PathfindingResource = CacheContext.ResourceCache.CreateStructureBspCacheFileResource(resourceDefinition);

            if (BlamCache.Version < CacheVersion.Halo3ODST)
            {
                bsp.SurfacePlanes.Clear();
                bsp.Planes.Clear();
                bsp.EdgeToSeams.Clear();
                bsp.PathfindingData.Clear();
            }

            return(bsp.PathfindingResource);
        }
Exemple #22
0
        public static CommandContext Create(CommandContext parent, GameCache cache, CachedTag tag, ScenarioStructureBsp bsp)
        {
            var groupName = cache.StringTable.GetString(tag.Group.Name);

            var context = new CommandContext(parent,
                                             string.Format("{0:X8}.{1}", tag.Index, groupName));

            Populate(context, cache, tag, bsp);

            return(context);
        }
Exemple #23
0
 public static void Populate(CommandContext commandContext, GameCache cache, CachedTag tag, ScenarioStructureBsp bsp)
 {
     commandContext.AddCommand(new GenerateJumpHintsCommand(cache, tag, bsp));
     commandContext.AddCommand(new DumpRenderGeometryCommand(cache, bsp.DecoratorGeometry, "Decorator"));
     commandContext.AddCommand(new DumpRenderGeometryCommand(cache, bsp.Geometry, "Bsp"));
     commandContext.AddCommand(new MoppDataCommand(bsp));
     commandContext.AddCommand(new ExtractCollisionGeometryCommand(cache, bsp));
     commandContext.AddCommand(new ExtractPathfindingGeometryCommand(cache, bsp));
     commandContext.AddCommand(new ExtractRenderGeometryCommand(cache, bsp));
 }
Exemple #24
0
        private static bool ExtractResource(ScenarioStructureBsp Definition, HaloOnlineCacheContext CacheContext, IReadOnlyList <string> args)
        {
            if (args.Count < 1)
            {
                return(false);
            }

            var resourceType = "";
            var filePath     = "";
            var cachePath    = "resources.dat";

            resourceType = args[1].ToLower(); // geometry2
            filePath     = args[2];           // sc140_000_geometry2.raw

            PageableResource resource = null;

            switch (resourceType)
            {
            case "geometry":
                resource = Definition.Geometry.Resource;
                break;

            case "geometry2":
                resource = Definition.Geometry2.Resource;
                break;

            case "collisionbspresource":
                resource = Definition.CollisionBspResource;
                break;

            case "pathfindingresource":
                resource = Definition.PathfindingResource;
                break;

            default:
                Console.WriteLine($"Invalid sbsp resource type.");
                return(false);
            }

            if (resource == null || resource.Page.Index < 0 || !resource.GetLocation(out var location))
            {
                Console.WriteLine("Resource is null.");
                return(false);
            }

            try
            {
                using (var stream = File.OpenRead(CacheContext.TagCacheFile.DirectoryName + "\\" + cachePath))
                {
                    var cache = new ResourceCache(stream);
                    using (var outStream = File.Open(filePath, FileMode.Create, FileAccess.Write))
                    {
                        cache.Decompress(stream, resource.Page.Index, resource.Page.CompressedBlockSize, outStream);
                        Console.WriteLine("Wrote 0x{0:X} bytes to {1}.", outStream.Position, filePath);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to extract resource: {0}", ex.Message);
            }

            return(true);
        }
Exemple #25
0
        private ScenarioStructureBsp ConvertScenarioStructureBsp(ScenarioStructureBsp sbsp, CachedTagInstance instance, Dictionary <ResourceLocation, Stream> resourceStreams)
        {
            sbsp.CollisionBspResource = ConvertStructureBspTagResources(sbsp, resourceStreams);
            sbsp.PathfindingResource  = ConvertStructureBspCacheFileTagResources(sbsp, resourceStreams);

            sbsp.Unknown86 = 1;

            //
            // Set compatibility flag for H3 mopps
            //

            if (BlamCache.Version == CacheVersion.Halo3Retail)
            {
                sbsp.CompatibilityFlags = ScenarioStructureBsp.StructureBspCompatibilityValue.UseMoppIndexPatch;
            }
            else
            {
                sbsp.CompatibilityFlags = ScenarioStructureBsp.StructureBspCompatibilityValue.None;
            }

            //
            // Fix cluster tag ref and decorator grids
            //

            var resource = sbsp.Geometry.Resource;

            if (resource != null && resource.Page.Index >= 0 && resource.GetLocation(out var location))
            {
                var resourceContext = new ResourceSerializationContext(CacheContext, sbsp.Geometry.Resource);
                var definition      = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext);

                using (var edResourceStream = new MemoryStream())
                    using (var edResourceReader = new EndianReader(edResourceStream, EndianFormat.LittleEndian))
                    {
                        var pageable = sbsp.Geometry.Resource;

                        if (pageable == null)
                        {
                            throw new ArgumentNullException("sbsp.Geometry.Resource");
                        }

                        if (!edResourceStream.CanWrite)
                        {
                            throw new ArgumentException("The output stream is not open for writing", "outStream");
                        }

                        pageable.GetLocation(out var resourceLocation);

                        var cache = CacheContext.GetResourceCache(resourceLocation);

                        if (!resourceStreams.ContainsKey(resourceLocation))
                        {
                            resourceStreams[resourceLocation] = FlagIsSet(PortingFlags.Memory) ?
                                                                new MemoryStream() :
                                                                (Stream)CacheContext.OpenResourceCacheReadWrite(resourceLocation);

                            if (FlagIsSet(PortingFlags.Memory))
                            {
                                using (var resourceStream = CacheContext.OpenResourceCacheRead(resourceLocation))
                                    resourceStream.CopyTo(resourceStreams[resourceLocation]);
                            }
                        }

                        cache.Decompress(resourceStreams[resourceLocation], pageable.Page.Index, pageable.Page.CompressedBlockSize, edResourceStream);

                        var inVertexStream = VertexStreamFactory.Create(CacheVersion.HaloOnline106708, edResourceStream);

                        foreach (var cluster in sbsp.Clusters)
                        {
                            List <ScenarioStructureBsp.Cluster.DecoratorGrid> newDecoratorGrids = new List <ScenarioStructureBsp.Cluster.DecoratorGrid>();

                            foreach (var grid in cluster.DecoratorGrids)
                            {
                                grid.DecoratorGeometryIndex_HO = grid.DecoratorGeometryIndex_H3;
                                grid.DecoratorIndex_HO         = grid.DecoratorIndex_H3;

                                if (grid.Amount == 0)
                                {
                                    newDecoratorGrids.Add(grid);
                                }
                                else
                                {
                                    List <TinyPositionVertex> vertices = new List <TinyPositionVertex>();

                                    // Get the buffer the right grid
                                    var vertexBuffer = definition.VertexBuffers[grid.DecoratorGeometryIndex_HO].Definition;
                                    // Get the offset from the grid
                                    edResourceStream.Position = vertexBuffer.Data.Address.Offset + grid.DecoratorGeometryOffset;
                                    // Read all vertices and add to the list
                                    for (int i = 0; i < grid.Amount; i++)
                                    {
                                        vertices.Add(inVertexStream.ReadTinyPositionVertex());
                                    }

                                    // Get the new grids
                                    List <ScenarioStructureBsp.Cluster.DecoratorGrid> newGrids = ConvertDecoratorGrid(vertices, grid);

                                    // Add all to list
                                    foreach (var newGrid in newGrids)
                                    {
                                        newDecoratorGrids.Add(newGrid);
                                    }
                                }
                            }

                            cluster.DecoratorGrids = newDecoratorGrids;
                        }
                    }
            }

            //
            // Temporary Fixes:
            //

            // Without this 005_intro crash on cortana sbsp
            sbsp.Geometry2.UnknownSections = new List <RenderGeometry.UnknownSection>();

            return(sbsp);
        }