public static TagInstance ConvertTag(TagInstance srcTag, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagCacheMap tagMap) { TagPrinter.PrintTagShort(srcTag); // Deserialize the tag from the source cache var structureType = TagStructureTypes.FindByGroupTag(srcTag.Group.Tag); var srcContext = new TagSerializationContext(srcStream, srcInfo.Cache, srcInfo.StringIDs, srcTag); var tagData = srcInfo.Deserializer.Deserialize(srcContext, structureType); // Acquire the destination tag var destTag = destInfo.Cache.AllocateTag(srcTag.Group); tagMap.Add(srcInfo.CacheFile.FullName, srcTag.Index, destInfo.CacheFile.FullName, destTag.Index); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = true; } // Convert the source tag tagData = Convert(tagData, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = false; } // Re-serialize into the destination cache var destContext = new TagSerializationContext(destStream, destInfo.Cache, destInfo.StringIDs, destTag); destInfo.Serializer.Serialize(destContext, tagData); return(destTag); }
public override bool Execute(List <string> args) { if (args.Count != 1) { return(false); } var groupTag = ArgumentParser.ParseGroupTag(Info.StringIDs, args[0]); if (groupTag == null || !TagGroup.Instances.ContainsKey(groupTag)) { return(false); } TagInstance instance; using (var stream = Info.OpenCacheReadWrite()) { instance = Info.Cache.AllocateTag(TagGroup.Instances[groupTag]); var context = new TagSerializationContext(stream, Info.Cache, Info.StringIDs, instance); var data = Activator.CreateInstance(TagStructureTypes.FindByGroupTag(groupTag)); Info.Serializer.Serialize(context, data); } var tagName = Info.TagNames.ContainsKey(instance.Index) ? Info.TagNames[instance.Index] : $"0x{instance.Index:X4}"; Console.WriteLine($"[Index: 0x{instance.Index:X4}, Offset: 0x{instance.HeaderOffset:X8}, Size: 0x{instance.TotalSize:X4}] {tagName}.{Info.StringIDs.GetString(instance.Group.Name)}"); return(true); }
private TagInstance ConvertTag(TagInstance srcTag, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagVersionMap tagMap) { TagPrinter.PrintTagShort(srcTag); // Uncomment this to use 0x101F for all shaders /*if (srcTag.IsClass("rm ")) * return destInfo.Cache.Tags[0x101F];*/ // Check if the tag is in the map, and just return the translated tag if so var destIndex = tagMap.Translate(srcInfo.Version, srcTag.Index, destInfo.Version); if (destIndex >= 0) { Console.WriteLine("- Using already-known index {0:X4}", destIndex); return(destInfo.Cache.Tags[destIndex]); } // Deserialize the tag from the source cache var structureType = TagStructureTypes.FindByGroupTag(srcTag.Group.Tag); var srcContext = new TagSerializationContext(srcStream, srcInfo.Cache, srcInfo.StringIDs, srcTag); var tagData = srcInfo.Deserializer.Deserialize(srcContext, structureType); // Uncomment this to use 0x101F in place of shaders that need conversion /*if (tagData is RenderMethod) * { * var rm = (RenderMethod)tagData; * foreach (var prop in rm.ShaderProperties) * { * if (tagMap.Translate(srcInfo.Version, prop.Template.Index, destInfo.Version) < 0) * return destInfo.Cache.Tags[0x101F]; * } * }*/ // Allocate a new tag and create a mapping for it var newTag = destInfo.Cache.AllocateTag(srcTag.Group); tagMap.Add(srcInfo.Version, srcTag.Index, destInfo.Version, newTag.Index); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { _isDecalShader = true; } // Convert it tagData = Convert(tagData, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { _isDecalShader = false; } // Re-serialize into the destination cache var destContext = new TagSerializationContext(destStream, destInfo.Cache, destInfo.StringIDs, newTag); destInfo.Serializer.Serialize(destContext, tagData); return(newTag); }
public static Tag ParseGroupTag(StringIDCache stringIDs, string groupName) { if (TagStructureTypes.IsGroupTag(groupName)) { return(new Tag(groupName)); } foreach (var pair in TagGroup.Instances) { if (groupName == stringIDs.GetString(pair.Value.Name)) { return(pair.Value.Tag); } } return(Tag.Null); }
private void SetGameObjectName(Stream stream, TagInstance tag, ref Dictionary <int, string> tagNames) { var context = new TagSerializationContext(stream, Info.Cache, Info.StringIds, tag); var definition = (GameObject)Info.Deserializer.Deserialize(context, TagStructureTypes.FindByGroupTag(tag.Group.Tag)); if (definition.Model == null) { return; } context = new TagSerializationContext(stream, Info.Cache, Info.StringIds, definition.Model); var modelDefinition = Info.Deserializer.Deserialize <Model>(context); if (modelDefinition.RenderModel == null) { return; } context = new TagSerializationContext(stream, Info.Cache, Info.StringIds, modelDefinition.RenderModel); var renderModelDefinition = Info.Deserializer.Deserialize <RenderModel>(context); var objectName = Info.StringIds.GetString(renderModelDefinition.Name); if (tag.Group.Tag == new Tag("bipd")) { var biped = (Biped)definition; var isMultiplayer = objectName.StartsWith("mp_"); var isMonitor = objectName.StartsWith("monitor"); var objectRootName = isMultiplayer ? objectName.Substring(3) : objectName; var objectGenericName = $"objects\\characters\\{objectRootName}\\{objectRootName}"; if (objectRootName != objectName) { objectName = $"objects\\characters\\{objectRootName}\\{objectName}\\{objectName}"; } else if (isMonitor) { objectName = $"{objectGenericName}_editor"; } else { objectName = objectGenericName; } tagNames[definition.Model.Index] = objectName; if (modelDefinition.RenderModel != null) { tagNames[modelDefinition.RenderModel.Index] = objectName; } if (modelDefinition.CollisionModel != null) { tagNames[modelDefinition.CollisionModel.Index] = objectGenericName; } if (modelDefinition.PhysicsModel != null) { tagNames[modelDefinition.PhysicsModel.Index] = objectGenericName; } if (modelDefinition.Animation != null) { tagNames[modelDefinition.Animation.Index] = objectGenericName; } if (biped.CollisionDamage != null && !tagNames.ContainsKey(biped.CollisionDamage.Index)) { tagNames[biped.CollisionDamage.Index] = isMonitor ? "globals\\collision_damage\\invulnerable_harmless" : "globals\\collision_damage\\biped_player"; } if (biped.MaterialEffects != null && !tagNames.ContainsKey(biped.MaterialEffects.Index)) { tagNames[biped.MaterialEffects.Index] = $"fx\\material_effects\\objects\\characters\\{objectRootName}"; } if (biped.MeleeImpact != null && !tagNames.ContainsKey(biped.MeleeImpact.Index)) { tagNames[biped.MeleeImpact.Index] = "sounds\\materials\\soft\\organic_flesh\\melee_impact"; } if (biped.CameraTracks.Count != 0 && biped.CameraTracks[0].Track != null && !tagNames.ContainsKey(biped.CameraTracks[0].Track.Index)) { tagNames[biped.CameraTracks[0].Track.Index] = isMonitor ? "camera\\biped_follow_camera" : "camera\\biped_support_camera"; } if (biped.MeleeDamage != null && !tagNames.ContainsKey(biped.MeleeDamage.Index)) { tagNames[biped.MeleeDamage.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_melee"; } if (biped.BoardingMeleeDamage != null && !tagNames.ContainsKey(biped.BoardingMeleeDamage.Index)) { tagNames[biped.BoardingMeleeDamage.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_boarding_melee"; } if (biped.BoardingMeleeResponse != null && !tagNames.ContainsKey(biped.BoardingMeleeResponse.Index)) { tagNames[biped.BoardingMeleeResponse.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_boarding_melee_response"; } if (biped.EjectionMeleeDamage != null && !tagNames.ContainsKey(biped.EjectionMeleeDamage.Index)) { tagNames[biped.EjectionMeleeDamage.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_ejection_melee"; } if (biped.EjectionMeleeResponse != null && !tagNames.ContainsKey(biped.EjectionMeleeResponse.Index)) { tagNames[biped.EjectionMeleeResponse.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_ejection_melee_response"; } if (biped.LandingMeleeDamage != null && !tagNames.ContainsKey(biped.LandingMeleeDamage.Index)) { tagNames[biped.LandingMeleeDamage.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_landing_melee"; } if (biped.FlurryMeleeDamage != null && !tagNames.ContainsKey(biped.FlurryMeleeDamage.Index)) { tagNames[biped.FlurryMeleeDamage.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_flurry_melee"; } if (biped.ObstacleSmashMeleeDamage != null && !tagNames.ContainsKey(biped.ObstacleSmashMeleeDamage.Index)) { tagNames[biped.ObstacleSmashMeleeDamage.Index] = $"objects\\characters\\{objectRootName}\\damage_effects\\{objectRootName}_obstacle_smash"; } if (biped.AreaDamageEffect != null && !tagNames.ContainsKey(biped.AreaDamageEffect.Index)) { tagNames[biped.AreaDamageEffect.Index] = $"fx\\material_effects\\objects\\characters\\contact\\collision\\blood_aoe_{objectRootName}"; } } else if (tag.Group.Tag == new Tag("weap")) { var weapon = (Weapon)definition; if (weapon.HudInterface != null && !tagNames.ContainsKey(weapon.HudInterface.Index)) { tagNames[weapon.HudInterface.Index] = $"ui\\chud\\{objectName}"; } if (weapon.FirstPerson.Count > 0) { var spartanJmadTag = weapon.FirstPerson[0].FirstPersonAnimations; if (spartanJmadTag != null) { tagNames[spartanJmadTag.Index] = $"objects\\characters\\mp_masterchief\\fp\\weapons\\fp_{objectName}\\fp_{objectName}"; } } if (weapon.FirstPerson.Count > 1) { var eliteJmadTag = weapon.FirstPerson[1].FirstPersonAnimations; if (eliteJmadTag != null) { tagNames[eliteJmadTag.Index] = $"objects\\characters\\mp_elite\\fp\\weapons\\fp_{objectName}\\fp_{objectName}"; } } var weaponClassName = // HUNTER WEAPONS objectName.StartsWith("flak_cannon") ? "hunter\\hunter_flak_cannon" : // MELEE WEAPONS objectName.StartsWith("energy_blade") ? "melee\\energy_blade" : objectName.StartsWith("gravity_hammer") ? "melee\\gravity_hammer" : // MULTIPLAYER WEAPONS objectName.StartsWith("assault_bomb") ? "multiplayer\\assault_bomb" : objectName.StartsWith("ball") ? "multiplayer\\ball" : objectName.StartsWith("flag") ? "multiplayer\\flag" : // PISTOL WEAPONS objectName.StartsWith("excavator") ? "pistol\\excavator" : objectName.StartsWith("magnum") ? "pistol\\magnum" : objectName.StartsWith("needler") ? "pistol\\needler" : objectName.StartsWith("plasma_pistol") ? "pistol\\plasma_pistol" : // RIFLE WEAPONS (objectName.StartsWith("assault_rifle") || objectName.StartsWith("ar_variant")) ? "rifle\\assault_rifle" : (objectName.StartsWith("battle_rifle") || objectName.StartsWith("br_variant")) ? "rifle\\battle_rifle" : objectName.StartsWith("beam_rifle") ? "rifle\\beam_rifle" : objectName.StartsWith("covenant_carbine") ? "rifle\\covenant_carbine" : objectName.StartsWith("dmr") ? "rifle\\dmr" : objectName.StartsWith("needle_rifle") ? "rifle\\needle_rifle" : objectName.StartsWith("plasma_rifle") ? "rifle\\plasma_rifle" : objectName.StartsWith("shotgun") ? "rifle\\shotgun" : objectName.StartsWith("smg") ? "rifle\\smg" : objectName.StartsWith("sniper_rifle") ? "rifle\\sniper_rifle" : objectName.StartsWith("spike_rifle") ? "rifle\\spike_rifle" : // SUPPORT WEAPONS objectName.StartsWith("rocket_launcher") ? "support_high\\rocket_launcher" : objectName.StartsWith("spartan_laser") ? "support_high\\spartan_laser" : objectName.StartsWith("brute_shot") ? "support_low\\brute_shot" : objectName.StartsWith("sentinel_gun") ? "support_low\\sentinel_gun" : // OTHER WEAPONS objectName; objectName = $"objects\\weapons\\{weaponClassName}\\{objectName}"; if (objectName.EndsWith("energy_blade") && definition.WaterDensity == GameObject.WaterDensityValue.Default) { objectName += "_useless"; } tagNames[definition.Model.Index] = objectName; if (modelDefinition.RenderModel != null) { tagNames[modelDefinition.RenderModel.Index] = objectName; } if (modelDefinition.CollisionModel != null) { tagNames[modelDefinition.CollisionModel.Index] = objectName; } if (modelDefinition.PhysicsModel != null) { tagNames[modelDefinition.PhysicsModel.Index] = objectName; } if (modelDefinition.Animation != null) { tagNames[modelDefinition.Animation.Index] = objectName; } } else if (tag.Group.Tag == new Tag("eqip")) { var equipment = (Equipment)definition; var equipmentClassName = (objectName.StartsWith("health_pack") || objectName.EndsWith("ammo")) ? $"powerups\\{objectName}" : objectName.StartsWith("powerup") ? $"multi\\powerups\\{objectName}" : objectName.EndsWith("grenade") ? $"weapons\\grenade\\{objectName}" : $"equipment\\{objectName}"; objectName = $"objects\\{equipmentClassName}\\{objectName}"; } else if (tag.Group.Tag == new Tag("vehi")) { } else if (tag.Group.Tag == new Tag("armr")) { // TODO: figure out spartan/elite armor name differences objectName = $"objects\\characters\\masterchief\\mp_masterchief\\armor\\{objectName}"; tagNames[definition.Model.Index] = objectName; if (modelDefinition.RenderModel != null) { tagNames[modelDefinition.RenderModel.Index] = objectName; } if (modelDefinition.CollisionModel != null) { tagNames[modelDefinition.CollisionModel.Index] = objectName; } if (modelDefinition.PhysicsModel != null) { tagNames[modelDefinition.PhysicsModel.Index] = objectName; } if (modelDefinition.Animation != null) { tagNames[modelDefinition.Animation.Index] = objectName; } } tagNames[tag.Index] = objectName; }
public override bool Execute(List <string> args) { if (args.Count < 2) { return(false); } var outputPath = args[0]; // Load each file and do version detection var infos = new List <OpenTagCache>(); foreach (var path in args.Skip(1)) { Console.WriteLine("Loading {0}...", path); // Load the cache file var info = new OpenTagCache { CacheFile = new FileInfo(path) }; using (var stream = info.OpenCacheRead()) info.Cache = new TagCache(stream); // Do version detection, and don't accept the closest version // because that might not work EngineVersion closestVersion; info.Version = VersionDetection.DetectVersion(info.Cache, out closestVersion); if (info.Version == EngineVersion.Unknown) { Console.WriteLine("- Unrecognized version! Ignoring."); continue; } info.Deserializer = new TagDeserializer(info.Version); infos.Add(info); } var result = new TagVersionMap(); using (var baseStream = _info.OpenCacheRead()) { // Get the scenario tags for this cache Console.WriteLine("Finding base scenario tags..."); var baseScenarios = FindScenarios(_info, baseStream); var baseVersion = _info.Version; var baseTagData = new Dictionary <int, object>(); foreach (var scenario in baseScenarios) { baseTagData[scenario.Tag.Index] = scenario.Data; } // Now compare with each of the other caches foreach (var info in infos) { using (var stream = info.OpenCacheRead()) { Console.WriteLine("Finding scenario tags in {0}...", info.CacheFile.FullName); // Get the scenario tags and connect them to the base tags var scenarios = FindScenarios(info, stream); var tagsToCompare = new Queue <QueuedTag>(); for (var i = 0; i < scenarios.Count; i++) { tagsToCompare.Enqueue(scenarios[i]); if (i < baseScenarios.Count) { result.Add(baseVersion, baseScenarios[i].Tag.Index, info.Version, scenarios[i].Tag.Index); } } // Process each tag in the queue, enqueuing all of its dependencies as well while (tagsToCompare.Count > 0) { // Get the tag and its data var tag = tagsToCompare.Dequeue(); TagPrinter.PrintTagShort(tag.Tag); var data = tag.Data; if (data == null) { // No data yet - deserialize it var context = new TagSerializationContext(stream, info.Cache, info.StringIds, tag.Tag); var type = TagStructureTypes.FindByGroupTag(tag.Tag.Group.Tag); data = info.Deserializer.Deserialize(context, type); } // Now get the data for the base tag var baseTag = result.Translate(info.Version, tag.Tag.Index, baseVersion); if (baseTag == -1 || _info.Cache.Tags[baseTag].Group.Tag != tag.Tag.Group.Tag) { continue; } object baseData; if (!baseTagData.TryGetValue(baseTag, out baseData)) { // No data yet - deserialize it var context = new TagSerializationContext(baseStream, _info.Cache, _info.StringIds, _info.Cache.Tags[baseTag]); var type = TagStructureTypes.FindByGroupTag(tag.Tag.Group.Tag); baseData = _info.Deserializer.Deserialize(context, type); baseTagData[baseTag] = baseData; } // Compare the two blocks CompareBlocks(baseData, baseVersion, data, info.Version, result, tagsToCompare); } } } } // Write out the CSV Console.WriteLine("Writing results..."); using (var writer = new StreamWriter(File.Open(outputPath, FileMode.Create, FileAccess.Write))) result.WriteCsv(writer); Console.WriteLine("Done!"); return(true); }
public static CommandContext Create(CommandContextStack stack, OpenTagCache info, TagInstance tag) { var groupName = info.StringIDs.GetString(tag.Group.Name); var tagName = $"0x{tag.Index:X4}"; if (info.TagNames.ContainsKey(tag.Index)) { tagName = info.TagNames[tag.Index]; tagName = $"(0x{tag.Index:X4}) {tagName.Substring(tagName.LastIndexOf('\\') + 1)}"; } var context = new CommandContext(stack.Context, string.Format("{0}.{1}", tagName, groupName)); switch (tag.Group.Tag.ToString()) { case "vfsl": // vfiles_list EditVFilesList(context, info, tag); break; case "unic": // multilingual_unicode_string_list EditMultilingualUnicodeStringList(context, info, tag); break; case "bitm": // bitmap EditBitmap(context, info, tag); break; case "hlmt": // model EditModel(context, info, tag); break; case "mode": // render_model EditRenderModel(context, info, tag); break; case "jmad": EditAnimation(context, info, tag); break; case "rm ": // render_method case "rmsh": // shader case "rmd ": // shader_decal case "rmfl": // shader_foliage case "rmhg": // shader_halogram case "rmss": // shader_screen case "rmtr": // shader_terrain case "rmw ": // shader_water case "rmzo": // shader_zonly case "rmcs": // shader_custom EditRenderMethod(context, info, tag); break; case "scnr": EditScenario(context, info, tag); break; } object value = null; using (var stream = info.OpenCacheRead()) value = info.Deserializer.Deserialize( new TagSerializationContext(stream, info.Cache, info.StringIDs, tag), TagStructureTypes.FindByGroupTag(tag.Group.Tag)); var structure = new TagStructureInfo( TagStructureTypes.FindByGroupTag(tag.Group.Tag)); context.AddCommand(new ListFieldsCommand(info, structure, value)); context.AddCommand(new SetFieldCommand(stack, info, tag, structure, value)); context.AddCommand(new EditBlockCommand(stack, info, tag, value)); context.AddCommand(new AddToCommand(stack, info, tag, structure, value)); context.AddCommand(new RemoveFromCommand(stack, info, tag, structure, value)); context.AddCommand(new CopyElementsCommand(stack, info, tag, structure, value)); context.AddCommand(new PasteElementsCommand(stack, info, tag, structure, value)); context.AddCommand(new SaveChangesCommand(info, tag, value)); context.AddCommand(new ExitToCommand(stack)); return(context); }