public static EncounterLayer_MDD InsertOrUpdateEncounterLayer(this MetadataDatabase mdd, EncounterLayer encounterLayer) { mdd.Execute("INSERT OR REPLACE INTO EncounterLayer (EncounterLayerID, MapID, Name, FriendlyName, Description, BattleValue, ContractTypeID, EncounterLayerGUID, TagSetID, IncludeInBuild) values(@EncounterLayerID, @MapID, @Name, @FriendlyName, @Description, @BattleValue, @ContractTypeID, @EncounterLayerGUID, @TagSetID, @IncludeInBuild)", new { EncounterLayerID = encounterLayer.EncounterLayerId, MapID = encounterLayer.MapId, Name = encounterLayer.Name, FriendlyName = encounterLayer.FriendlyName, Description = encounterLayer.Description, BattleValue = encounterLayer.BattleValue, ContractTypeID = encounterLayer.ContractTypeId, EncounterLayerGUID = encounterLayer.EncounterLayerGuid, TagSetID = encounterLayer.TagSetId, IncludeInBuild = encounterLayer.IncludeInBuild }, null, null, null); return(mdd.SelectEncounterLayerByID(encounterLayer.EncounterLayerId)); }
private static int CreateMetadata(bool Update = false) { ConsoleColor c = Console.ForegroundColor; try { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Connecting to " + ConnectionString); SqlMetadataDatabase db = SqlMetadataDatabase.FromConnection(ConnectionString, Update, File.Exists(OutputFile) ? OutputFile : null); Console.WriteLine("{0} metadata for {1} tables and views...", Update ? "Updating" : "Building", Tables == null ? "all" : Tables.Length.ToString()); if (Update) { db.FileName = OutputFile; } db.MetadataUpdateEvent += db_MetadataUpdateEvent; if (Update && !File.Exists(OutputFile)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("'Update' was specified but the file {0} does not exist. 'Create' will be used in stead", OutputFile); Console.ForegroundColor = ConsoleColor.Yellow; Update = false; db.FileName = null; } MetadataDatabase mdb = db.BuildMetadata(true, Tables, Update); Console.WriteLine("Done. Metadata contains {0} tables", mdb.Tables.Count); Console.WriteLine("Saving metadata in the file {0}", OutputFile); ClassCreationOptions.MetadataEvent = new MetadataUpdateDelegate(db_MetadataUpdateEvent); ClassGenerator.CreateClasses(mdb); mdb.ToFile(OutputFile); return(0); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(ex.Message); return(1); } finally { Console.ForegroundColor = c; if (PromptUser) { Console.Write("Finished. Press any key to exit"); Console.ReadKey(true); } } }
private static bool AddModEntryToDB(MetadataDatabase db, string absolutePath, string typeStr) { if (Path.GetExtension(absolutePath)?.ToLower() != ".json") { return(false); } var type = (BattleTechResourceType)Enum.Parse(typeof(BattleTechResourceType), typeStr); var relativePath = GetRelativePath(absolutePath, GameDirectory); switch (type) // switch is to avoid poisoning the output_log.txt with known types that don't use MDD { case BattleTechResourceType.TurretDef: case BattleTechResourceType.UpgradeDef: case BattleTechResourceType.VehicleDef: case BattleTechResourceType.ContractOverride: case BattleTechResourceType.SimGameEventDef: case BattleTechResourceType.LanceDef: case BattleTechResourceType.MechDef: case BattleTechResourceType.PilotDef: case BattleTechResourceType.WeaponDef: var writeTime = File.GetLastWriteTimeUtc(absolutePath); if (!dbCache.ContainsKey(relativePath) || dbCache[relativePath] != writeTime) { try { VersionManifestHotReload.InstantiateResourceAndUpdateMDDB(type, absolutePath, db); dbCache[relativePath] = writeTime; return(true); } catch (Exception e) { Log($"\tAdd to DB failed for {Path.GetFileName(absolutePath)}, exception caught:"); Log($"\t\t{e.Message}"); return(false); } } break; } return(false); }
public static void CreateClasses(MetadataDatabase mdb) { if (!Directory.Exists(ClassCreationOptions.OutputPath)) { Directory.CreateDirectory(ClassCreationOptions.OutputPath); } double total = mdb.Tables.Count; double done = 0; foreach (MetadataTable mt in mdb.Tables.Values) { StringBuilder sb = CreateTable(mt); string file = Path.Combine(ClassCreationOptions.OutputPath, mt.Name + ".cs"); File.WriteAllText(file, sb.ToString()); if (ClassCreationOptions.MetadataEvent != null) { done++; ClassCreationOptions.MetadataEvent.Invoke(Convert.ToInt32((done / total) * 100), mt.Name + ".cs created", DateTime.Now); } } }
public static void ToFile(this MetadataDatabase Metadata, string FileName, bool CreateDirectory = true) { if (CreateDirectory) { if (!Directory.Exists(Path.GetDirectoryName(FileName))) { Directory.CreateDirectory(Path.GetDirectoryName(FileName)); } } if (!Path.GetExtension(FileName).ToLower().EndsWith(".json")) { FileName += ".json"; } using (FileStream fs = File.OpenWrite(FileName)) using (StreamWriter sw = new StreamWriter(fs)) using (JsonWriter jw = new JsonTextWriter(sw)) { jw.Formatting = Formatting.None; JsonSerializer serializer = JsonSerializer.Create(settings); serializer.Serialize(jw, Metadata); } }
public static MetadataHelper WithMetadata(this Table table) { MetadataDatabase mdb = table.Builder.Metadata; if (mdb != null) { MetadataTable mt = mdb.FindTable(table.FullName); if (mt != null) { return(new MetadataHelper() { Table = table, Model = mt }); } else { throw new InvalidOperationException(string.Format("The Table '{0}' was not found in metadata", table.FullName)); } } else { throw new InvalidOperationException("The SqlBuilder does not contain metadata"); } }
public static List <Mood_MDD> GetMoods(this MetadataDatabase mdd) { return(mdd.Query <Mood_MDD>("SELECT * FROM Mood").ToList <Mood_MDD>()); }
public static EncounterLayer_MDD SelectEncounterLayerByGuid(this MetadataDatabase mdd, string encounterLayerGuid) { return(mdd.Query <EncounterLayer_MDD>("SELECT * FROM EncounterLayer WHERE EncounterLayerGUID=@encounterLayerGuid", new { EncounterLayerGUID = encounterLayerGuid }, null, true, null, null).FirstOrDefault <EncounterLayer_MDD>()); }
public static List <ContractType_MDD> GetStoryContractTypes(this MetadataDatabase mdd) { return(mdd.Query <ContractType_MDD>("SELECT * FROM ContractType WHERE IsStory = 1 OR IsRestoration = 1").ToList <ContractType_MDD>()); }
public static List <ContractType_MDD> GetCustomContractTypes(this MetadataDatabase mdd) { return(mdd.Query <ContractType_MDD>("SELECT * FROM ContractType WHERE ContractTypeID >= 10000").ToList <ContractType_MDD>()); }
public static Contract GetNewWarContract(SimGameState Sim, int Difficulty, Faction emp, Faction targ, StarSystem system) { if (Difficulty <= 1) { Difficulty = 2; } else if (Difficulty > 9) { Difficulty = 9; } ContractDifficulty minDiffClamped = (ContractDifficulty)AccessTools.Method(typeof(SimGameState), "GetDifficultyEnumFromValue").Invoke(Sim, new object[] { Difficulty }); ContractDifficulty maxDiffClamped = (ContractDifficulty)AccessTools.Method(typeof(SimGameState), "GetDifficultyEnumFromValue").Invoke(Sim, new object[] { Difficulty }); List <Contract> contractList = new List <Contract>(); int maxContracts = 1; int debugCount = 0; while (contractList.Count < maxContracts && debugCount < 1000) { WeightedList <MapAndEncounters> contractMaps = new WeightedList <MapAndEncounters>(WeightedListType.SimpleRandom, null, null, 0); List <ContractType> contractTypes = new List <ContractType>(); Dictionary <ContractType, List <ContractOverride> > potentialOverrides = new Dictionary <ContractType, List <ContractOverride> >(); AccessTools.Field(typeof(SimGameState), "singlePlayerTypes"); ContractType[] singlePlayerTypes = (ContractType[])AccessTools.Field(typeof(SimGameState), "singlePlayerTypes").GetValue(Sim); using (MetadataDatabase metadataDatabase = new MetadataDatabase()) { foreach (Contract_MDD contract_MDD in metadataDatabase.GetContractsByDifficultyRange(Difficulty - 1, Difficulty + 1)) { ContractType contractType = contract_MDD.ContractTypeEntry.ContractType; if (singlePlayerTypes.Contains(contractType)) { if (!contractTypes.Contains(contractType)) { contractTypes.Add(contractType); } if (!potentialOverrides.ContainsKey(contractType)) { potentialOverrides.Add(contractType, new List <ContractOverride>()); } ContractOverride item = Sim.DataManager.ContractOverrides.Get(contract_MDD.ContractID); potentialOverrides[contractType].Add(item); } } foreach (MapAndEncounters element in metadataDatabase.GetReleasedMapsAndEncountersByContractTypeAndTags(singlePlayerTypes, system.Def.MapRequiredTags, system.Def.MapExcludedTags, system.Def.SupportedBiomes)) { if (!contractMaps.Contains(element)) { contractMaps.Add(element, 0); } } } if (contractMaps.Count == 0) { Logger.LogLine("Maps0 break"); break; } if (potentialOverrides.Count == 0) { Logger.LogLine("Overrides0 break"); break; } contractMaps.Reset(false); WeightedList <Faction> validEmployers = new WeightedList <Faction>(WeightedListType.SimpleRandom, null, null, 0); Dictionary <Faction, WeightedList <Faction> > validTargets = new Dictionary <Faction, WeightedList <Faction> >(); int i = debugCount; debugCount = i + 1; WeightedList <MapAndEncounters> activeMaps = new WeightedList <MapAndEncounters>(WeightedListType.SimpleRandom, contractMaps.ToList(), null, 0); List <MapAndEncounters> discardedMaps = new List <MapAndEncounters>(); List <string> mapDiscardPile = (List <string>)AccessTools.Field(typeof(SimGameState), "mapDiscardPile").GetValue(Sim); for (int j = activeMaps.Count - 1; j >= 0; j--) { if (mapDiscardPile.Contains(activeMaps[j].Map.MapID)) { discardedMaps.Add(activeMaps[j]); activeMaps.RemoveAt(j); } } if (activeMaps.Count == 0) { mapDiscardPile.Clear(); foreach (MapAndEncounters element2 in discardedMaps) { activeMaps.Add(element2, 0); } } activeMaps.Reset(false); MapAndEncounters level = null; List <EncounterLayer_MDD> validEncounters = new List <EncounterLayer_MDD>(); Dictionary <ContractType, WeightedList <PotentialContract> > validContracts = new Dictionary <ContractType, WeightedList <PotentialContract> >(); WeightedList <PotentialContract> flatValidContracts = null; do { level = activeMaps.GetNext(false); if (level == null) { break; } validEncounters.Clear(); validContracts.Clear(); flatValidContracts = new WeightedList <PotentialContract>(WeightedListType.WeightedRandom, null, null, 0); foreach (EncounterLayer_MDD encounterLayer_MDD in level.Encounters) { ContractType contractType2 = encounterLayer_MDD.ContractTypeEntry.ContractType; if (contractTypes.Contains(contractType2)) { if (validContracts.ContainsKey(contractType2)) { validEncounters.Add(encounterLayer_MDD); } else { foreach (ContractOverride contractOverride2 in potentialOverrides[contractType2]) { bool flag = true; ContractDifficulty difficultyEnumFromValue = (ContractDifficulty)AccessTools.Method(typeof(SimGameState), "GetDifficultyEnumFromValue").Invoke(Sim, new object[] { contractOverride2.difficulty }); Faction employer2 = Faction.INVALID_UNSET; Faction target2 = Faction.INVALID_UNSET; if (difficultyEnumFromValue >= minDiffClamped && difficultyEnumFromValue <= maxDiffClamped) { employer2 = emp; target2 = targ; int difficulty = Sim.NetworkRandom.Int(Difficulty, Difficulty + 1); system.SetCurrentContractFactions(employer2, target2); int k = 0; while (k < contractOverride2.requirementList.Count) { RequirementDef requirementDef = new RequirementDef(contractOverride2.requirementList[k]); EventScope scope = requirementDef.Scope; TagSet curTags; StatCollection stats; switch (scope) { case EventScope.Company: curTags = Sim.CompanyTags; stats = Sim.CompanyStats; break; case EventScope.MechWarrior: case EventScope.Mech: goto IL_88B; case EventScope.Commander: goto IL_8E9; case EventScope.StarSystem: curTags = system.Tags; stats = system.Stats; break; default: goto IL_88B; } IL_803: for (int l = requirementDef.RequirementComparisons.Count - 1; l >= 0; l--) { ComparisonDef item2 = requirementDef.RequirementComparisons[l]; if (item2.obj.StartsWith("Target") || item2.obj.StartsWith("Employer")) { requirementDef.RequirementComparisons.Remove(item2); } } if (!SimGameState.MeetsRequirements(requirementDef, curTags, stats, null)) { flag = false; break; } k++; continue; IL_88B: if (scope != EventScope.Map) { throw new Exception("Contracts cannot use the scope of: " + requirementDef.Scope); } using (MetadataDatabase metadataDatabase2 = new MetadataDatabase()) { curTags = metadataDatabase2.GetTagSetForTagSetEntry(level.Map.TagSetID); stats = new StatCollection(); goto IL_803; } IL_8E9: curTags = Sim.CommanderTags; stats = Sim.CommanderStats; goto IL_803; } if (flag) { PotentialContract element3 = default(PotentialContract); element3.contractOverride = contractOverride2; element3.difficulty = difficulty; element3.employer = employer2; element3.target = target2; validEncounters.Add(encounterLayer_MDD); if (!validContracts.ContainsKey(contractType2)) { validContracts.Add(contractType2, new WeightedList <PotentialContract>(WeightedListType.WeightedRandom, null, null, 0)); } validContracts[contractType2].Add(element3, contractOverride2.weight); flatValidContracts.Add(element3, contractOverride2.weight); } } } } } } }while (validContracts.Count == 0 && level != null); system.SetCurrentContractFactions(Faction.INVALID_UNSET, Faction.INVALID_UNSET); if (validContracts.Count == 0) { if (mapDiscardPile.Count > 0) { mapDiscardPile.Clear(); } else { debugCount = 1000; Logger.LogLine(string.Format("[CONTRACT] Unable to find any valid contracts for available map pool. Alert designers.", new object[0])); } } else { GameContext gameContext = new GameContext(Sim.Context); gameContext.SetObject(GameContextObjectTagEnum.TargetStarSystem, system); Dictionary <ContractType, List <EncounterLayer_MDD> > finalEncounters = new Dictionary <ContractType, List <EncounterLayer_MDD> >(); foreach (EncounterLayer_MDD encounterLayer_MDD2 in validEncounters) { ContractType contractType3 = encounterLayer_MDD2.ContractTypeEntry.ContractType; if (!finalEncounters.ContainsKey(contractType3)) { finalEncounters.Add(contractType3, new List <EncounterLayer_MDD>()); } finalEncounters[contractType3].Add(encounterLayer_MDD2); } List <PotentialContract> discardedContracts = new List <PotentialContract>(); List <string> contractDiscardPile = (List <string>)AccessTools.Field(typeof(SimGameState), "contractDiscardPile").GetValue(Sim); for (int m = flatValidContracts.Count - 1; m >= 0; m--) { if (contractDiscardPile.Contains(flatValidContracts[m].contractOverride.ID)) { discardedContracts.Add(flatValidContracts[m]); flatValidContracts.RemoveAt(m); } } if ((float)discardedContracts.Count >= (float)flatValidContracts.Count * Sim.Constants.Story.DiscardPileToActiveRatio || flatValidContracts.Count == 0) { contractDiscardPile.Clear(); foreach (PotentialContract element4 in discardedContracts) { flatValidContracts.Add(element4, 0); } } PotentialContract next = flatValidContracts.GetNext(true); ContractType finalContractType = next.contractOverride.contractType; finalEncounters[finalContractType].Shuffle <EncounterLayer_MDD>(); string encounterGuid = finalEncounters[finalContractType][0].EncounterLayerGUID; ContractOverride contractOverride3 = next.contractOverride; Faction employer3 = next.employer; Faction target3 = next.target; int targetDifficulty = next.difficulty; Contract con = (Contract)AccessTools.Method(typeof(SimGameState), "CreateTravelContract").Invoke(Sim, new object[] { level.Map.MapName, level.Map.MapPath, encounterGuid, finalContractType, contractOverride3, gameContext, employer3, target3, employer3, false, targetDifficulty }); mapDiscardPile.Add(level.Map.MapID); contractDiscardPile.Add(contractOverride3.ID); Sim.PrepContract(con, employer3, target3, target3, level.Map.BiomeSkinEntry.BiomeSkin, con.Override.travelSeed, system); contractList.Add(con); } } if (debugCount >= 1000) { Logger.LogLine("Unable to fill contract list. Please inform AJ Immediately"); } return(contractList[0]); }
public void CloseDatabase() { DatabaseInfo.Save(DatabaseInfoPath, SerializationMode.Xml); _fileStorage.Stop(); _metadata.Stop(); _fileStorage = null; _metadata = null; _rootPath = null; _info = null; RaisePropertyChanged(string.Empty); }
static bool Prefix(UnitSpawnPointOverride __instance, ref LoadRequest request, MetadataDatabase mdd, string lanceName, int unitIndex) { if (UnityGameInstance.BattleTechGame.Simulation != null && Core.Settings.UpgradePilots) { try { DataManager dataManager = Traverse.Create(__instance).Field("dataManager").GetValue <DataManager>(); if (__instance.pilotDefId == UnitSpawnPointGameLogic.PilotDef_Tagged && __instance.selectedUnitType == UnitType.Mech && __instance.selectedUnitDefId != UnitSpawnPointGameLogic.MechDef_None && dataManager != null && __instance.pilotTagSet.IsEmpty && __instance.pilotExcludedTagSet.IsEmpty) { //Logger.Log($"Adding Exclusions to pilot: {__instance.pilotDefId}, for lance: {lanceName}, unit index: {unitIndex}, in Mech: {__instance.selectedUnitDefId}"); /* * Skill - Gunnery 8 Piloting 8 Guts 8 Tactics 8 * Gunnery 5 Gunner - Flanker Gladiator Striker * Piloting 5 Pilot Skirmisher - Brawler Scout * Guts 5 Defender Lancer Outrider - Vanguard * Tactics 5 Tactician Sharpshooter Recon Sentinel - */ // Add the Tags we want MechDef mechDef = dataManager.MechDefs.Get(__instance.selectedUnitDefId); TagSet excludeTags = new TagSet(); if (mechDef.Chassis.ChassisTags.Contains("mech_quirk_multitrac")) { // Excluding tier 2 skilled pilots that don't have Multi Target for Multi-Trac quirk excludeTags.Add("pilot_npc_outrider"); excludeTags.Add("pilot_npc_recon"); excludeTags.Add("pilot_npc_brawler"); excludeTags.Add("pilot_npc_sentinel"); excludeTags.Add("pilot_npc_scout"); excludeTags.Add("pilot_npc_vanguard"); } // Brawlers if (mechDef.MechTags.Contains("unit_role_brawler")) { // Excluding tier 2 pilots that have no or next to no survivability skills in brawlers excludeTags.Add("pilot_npc_sharpshooter"); excludeTags.Add("pilot_npc_skirmisher"); if (!mechDef.MechTags.Contains("unit_speed_high")) { // We aren't fast, get rid of shoot and move with no additional survivability excludeTags.Add("pilot_npc_striker"); } if (mechDef.MechTags.Contains("unit_speed_low") && !mechDef.MechTags.Contains("unit_jumpOK")) { // We are slow, can't jump and want to brawl, tactics 8 with Piloting 5 will not be enough for us to live on excludeTags.Add("pilot_npc_scout"); } } // Snipers if (mechDef.MechTags.Contains("unit_role_sniper")) { if (mechDef.MechTags.Contains("unit_speed_low") || (!mechDef.MechTags.Contains("unit_speed_high") && !mechDef.MechTags.Contains("unit_jumpOK"))) { // Excluding all piloting 8 if a sniper in medium speed or less mech excludeTags.Add("pilot_npc_flanker"); excludeTags.Add("pilot_npc_outrider"); excludeTags.Add("pilot_npc_recon"); } } // Scouts if (mechDef.MechTags.Contains("unit_role_scout")) { // Let's throw away Coolant Vent in scouts excludeTags.Add("pilot_npc_gladiator"); excludeTags.Add("pilot_npc_brawler"); excludeTags.Add("pilot_npc_sentinel"); if (mechDef.MechTags.Contains("unit_light") || mechDef.MechTags.Contains("unit_medium")) { // Excluding Gunnery 8 on light and medium scouts excludeTags.Add("pilot_npc_skirmisher"); excludeTags.Add("pilot_npc_lancer"); excludeTags.Add("pilot_npc_sharpshooter"); } } // Slow ass Mechs if (mechDef.MechTags.Contains("unit_speed_low")) { if (!mechDef.MechTags.Contains("unit_jumpOK")) { // Excluding non Outrider, piloting 8 in slow, non JJ Mechs // Leaving Outrider as a brawler might want it even if slow excludeTags.Add("pilot_npc_flanker"); excludeTags.Add("pilot_npc_recon"); } } // Fast fuckers if (mechDef.MechTags.Contains("unit_speed_high")) { if (mechDef.MechTags.Contains("unit_armor_low") && !mechDef.MechTags.Contains("unit_role_sniper")) { // We are protected by paper but fast, we are not a sniper, let's use certain combos if we have a tier 2 skill // Excluding Gunnery 8 excludeTags.Add("pilot_npc_skirmisher"); excludeTags.Add("pilot_npc_lancer"); excludeTags.Add("pilot_npc_sharpshooter"); // Excluding Gunnery 5 if we don't have Piloting 8 excludeTags.Add("pilot_npc_striker"); excludeTags.Add("pilot_npc_gladiator"); } if (!mechDef.MechTags.Contains("unit_armor_high")) { if (!mechDef.MechTags.Contains("unit_hot")) { // We aren't high armour, we are fast, and we aren't hot // Let's throw away Coolant Vent in non hot mechs to improve chances of more appropriate skills excludeTags.Add("pilot_npc_brawler"); excludeTags.Add("pilot_npc_sentinel"); } } } /* * Logger.Log($"Exclusions:"); * foreach (string anExclude in excludeTags) * { * Logger.Log(" " + anExclude); * }*/ // TagSet should remove duplicates so no need to do that __instance.pilotExcludedTagSet.AddRange(excludeTags); /*Logger.Log($"Final Exclusions:"); * foreach (string anExclude in __instance.pilotExcludedTagSet) * { * Logger.Log(" " + anExclude); * }*/ // Now do the same as the method would and don't call original method PilotDef_MDD pilotDef_MDD = UnitSpawnPointOverride.SelectTaggedPilotDef(mdd, __instance.pilotTagSet, __instance.pilotExcludedTagSet, lanceName, unitIndex); __instance.selectedPilotDefId = pilotDef_MDD.PilotDefID; request.AddBlindLoadRequest(BattleTechResourceType.PilotDef, __instance.selectedPilotDefId, new bool?(false)); return(false); } } catch (Exception e) { Logger.Error(e); } } return(true); }
public MetadataTable BuildMetadata(MetadataDatabase mdb, string TableName, string Schema = "dbo", bool PrimaryKeyIndexOnly = true, bool SelfJoin = false) { MetadataTable mt = null; if (mdb.Tables.TryGetValue(TableName, out mt)) { return mt; } Microsoft.SqlServer.Management.Smo.Table t = new Microsoft.SqlServer.Management.Smo.Table(SqlDatabase, TableName, Schema); t.Refresh(); return BuildMetadata(mdb, t, PrimaryKeyIndexOnly, SelfJoin); }
private MetadataTable BuildMetadata(MetadataDatabase mdb, Microsoft.SqlServer.Management.Smo.Table table, bool PrimaryKeyIndexOnly = true, bool SelfJoin = false) { MetadataTable mt = null; List<VirtualForeignKey> VirtualKeys = new List<VirtualForeignKey>(); table.Refresh(); if (mdb.Tables.TryGetValue(table.Name, out mt)) { return mt; } mt = new MetadataTable() { ID = table.ID, Schema = table.Schema, Name = table.Name, //Parent = mdb }; mt.TitleColumn = GetExtendedProperty("TitleColumn", table.ExtendedProperties); string[] values = GetExtendedProperty("DisplayName", table.ExtendedProperties, new char[] { '\r', '\n' }); if (values != null) { foreach (string value in values) { string[] v = value.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); mt.DisplayNames.TryAdd(Convert.ToInt32(v[0]), v[1]); } } values = GetExtendedProperty("Lists", table.ExtendedProperties, new char[] { '\r', '\n' }); if (values != null) { foreach (string value in values) { string[] v = value.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); List<string> v2 = v[1].Split(',').ToList(); if (!mt.ListDefinitions.TryAdd(v[0].Trim(), v2)) { throw new InvalidOperationException(string.Format("The TinySql.Lists extended property is invalid for the table '{0}'", table.Name)); } } } foreach (Microsoft.SqlServer.Management.Smo.Column column in table.Columns) { try { MetadataColumn col = new MetadataColumn() { ID = column.ID, Parent = mt, //Database = mdb, Name = column.Name, Collation = column.Collation, Default = column.Default, IsComputed = column.Computed, ComputedText = column.ComputedText, IsPrimaryKey = column.InPrimaryKey, IsIdentity = column.Identity, IsForeignKey = column.IsForeignKey, IdentityIncrement = column.IdentityIncrement, IdentitySeed = column.IdentitySeed, Nullable = column.Nullable, IsRowGuid = column.RowGuidCol }; BuildColumnDataType(col, column); values = GetExtendedProperty("DisplayName", column.ExtendedProperties, new char[] { '\r', '\n' }); if (values != null) { foreach (string value in values) { if (!value.Contains("=")) { col.DisplayNames.TryAdd(SqlBuilder.DefaultCulture.LCID, value); } else { string[] v = value.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); col.DisplayNames.TryAdd(Convert.ToInt32(v[0]), v[1]); } } } col.IncludeColumns = GetExtendedProperty("IncludeColumns", column.ExtendedProperties, new char[] { ',' }); values = GetExtendedProperty("FK", column.ExtendedProperties, new char[] { '\r', '\n' }); if (values != null) { VirtualKeys.Add(new VirtualForeignKey() { Column = col, values = values }); col.IsForeignKey = true; } mt.Columns.AddOrUpdate(col.Name, col, (k, v) => { return col; }); } catch (Exception exColumn) { throw new InvalidOperationException(string.Format("Unable to generate the column {0}", column.Name), exColumn); } } foreach (Index idx in table.Indexes) { if (!PrimaryKeyIndexOnly || idx.IndexKeyType == IndexKeyType.DriPrimaryKey) { Key key = new Key() { ID = idx.ID, Parent = mt, Database = mdb, Name = idx.Name, IsUnique = idx.IsUnique, IsPrimaryKey = idx.IndexKeyType == IndexKeyType.DriPrimaryKey }; foreach (IndexedColumn c in idx.IndexedColumns) { key.Columns.Add(mt[c.Name]); } mt.Indexes.AddOrUpdate(key.Name, key, (k, v) => { return key; }); } } if (!SelfJoin) { foreach (ForeignKey FK in table.ForeignKeys) { MetadataForeignKey mfk = new MetadataForeignKey() { ID = FK.ID, Parent = mt, Database = mdb, Name = FK.Name, ReferencedKey = FK.ReferencedKey, ReferencedSchema = FK.ReferencedTableSchema, ReferencedTable = FK.ReferencedTable }; MetadataTable mtref = null; if (!mdb.Tables.TryGetValue(mfk.ReferencedSchema + "." + mfk.ReferencedTable, out mtref)) { bool self = false; if ((mfk.ReferencedSchema == mt.Schema && mfk.ReferencedTable == mt.Name) || TablesInProgress.Contains(mfk.ReferencedSchema + "." + mfk.ReferencedTable)) { self = true; } TablesInProgress.Add(mfk.ReferencedSchema + "." + mfk.ReferencedTable); mtref = BuildMetadata(mdb, mfk.ReferencedTable, mfk.ReferencedSchema, PrimaryKeyIndexOnly, self); } foreach (ForeignKeyColumn cc in FK.Columns) { mfk.ColumnReferences.Add(new MetadataColumnReference() { Name = cc.Name, Column = mt[cc.Name], ReferencedColumn = mtref[cc.ReferencedColumn] }); } mt.ForeignKeys.AddOrUpdate(mfk.Name, mfk, (key, existing) => { return mfk; }); } } if (VirtualKeys.Count > 0) { BuildVirtualKeys(VirtualKeys, mt, mdb, PrimaryKeyIndexOnly); } mdb.Tables.AddOrUpdate(mt.Schema + "." + mt.Name, mt, (key, existing) => { return mt; }); return mt; }
internal static void AddModEntries(VersionManifest manifest) { if (!hasLoadedMods) { LoadMods(); } stopwatch.Start(); // there are no mods loaded, just return if (modLoadOrder == null || modLoadOrder.Count == 0) { return; } if (modEntries != null) { LogWithDate("Loading another manifest with already setup mod manifests."); foreach (var modEntry in modEntries) { AddModEntry(manifest, modEntry); } stopwatch.Stop(); Log(""); LogWithDate($"Done. Elapsed running time: {stopwatch.Elapsed.TotalSeconds} seconds\n"); return; } LogWithDate("Setting up mod manifests..."); var jsonMerges = new Dictionary <string, List <string> >(); modEntries = new List <ModDef.ManifestEntry>(); foreach (var modName in modLoadOrder) { if (!modManifest.ContainsKey(modName)) { continue; } Log($"\t{modName}:"); foreach (var modEntry in modManifest[modName]) { // type being null means we have to figure out the type from the path (StreamingAssets) if (modEntry.Type == null) { // TODO: + 16 is a little bizzare looking, it's the length of the substring + 1 because we want to get rid of it and the \ var relPath = modEntry.Path.Substring(modEntry.Path.LastIndexOf("StreamingAssets", StringComparison.Ordinal) + 16); var fakeStreamingAssetsPath = Path.GetFullPath(Path.Combine(StreamingAssetsDirectory, relPath)); List <string> types; if (typeCache.ContainsKey(fakeStreamingAssetsPath)) { types = typeCache[fakeStreamingAssetsPath]; } else { // get the type from the manifest var matchingEntries = manifest.FindAll(x => Path.GetFullPath(x.FilePath) == fakeStreamingAssetsPath); if (matchingEntries == null || matchingEntries.Count == 0) { Log($"\t\tCould not find an existing VersionManifest entry for {modEntry.Id}. Is this supposed to be a new entry? Don't put new entries in StreamingAssets!"); continue; } types = new List <string>(); foreach (var existingEntry in matchingEntries) { types.Add(existingEntry.Type); } typeCache[fakeStreamingAssetsPath] = types; } if (Path.GetExtension(modEntry.Path).ToLower() == ".json" && modEntry.ShouldMergeJSON) { if (!typeCache.ContainsKey(fakeStreamingAssetsPath)) { Log($"\t\tUnable to determine type of {modEntry.Id}. Is there someone screwy with your this mod.json?"); continue; } if (!jsonMerges.ContainsKey(fakeStreamingAssetsPath)) { jsonMerges[fakeStreamingAssetsPath] = new List <string>(); } if (jsonMerges[fakeStreamingAssetsPath].Contains(modEntry.Path)) { continue; } // this assumes that .json can only have a single type modEntry.Type = typeCache[fakeStreamingAssetsPath][0]; Log($"\t\tMerge => {modEntry.Id} ({modEntry.Type})"); jsonMerges[fakeStreamingAssetsPath].Add(modEntry.Path); continue; } foreach (var type in types) { var subModEntry = new ModDef.ManifestEntry(modEntry, modEntry.Path, modEntry.Id); subModEntry.Type = type; if (AddModEntry(manifest, subModEntry)) { modEntries.Add(subModEntry); } } continue; } // get "fake" entries that don't actually go into the game's VersionManifest // add videos to be loaded from an external path if (modEntry.Type == "Video") { var fileName = Path.GetFileName(modEntry.Path); if (fileName != null && File.Exists(modEntry.Path)) { Log($"\t\tVideo => {fileName}"); ModVideos.Add(fileName, modEntry.Path); } continue; } // non-streamingassets json merges if (Path.GetExtension(modEntry.Path)?.ToLower() == ".json" && modEntry.ShouldMergeJSON) { // have to find the original path for the manifest entry that we're merging onto var matchingEntry = manifest.Find(x => x.Id == modEntry.Id); if (matchingEntry == null) { Log($"\t\tCould not find an existing VersionManifest entry for {modEntry.Id}!"); continue; } if (!jsonMerges.ContainsKey(matchingEntry.FilePath)) { jsonMerges[matchingEntry.FilePath] = new List <string>(); } if (jsonMerges[matchingEntry.FilePath].Contains(modEntry.Path)) { continue; } // this assumes that .json can only have a single type modEntry.Type = matchingEntry.Type; if (!typeCache.ContainsKey(matchingEntry.FilePath)) { typeCache[matchingEntry.FilePath] = new List <string>(); typeCache[matchingEntry.FilePath].Add(modEntry.Type); } Log($"\t\tMerge => {modEntry.Id} ({modEntry.Type})"); jsonMerges[matchingEntry.FilePath].Add(modEntry.Path); continue; } if (AddModEntry(manifest, modEntry)) { modEntries.Add(modEntry); } } } // write type cache to disk WriteJsonFile(TypeCachePath, typeCache); // perform merges into cache LogWithDate("Doing merges..."); foreach (var jsonMerge in jsonMerges) { var cachePath = jsonMergeCache.GetOrCreateCachedEntry(jsonMerge.Key, jsonMerge.Value); // something went wrong (the parent json prob had errors) if (cachePath == null) { continue; } var cacheEntry = new ModDef.ManifestEntry(cachePath); cacheEntry.ShouldMergeJSON = false; cacheEntry.Type = typeCache[jsonMerge.Key][0]; cacheEntry.Id = InferIDFromFile(cachePath); if (AddModEntry(manifest, cacheEntry)) { modEntries.Add(cacheEntry); } } // write merge cache to disk jsonMergeCache.WriteCacheToDisk(Path.Combine(CacheDirectory, MERGE_CACHE_FILE_NAME)); LogWithDate("Adding to DB..."); // check if files removed from DB cache var rebuildDB = false; var replacementEntries = new List <VersionManifestEntry>(); var removeEntries = new List <string>(); foreach (var kvp in dbCache) { var path = kvp.Key; if (File.Exists(path)) { continue; } Log($"\tNeed to remove DB entry from file in path: {path}"); // file is missing, check if another entry exists with same filename in manifest var fileName = Path.GetFileName(path); var existingEntry = manifest.Find(x => Path.GetFileName(x.FilePath) == fileName); if (existingEntry == null) { Log("\t\tHave to rebuild DB, no existing entry in VersionManifest matches removed entry"); rebuildDB = true; break; } replacementEntries.Add(existingEntry); removeEntries.Add(path); } // add removed entries replacements to db if (!rebuildDB) { // remove old entries foreach (var removeEntry in removeEntries) { dbCache.Remove(removeEntry); } using (var metadataDatabase = new MetadataDatabase()) { foreach (var replacementEntry in replacementEntries) { if (AddModEntryToDB(metadataDatabase, Path.GetFullPath(replacementEntry.FilePath), replacementEntry.Type)) { Log($"\t\tReplaced DB entry with an existing entry in path: {Path.GetFullPath(replacementEntry.FilePath)}"); } } } } // if an entry has been removed and we cannot find a replacement, have to rebuild the mod db if (rebuildDB) { if (File.Exists(ModDBPath)) { File.Delete(ModDBPath); } File.Copy(Path.Combine(Path.Combine(StreamingAssetsDirectory, "MDD"), MDD_FILE_NAME), ModDBPath); dbCache = new Dictionary <string, DateTime>(); } // add needed files to db using (var metadataDatabase = new MetadataDatabase()) { foreach (var modEntry in modEntries) { if (modEntry.AddToDB && AddModEntryToDB(metadataDatabase, modEntry.Path, modEntry.Type)) { Log($"\tAdded/Updated {modEntry.Id} ({modEntry.Type})"); } } } // write db/type cache to disk WriteJsonFile(DBCachePath, dbCache); stopwatch.Stop(); Log(""); LogWithDate($"Done. Elapsed running time: {stopwatch.Elapsed.TotalSeconds} seconds\n"); }
private static JoinConditionGroup To(SqlBuilder Builder, Table FromSqlTable, MetadataTable FromTable, MetadataColumn FromField, MetadataTable ToTable, Join.JoinTypes JoinType, bool PreferForeignKeyOverPrimaryKey = true) { MetadataDatabase mdb = Builder.Metadata; List <MetadataForeignKey> Fks = null; MetadataForeignKey FK = null; Join j = null; MetadataColumnReference mcr = null; JoinConditionGroup jcg = null; if (FromField.IsPrimaryKey) { if (!FromField.IsForeignKey || !PreferForeignKeyOverPrimaryKey) { Fks = ToTable.ForeignKeys.Values.Where(x => x.ReferencedTable.Equals(FromTable.Name) && x.ReferencedSchema.Equals(FromTable.Schema) && x.ColumnReferences.Any(y => y.ReferencedColumn.Equals(FromField))).ToList(); if (Fks.Count != 1) { throw new InvalidOperationException(string.Format("The column '{0}' is referenced by {1} keys in the table {2}. Expected 1. Make the join manually", FromField.Name, Fks.Count, ToTable.Fullname)); } FK = Fks.First(); j = SqlStatementExtensions.MakeJoin(JoinType, FromSqlTable, ToTable.Name, null, ToTable.Schema.Equals("dbo") ? null : ToTable.Schema); mcr = FK.ColumnReferences.First(); jcg = j.On(FromField.Name, SqlOperators.Equal, mcr.Name); return(jcg); } } if (FromField.IsForeignKey) { Fks = new List <MetadataForeignKey>(FromTable.FindForeignKeys(FromField, ToTable.Name)); if (Fks.Count != 1) { throw new InvalidOperationException(string.Format("The column '{0}' resolves to {1} keys in the table {2}. Expected 1. Make the join manually", FromField.Name, Fks.Count, ToTable.Fullname)); } FK = Fks.First(); j = SqlStatementExtensions.MakeJoin(JoinType, FromSqlTable, ToTable.Name, null, ToTable.Schema.Equals("dbo") ? null : ToTable.Schema); mcr = FK.ColumnReferences.First(); jcg = j.On(FromField.Name, SqlOperators.Equal, mcr.ReferencedColumn.Name); if (FK.ColumnReferences.Count > 1) { foreach (MetadataColumnReference mcr2 in FK.ColumnReferences.Skip(1)) { if (mcr2.Name.StartsWith("\"")) { // its a value reference // jcg.And(FK.ReferencedTable, mcr2.ReferencedColumn.Name, SqlOperators.Equal, mcr2.Name.Trim('\"'),null); decimal d; object o; if (decimal.TryParse(mcr2.Name.Trim('\"'), out d)) { o = d; } else { o = (object)mcr2.Name.Trim('\"'); } jcg.And(mcr2.ReferencedColumn.Name, SqlOperators.Equal, o, null); } else { jcg.And(mcr2.Column.Name, SqlOperators.Equal, mcr2.ReferencedColumn.Name); } } } return(jcg); } throw new ArgumentException(string.Format("The Column '{0}' in the table '{1}' must be a foreign key or primary key", FromField.Name, FromTable.Fullname), "FromField"); }
public static void Postfix(UnitSpawnPointOverride __instance, UnitDef_MDD __result, MetadataDatabase mdd, TagSet unitTagSet, TagSet unitExcludedTagSet, string lanceName, TagSet companyTags) { try { Logger.Debug("----------------------------------------------------------------------------------------------------"); Logger.Debug("[UnitSpawnPointOverride_SelectTaggedUnitDef_POSTFIX] lanceName: " + lanceName); Logger.Debug("[UnitSpawnPointOverride_SelectTaggedUnitDef_POSTFIX] __result.UnitDefID: " + __result.UnitDefID); /* * Logger.Debug($"[UnitSpawnPointOverride_SelectTaggedUnitDef_POSTFIX] __result.GetRequiredToSpawnCompanyTagSet(): { String.Join(", ", __result.GetRequiredToSpawnCompanyTagSet().ToArray())}"); * Logger.Debug($"[UnitSpawnPointOverride_SelectTaggedUnitDef_POSTFIX] companyTags: { String.Join(", ", companyTags.ToArray())}"); * if (companyTags != null && !companyTags.ContainsAll(__result.GetRequiredToSpawnCompanyTagSet())) * { * Logger.Debug($"[UnitSpawnPointOverride_SelectTaggedUnitDef_POSTFIX] WARNING: {__result.UnitDefID} should NOT spawn yet!"); * } */ } catch (Exception e) { Logger.Error(e); } }
public static void TagSetQueryExtensions_GetMatchingUnitDefs_Postfix(MetadataDatabase __instance, TagSet requiredTags, DateTime?currentDate, ref List <UnitDef_MDD> __result) { Logger.Debug($"Executing [{nameof(TagSetQueryExtensions_GetMatchingUnitDefs_Postfix)}],\r\n" + $"RequiredTags = [{string.Join(", ", requiredTags)}]\r\n" + $"MatchingDataByTagSet = [{string.Join("\r\n", __result.Select(defMdd => defMdd.UnitDefID))}]..."); if (requiredTags.Contains("unit_vehicle") || requiredTags.Contains("unit_turret")) { Logger.Debug($"Bypassing lance spawn morph as required tags are not looking for mechs..."); return; } else if (__result.Count == 0) { Logger.Debug($"Bypassing lance spawn morph as initial result is empty..."); return; } // Alias the keywords for readability... var mdd = __instance; var matchingDataByTagSet = __result; var simGameState = UnityGameInstance.BattleTechGame.Simulation; var filteredList = new List <UnitDef_MDD>(); // Group matching unitDef_MDD records by their associated prefabIdentifier var unitsGroupedByPrefab = matchingDataByTagSet .Select(defMdd => new { unitDefMdd = defMdd, mechDef = simGameState.DataManager.MechDefs.First(pair => pair.Key == defMdd.UnitDefID).Value }) .GroupBy(arg => arg.mechDef.Chassis.PrefabIdentifier, arg => arg, (s, enumerable) => new { Base = s, Units = enumerable }) .ToList(); Logger.Debug($"Grouped result list into [\r\n" + $"{string.Join("\r\n", unitsGroupedByPrefab.Select(arg => $"[{arg.Base}] -> {string.Join(", ", arg.Units.Select(arg1 => arg1.unitDefMdd.UnitDefID))}"))}]"); // var prefabVariantsOccuringOnce = unitsGroupedByPrefab.Where(arg => arg.Units.Count() == 1).SelectMany(arg => arg.Units).ToList(); foreach (var prefabGroup in unitsGroupedByPrefab) { Logger.Debug($"Processing units for prefab [{prefabGroup.Base}]..."); var prefabSelectionList = new List <UnitDef_MDD>(); foreach (var unit in prefabGroup.Units) { Logger.Trace($"Processing unit [{unit.mechDef.Description.Id}], CurrentDate = [{currentDate}], MinAppearanceDate = [{unit.mechDef.MinAppearanceDate}]..."); // For mechs with an appearance date (and current date is set, which it should always be) // 1. Each entry gets a rarityWeighting + 1 per 30 days since appearance date has passed // 2. To a maximum of 6 (so mechs that appeared at least 180 days prior to the current date receive the maximum rarity weighting) // These following two variables ought to be set via [Settings] in the mod.json... var rarityWeighting = Myself.Settings.MaxRarityWeighting; if (currentDate != null && unit.mechDef.MinAppearanceDate != null) { // Could do this in only one statement, but that ended up being a little kludgy and hard to read... var rawDays = (currentDate - unit.mechDef.MinAppearanceDate).Value.TotalDays + 1; var roundedDays = Math.Round(rawDays / Myself.Settings.RarityWeightingDaysDivisor, 0); var rawRarity = Convert.ToInt32(roundedDays); rarityWeighting = Math.Min(rawRarity, Myself.Settings.MaxRarityWeighting); if (rarityWeighting <= 0) { Logger.Trace($"Rarity negative for [{unit.unitDefMdd.UnitDefID}], fixing to 1..."); rarityWeighting = 1; } Logger.Trace($"Raw Days = [{rawDays}], " + $"Rounded Days = [{roundedDays}], " + $"Raw Rarity = [{rawRarity}], " + $"Final Rarity Rating = [{rarityWeighting}]"); } // Insert multiple copies of unitDefMdd to influence the RNG selection weighted by rarity, appropriately... for (var i = 0; i < rarityWeighting; i++) { Logger.Trace($"Adding [{unit.unitDefMdd.UnitDefID}] to prefabSelectionList..."); prefabSelectionList.Add(unit.unitDefMdd); } } Logger.Trace($"PrefabSelectionList count = [{prefabSelectionList.Count}]"); var prefabSelectionListGroupByPrefab = prefabSelectionList .Select(defMdd => new { unitDefMdd = defMdd, mechDef = simGameState.DataManager.MechDefs.First(pair => pair.Key == defMdd.UnitDefID).Value }) .GroupBy(arg => arg.unitDefMdd.UnitDefID, arg => arg, (s, enumerable) => new { Base = s, units = enumerable }); Logger.Debug($"Final Prefab Selection List = [\r\n" + $"{string.Join("\r\n", prefabSelectionListGroupByPrefab.Select(arg => $"[{arg.Base}] - Count [{arg.units.Count()}]"))}" + $"]"); // Select one variant of the prefab base to include as an option in the filtered list... Logger.Trace($"Shuffling prefab selection list..."); prefabSelectionList.Shuffle(); var selectedPrefabVariant = prefabSelectionList[0]; Logger.Debug($"Selected [{selectedPrefabVariant.UnitDefID} for inclusion in final filtered list...]"); filteredList.Add(selectedPrefabVariant); } Logger.Debug($"Final filtered list = [\r\n" + $"{string.Join("\r\n", filteredList.Select(defMdd => defMdd.UnitDefID))}" + $"]"); __result = filteredList; }
internal static IEnumerator <ProgressReport> BuildCachedManifestLoop(VersionManifest manifest) { stopwatch.Start(); // there are no mods loaded, just return if (modLoadOrder == null || modLoadOrder.Count == 0) { yield break; } string loadingModText = "Loading Mod Manifests"; yield return(new ProgressReport(0.0f, loadingModText, "Setting up mod manifests...")); LogWithDate("Setting up mod manifests..."); var jsonMerges = new Dictionary <string, List <string> >(); modEntries = new List <ModDef.ManifestEntry>(); int modCount = 0; var manifestMods = modLoadOrder.Where(name => modManifest.ContainsKey(name)).ToList(); foreach (var modName in manifestMods) { Log($"\t{modName}:"); yield return(new ProgressReport((float)modCount++ / (float)manifestMods.Count, loadingModText, string.Format("Loading manifest for {0}", modName))); foreach (var modEntry in modManifest[modName]) { // type being null means we have to figure out the type from the path (StreamingAssets) if (modEntry.Type == null) { // TODO: + 16 is a little bizzare looking, it's the length of the substring + 1 because we want to get rid of it and the \ var relPath = modEntry.Path.Substring(modEntry.Path.LastIndexOf("StreamingAssets", StringComparison.Ordinal) + 16); var fakeStreamingAssetsPath = Path.GetFullPath(Path.Combine(StreamingAssetsDirectory, relPath)); var types = GetTypesFromCacheOrManifest(manifest, fakeStreamingAssetsPath); if (types == null) { Log($"\t\tCould not find an existing VersionManifest entry for {modEntry.Id}. Is this supposed to be a new entry? Don't put new entries in StreamingAssets!"); continue; } if (Path.GetExtension(modEntry.Path).ToLower() == ".json" && modEntry.ShouldMergeJSON) { if (!jsonMerges.ContainsKey(fakeStreamingAssetsPath)) { jsonMerges[fakeStreamingAssetsPath] = new List <string>(); } if (jsonMerges[fakeStreamingAssetsPath].Contains(modEntry.Path)) { continue; } // this assumes that .json can only have a single type // typeCache will always contain this path modEntry.Type = typeCache[fakeStreamingAssetsPath][0]; Log($"\t\tMerge => {modEntry.Id} ({modEntry.Type})"); jsonMerges[fakeStreamingAssetsPath].Add(modEntry.Path); continue; } foreach (var type in types) { var subModEntry = new ModDef.ManifestEntry(modEntry, modEntry.Path, modEntry.Id); subModEntry.Type = type; if (AddModEntry(manifest, subModEntry)) { modEntries.Add(subModEntry); } } continue; } // get "fake" entries that don't actually go into the game's VersionManifest // add videos to be loaded from an external path switch (modEntry.Type) { case "Video": var fileName = Path.GetFileName(modEntry.Path); if (fileName != null && File.Exists(modEntry.Path)) { Log($"\t\tVideo => {fileName}"); ModVideos.Add(fileName, modEntry.Path); } continue; case "AdvancedJSONMerge": var targetFileRelative = AdvancedJSONMerger.GetTargetFile(modEntry.Path); var targetFile = ResolvePath(targetFileRelative); // need to add the types of the file to the typeCache, so that they can be used later // this actually returns the type, but we don't actually care about that right now GetTypesFromCacheOrManifest(manifest, targetFile); if (!jsonMerges.ContainsKey(targetFile)) { jsonMerges[targetFile] = new List <string>(); } if (jsonMerges[targetFile].Contains(modEntry.Path)) { continue; } Log($"\t\tAdvancedJSONMerge => {modEntry.Id} ({modEntry.Type})"); jsonMerges[targetFile].Add(modEntry.Path); continue; } // non-streamingassets json merges if (Path.GetExtension(modEntry.Path)?.ToLower() == ".json" && modEntry.ShouldMergeJSON) { // have to find the original path for the manifest entry that we're merging onto var matchingEntry = manifest.Find(x => x.Id == modEntry.Id); if (matchingEntry == null) { Log($"\t\tCould not find an existing VersionManifest entry for {modEntry.Id}!"); continue; } if (!jsonMerges.ContainsKey(matchingEntry.FilePath)) { jsonMerges[matchingEntry.FilePath] = new List <string>(); } if (jsonMerges[matchingEntry.FilePath].Contains(modEntry.Path)) { continue; } // this assumes that .json can only have a single type modEntry.Type = matchingEntry.Type; if (!typeCache.ContainsKey(matchingEntry.FilePath)) { typeCache[matchingEntry.FilePath] = new List <string>(); typeCache[matchingEntry.FilePath].Add(modEntry.Type); } Log($"\t\tMerge => {modEntry.Id} ({modEntry.Type})"); jsonMerges[matchingEntry.FilePath].Add(modEntry.Path); continue; } if (AddModEntry(manifest, modEntry)) { modEntries.Add(modEntry); } } } yield return(new ProgressReport(100.0f, "JSON", "Writing JSON file to disk")); // write type cache to disk WriteJsonFile(TypeCachePath, typeCache); // perform merges into cache LogWithDate("Doing merges..."); yield return(new ProgressReport(0.0f, "Merges", "Doing Merges...")); int mergeCount = 0; foreach (var jsonMerge in jsonMerges) { yield return(new ProgressReport((float)mergeCount++ / jsonMerges.Count, "Merges", string.Format("Merging {0}", jsonMerge.Key))); var cachePath = jsonMergeCache.GetOrCreateCachedEntry(jsonMerge.Key, jsonMerge.Value); // something went wrong (the parent json prob had errors) if (cachePath == null) { continue; } var cacheEntry = new ModDef.ManifestEntry(cachePath); cacheEntry.ShouldMergeJSON = false; cacheEntry.Type = typeCache[jsonMerge.Key][0]; // this assumes only one type for each json file cacheEntry.Id = InferIDFromFile(cachePath); if (AddModEntry(manifest, cacheEntry)) { modEntries.Add(cacheEntry); } } yield return(new ProgressReport(100.0f, "Merge Cache", "Writing Merge Cache to disk")); // write merge cache to disk jsonMergeCache.WriteCacheToDisk(Path.Combine(CacheDirectory, MERGE_CACHE_FILE_NAME)); LogWithDate("Adding to DB..."); // check if files removed from DB cache var rebuildDB = false; var replacementEntries = new List <VersionManifestEntry>(); var removeEntries = new List <string>(); string dbText = "Syncing Database"; yield return(new ProgressReport(0.0f, dbText, "")); foreach (var kvp in dbCache) { var path = kvp.Key; if (File.Exists(path)) { continue; } Log($"\tNeed to remove DB entry from file in path: {path}"); // file is missing, check if another entry exists with same filename in manifest var fileName = Path.GetFileName(path); var existingEntry = manifest.Find(x => Path.GetFileName(x.FilePath) == fileName); if (existingEntry == null) { Log("\t\tHave to rebuild DB, no existing entry in VersionManifest matches removed entry"); rebuildDB = true; break; } replacementEntries.Add(existingEntry); removeEntries.Add(path); } // add removed entries replacements to db dbText = "Cleaning Database"; yield return(new ProgressReport(100.0f, dbText, "")); if (!rebuildDB) { // remove old entries foreach (var removeEntry in removeEntries) { dbCache.Remove(removeEntry); } using (var metadataDatabase = new MetadataDatabase()) { foreach (var replacementEntry in replacementEntries) { if (AddModEntryToDB(metadataDatabase, Path.GetFullPath(replacementEntry.FilePath), replacementEntry.Type)) { Log($"\t\tReplaced DB entry with an existing entry in path: {Path.GetFullPath(replacementEntry.FilePath)}"); } } } } // if an entry has been removed and we cannot find a replacement, have to rebuild the mod db if (rebuildDB) { if (File.Exists(ModMDDBPath)) { File.Delete(ModMDDBPath); } File.Copy(MDDBPath, ModMDDBPath); dbCache = new Dictionary <string, DateTime>(); } // add needed files to db dbText = "Populating Database"; int addCount = 0; yield return(new ProgressReport(0.0f, dbText, "")); using (var metadataDatabase = new MetadataDatabase()) { foreach (var modEntry in modEntries) { if (modEntry.AddToDB && AddModEntryToDB(metadataDatabase, modEntry.Path, modEntry.Type)) { yield return(new ProgressReport((float)addCount / (float)modEntries.Count, dbText, string.Format("Added {0}", modEntry.Path))); Log($"\tAdded/Updated {modEntry.Id} ({modEntry.Type})"); } addCount++; } } // write db/type cache to disk WriteJsonFile(DBCachePath, dbCache); stopwatch.Stop(); Log(""); LogWithDate($"Done. Elapsed running time: {stopwatch.Elapsed.TotalSeconds} seconds\n"); // Cache the completed manifest ModTek.cachedManifest = manifest; try { if (manifest != null && ModTek.modEntries != null) { ModTek.modtekOverrides = manifest.Entries.Where(e => ModTek.modEntries.Any(m => e.Id == m.Id)) // ToDictionary expects distinct keys, so take the last entry of each Id .GroupBy(ks => ks.Id) .Select(v => v.Last()) .ToDictionary(ks => ks.Id); } Logger.Log("Built {0} modtek overrides", ModTek.modtekOverrides.Count()); } catch (Exception e) { Logger.Log("Failed to build overrides {0}", e); } yield break; }
public static bool CacheMetadata(string MetadataKey, MetadataDatabase mdb, CacheItemPolicy Policy = null) { if (MemoryCache.Default.Contains(MetadataKey)) { return true; } CacheItem item = MemoryCache.Default.AddOrGetExisting(new CacheItem(MetadataKey, SerializationExtensions.ToJson<MetadataDatabase>(mdb)), (Policy ?? CachePolicy)); return item.Value == null; }
internal static void TryAddToVersionManifest(VersionManifest manifest) { if (!hasLoadedMods) { LoadMods(); } var breakMyGame = File.Exists(Path.Combine(ModDirectory, "break.my.game")); LogWithDate("Adding in mod manifests!"); if (breakMyGame) { var mddPath = Path.Combine(Path.Combine(StreamingAssetsDirectory, "MDD"), "MetadataDatabase.db"); var mddBackupPath = mddPath + ".orig"; Log($"\tBreak my game mode enabled! All new modded content (doesn't currently support merges) will be added to the DB."); if (!File.Exists(mddBackupPath)) { Log($"\t\tBacking up metadata database to {Path.GetFileName(mddBackupPath)}"); File.Copy(mddPath, mddBackupPath); } } foreach (var modName in modLoadOrder) { if (!ModManifest.ContainsKey(modName)) { continue; } Log($"\t{modName}:"); foreach (var modEntry in ModManifest[modName]) { var existingEntry = manifest.Find(x => x.Id == modEntry.Id); VersionManifestAddendum addendum = null; if (!string.IsNullOrEmpty(modEntry.AddToAddendum)) { addendum = manifest.GetAddendumByName(modEntry.AddToAddendum); // create the addendum if it doesn't exist if (addendum == null) { Log($"\t\tCreated addendum {modEntry.AddToAddendum}:"); addendum = new VersionManifestAddendum(modEntry.AddToAddendum); manifest.ApplyAddendum(addendum); } } if (modEntry.Type == null) { // null type means that we have to find existing entry with the same rel path to fill in the entry // TODO: + 16 is a little bizzare looking, it's the length of the substring + 1 because we want to get rid of it and the \ var relPath = modEntry.Path.Substring(modEntry.Path.LastIndexOf("StreamingAssets", StringComparison.Ordinal) + 16); var fakeStreamingAssetsPath = Path.Combine(StreamingAssetsDirectory, relPath); existingEntry = manifest.Find(x => Path.GetFullPath(x.FilePath) == Path.GetFullPath(fakeStreamingAssetsPath)); if (existingEntry == null) { continue; } modEntry.Id = existingEntry.Id; modEntry.Type = existingEntry.Type; } if (Path.GetExtension(modEntry.Path).ToLower() == ".json" && modEntry.ShouldMergeJSON && existingEntry != null) { // read the manifest pointed entry and hash the contents JsonHashToId[File.ReadAllText(existingEntry.FilePath).GetHashCode()] = modEntry.Id; // The manifest already contains this information, so we need to queue it to be merged var partialJson = File.ReadAllText(modEntry.Path); if (!JsonMerges.ContainsKey(modEntry.Id)) { JsonMerges.Add(modEntry.Id, new List <string>()); } if (JsonMerges[modEntry.Id].Contains(partialJson)) { Log($"\t\tAlready added {modEntry.Id} to JsonMerges"); continue; } Log($"\t\tAdding {modEntry.Id} to JsonMerges"); JsonMerges[modEntry.Id].Add(partialJson); continue; } if (breakMyGame && Path.GetExtension(modEntry.Path).ToLower() == ".json") { var type = (BattleTechResourceType)Enum.Parse(typeof(BattleTechResourceType), modEntry.Type); using (var metadataDatabase = new MetadataDatabase()) { VersionManifestHotReload.InstantiateResourceAndUpdateMDDB(type, modEntry.Path, metadataDatabase); Log($"\t\tAdding to MDDB! {type} {modEntry.Path}"); } } if (!string.IsNullOrEmpty(modEntry.AddToAddendum)) { Log($"\t\tAddOrUpdate {modEntry.Type} {modEntry.Id} to addendum {addendum.Name}"); addendum.AddOrUpdate(modEntry.Id, modEntry.Path, modEntry.Type, DateTime.Now, modEntry.AssetBundleName, modEntry.AssetBundlePersistent); continue; } // This is a new definition or a replacement that doesn't get merged, so add or update the manifest Log($"\t\tAddOrUpdate {modEntry.Type} {modEntry.Id}"); manifest.AddOrUpdate(modEntry.Id, modEntry.Path, modEntry.Type, DateTime.Now, modEntry.AssetBundleName, modEntry.AssetBundlePersistent); } } Log(""); }
internal static IEnumerator <ProgressReport> BuildModManifestEntriesLoop() { stopwatch.Start(); // there are no mods loaded, just return if (modLoadOrder == null || modLoadOrder.Count == 0) { yield break; } Log(""); var jsonMerges = new Dictionary <string, List <string> >(); var manifestMods = modLoadOrder.Where(name => entriesByMod.ContainsKey(name)).ToList(); var entryCount = 0; var numEntries = 0; entriesByMod.Do(entries => numEntries += entries.Value.Count); foreach (var modName in manifestMods) { Log($"{modName}:"); foreach (var modEntry in entriesByMod[modName]) { yield return(new ProgressReport(entryCount++ / ((float)numEntries), $"Loading {modName}", modEntry.Id)); // type being null means we have to figure out the type from the path (StreamingAssets) if (modEntry.Type == null) { // TODO: + 16 is a little bizzare looking, it's the length of the substring + 1 because we want to get rid of it and the \ var relPath = modEntry.Path.Substring(modEntry.Path.LastIndexOf("StreamingAssets", StringComparison.Ordinal) + 16); var fakeStreamingAssetsPath = Path.GetFullPath(Path.Combine(StreamingAssetsDirectory, relPath)); if (!File.Exists(fakeStreamingAssetsPath)) { Log($"\tCould not find a file at {fakeStreamingAssetsPath} for {modName} {modEntry.Id}. NOT LOADING THIS FILE"); continue; } var types = GetTypesFromCacheOrManifest(CachedVersionManifest, modEntry.Id); if (types == null) { Log($"\tCould not find an existing VersionManifest entry for {modEntry.Id}. Is this supposed to be a new entry? Don't put new entries in StreamingAssets!"); continue; } // this is getting merged later and then added to the BTRL entries then if (Path.GetExtension(modEntry.Path).ToLower() == ".json" && modEntry.ShouldMergeJSON) { if (!jsonMerges.ContainsKey(modEntry.Id)) { jsonMerges[modEntry.Id] = new List <string>(); } if (jsonMerges[modEntry.Id].Contains(modEntry.Path)) // TODO: is this necessary? { continue; } // this assumes that .json can only have a single type // typeCache will always contain this path modEntry.Type = GetTypesFromCache(modEntry.Id)[0]; Log($"\tMerge: \"{GetRelativePath(modEntry.Path, ModsDirectory)}\" ({modEntry.Type})"); jsonMerges[modEntry.Id].Add(modEntry.Path); continue; } foreach (var type in types) { var subModEntry = new ModDef.ManifestEntry(modEntry, modEntry.Path, modEntry.Id); subModEntry.Type = type; AddModEntry(CachedVersionManifest, subModEntry); // clear json merges for this entry, mod is overwriting the original file, previous mods merges are tossed if (jsonMerges.ContainsKey(modEntry.Id)) { jsonMerges.Remove(modEntry.Id); Log($"\t\tHad merges for {modEntry.Id} but had to toss, since original file is being replaced"); } } continue; } // get "fake" entries that don't actually go into the game's VersionManifest // add videos to be loaded from an external path switch (modEntry.Type) { case "Video": var fileName = Path.GetFileName(modEntry.Path); if (fileName != null && File.Exists(modEntry.Path)) { Log($"\tVideo: \"{GetRelativePath(modEntry.Path, ModsDirectory)}\""); ModVideos.Add(fileName, modEntry.Path); } continue; case "AdvancedJSONMerge": var id = AdvancedJSONMerger.GetTargetID(modEntry.Path); // need to add the types of the file to the typeCache, so that they can be used later // if merging onto a file added by another mod, the type is already in the cache var types = GetTypesFromCacheOrManifest(CachedVersionManifest, id); if (!jsonMerges.ContainsKey(id)) { jsonMerges[id] = new List <string>(); } if (jsonMerges[id].Contains(modEntry.Path)) // TODO: is this necessary? { continue; } Log($"\tAdvancedJSONMerge: \"{GetRelativePath(modEntry.Path, ModsDirectory)}\" ({types[0]})"); jsonMerges[id].Add(modEntry.Path); continue; } // non-streamingassets json merges if (Path.GetExtension(modEntry.Path)?.ToLower() == ".json" && modEntry.ShouldMergeJSON) { // have to find the original path for the manifest entry that we're merging onto var matchingEntry = GetEntryFromCachedOrBTRLEntries(modEntry.Id); if (matchingEntry == null) { Log($"\tCould not find an existing VersionManifest entry for {modEntry.Id}!"); continue; } var matchingPath = Path.GetFullPath(matchingEntry.FilePath); if (!jsonMerges.ContainsKey(modEntry.Id)) { jsonMerges[modEntry.Id] = new List <string>(); } if (jsonMerges[modEntry.Id].Contains(modEntry.Path)) // TODO: is this necessary? { continue; } Log($"\tMerge: \"{GetRelativePath(modEntry.Path, ModsDirectory)}\" ({modEntry.Type})"); // this assumes that .json can only have a single type modEntry.Type = matchingEntry.Type; TryAddTypeToCache(modEntry.Id, modEntry.Type); jsonMerges[modEntry.Id].Add(modEntry.Path); continue; } AddModEntry(CachedVersionManifest, modEntry); TryAddTypeToCache(modEntry.Id, modEntry.Type); // clear json merges for this entry, mod is overwriting the original file, previous mods merges are tossed if (jsonMerges.ContainsKey(modEntry.Id)) { jsonMerges.Remove(modEntry.Id); Log($"\t\tHad merges for {modEntry.Id} but had to toss, since original file is being replaced"); } } } WriteJsonFile(TypeCachePath, typeCache); // perform merges into cache Log(""); LogWithDate("Doing merges..."); yield return(new ProgressReport(1, "Merging", "")); var mergeCount = 0; foreach (var id in jsonMerges.Keys) { var existingEntry = GetEntryFromCachedOrBTRLEntries(id); if (existingEntry == null) { Log($"\tHave merges for {id} but cannot find an original file! Skipping."); continue; } var originalPath = Path.GetFullPath(existingEntry.FilePath); var mergePaths = jsonMerges[id]; if (!jsonMergeCache.HasCachedEntry(originalPath, mergePaths)) { yield return(new ProgressReport(mergeCount++ / ((float)jsonMerges.Count), "Merging", id)); } var cachePath = jsonMergeCache.GetOrCreateCachedEntry(originalPath, mergePaths); // something went wrong (the parent json prob had errors) if (cachePath == null) { continue; } var cacheEntry = new ModDef.ManifestEntry(cachePath) { ShouldMergeJSON = false, Type = GetTypesFromCache(id)[0], // this assumes only one type for each json file Id = id }; AddModEntry(CachedVersionManifest, cacheEntry); } jsonMergeCache.WriteCacheToDisk(Path.Combine(CacheDirectory, MERGE_CACHE_FILE_NAME)); Log(""); Log("Syncing Database"); yield return(new ProgressReport(1, "Syncing Database", "")); // check if files removed from DB cache var rebuildDB = false; var replacementEntries = new List <VersionManifestEntry>(); var removeEntries = new List <string>(); foreach (var path in dbCache.Keys) { var absolutePath = ResolvePath(path, GameDirectory); // check if the file in the db cache is still used if (BTRLEntries.Exists(x => x.Path == absolutePath)) { continue; } Log($"\tNeed to remove DB entry from file in path: {path}"); // file is missing, check if another entry exists with same filename in manifest or in BTRL entries var fileName = Path.GetFileName(path); var existingEntry = BTRLEntries.FindLast(x => Path.GetFileName(x.Path) == fileName)?.GetVersionManifestEntry() ?? CachedVersionManifest.Find(x => Path.GetFileName(x.FilePath) == fileName); if (existingEntry == null) { Log("\t\tHave to rebuild DB, no existing entry in VersionManifest matches removed entry"); rebuildDB = true; break; } replacementEntries.Add(existingEntry); removeEntries.Add(path); } // add removed entries replacements to db if (!rebuildDB) { // remove old entries foreach (var removeEntry in removeEntries) { dbCache.Remove(removeEntry); } using (var metadataDatabase = new MetadataDatabase()) { foreach (var replacementEntry in replacementEntries) { if (AddModEntryToDB(metadataDatabase, Path.GetFullPath(replacementEntry.FilePath), replacementEntry.Type)) { Log($"\t\tReplaced DB entry with an existing entry in path: {Path.GetFullPath(replacementEntry.FilePath)}"); } } } } // if an entry has been removed and we cannot find a replacement, have to rebuild the mod db if (rebuildDB) { if (File.Exists(ModMDDBPath)) { File.Delete(ModMDDBPath); } File.Copy(MDDBPath, ModMDDBPath); dbCache = new Dictionary <string, DateTime>(); } // add needed files to db var addCount = 0; using (var metadataDatabase = new MetadataDatabase()) { foreach (var modEntry in BTRLEntries) { if (modEntry.AddToDB && AddModEntryToDB(metadataDatabase, modEntry.Path, modEntry.Type)) { yield return(new ProgressReport(addCount / ((float)BTRLEntries.Count), "Populating Database", modEntry.Id)); Log($"\tAdded/Updated {modEntry.Id} ({modEntry.Type})"); } addCount++; } } // write db/type cache to disk WriteJsonFile(DBCachePath, dbCache); stopwatch.Stop(); Log(""); LogWithDate($"Done. Elapsed running time: {stopwatch.Elapsed.TotalSeconds} seconds\n"); CloseLogStream(); yield break; }
public MetadataDatabase BuildMetadata(bool PrimaryKeyIndexOnly = true, string[] Tables = null, bool UpdateExisting = false) { MetadataDatabase mdb = FromCache(); string[] Changes = null; if (mdb != null && !UpdateExisting) { // mdb.Builder = builder; return mdb; } Guid g = Guid.NewGuid(); try { g = SqlDatabase.DatabaseGuid; } catch (Exception) { } if (UpdateExisting) { if (mdb == null) { throw new ArgumentException("Update was specified but the metadata was not found in cache or file", "UpdateExisting"); } long v = GetVersion(); if (v <= mdb.Version) { RaiseUpdateEvent(100, "The database is up to date"); return mdb; } else { Changes = GetChanges(new DateTime(mdb.Version)); RaiseUpdateEvent(0, string.Format("{0} Changed tables identified", Changes.Length)); foreach (string change in Changes) { MetadataTable mt = null; if (mdb.Tables.TryRemove(change, out mt)) { RaiseUpdateEvent(0, string.Format("{0} removed from Metadata pending update", change)); } else { throw new InvalidOperationException("Could not remove the table " + change + " pending update"); } } mdb.Version = v; } } else { mdb = new MetadataDatabase() { ID = g, Name = SqlDatabase.Name, Server = SqlServer.Name + (!string.IsNullOrEmpty(SqlServer.InstanceName) && SqlServer.Name.IndexOf('\\') == -1 ? "" : ""), Builder = builder, Version = GetVersion() }; } double t = 0; double total = Changes != null ? Changes.Length : Tables != null ? Tables.Length : SqlDatabase.Tables.Count + SqlDatabase.Views.Count; foreach (Microsoft.SqlServer.Management.Smo.Table table in SqlDatabase.Tables) { if (Tables == null || Tables.Contains(table.Name)) { if (Changes == null || Changes.Contains(table.Schema + "." + table.Name)) { table.Refresh(); BuildMetadata(mdb, table); if (MetadataUpdateEvent != null) { t++; RaiseUpdateEvent(Convert.ToInt32((t / total) * 100), table.Schema + "." + table.Name + " built"); } if (t == total) { break; } } } } foreach (Microsoft.SqlServer.Management.Smo.View view in SqlDatabase.Views) { if (view.IsSystemObject) { t++; continue; } if (Tables == null || Tables.Contains(view.Name)) { if (Changes == null ||Changes.Contains(view.Schema + "." + view.Name)) { view.Refresh(); BuildMetadataView(mdb, view); if (MetadataUpdateEvent != null) { t++; RaiseUpdateEvent(Convert.ToInt32((t / total) * 100), view.Schema + "." + view.Name + " built"); } if (t == total) { break; } } } } ToCache(mdb); return mdb; }
private void CommonCreationOpening(String pathToMongod, String path) { _info = DatabaseInfo.Load(File.OpenRead(DatabaseInfoPath), SerializationMode.Xml); // create the file database _fileStorage = new FileDatabase(path); _fileStorage.Start(); // create the mongodb _metadata = new MetadataDatabase(pathToMongod, path); _metadata.Start(); RaisePropertyChanged(String.Empty); }
private void BuildVirtualKeys(List<VirtualForeignKey> keys, MetadataTable mt, MetadataDatabase mdb, bool PrimaryKeyIndexOnly) { foreach (VirtualForeignKey vfk in keys) { MetadataForeignKey mfk = new MetadataForeignKey() { ID = 0, Name = vfk.values[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0], ReferencedKey = "", ReferencedTable = vfk.values[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[1], ReferencedSchema = vfk.values[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[2], Parent = mt, IsVirtual = true }; MetadataTable mtref = null; if (!mdb.Tables.TryGetValue(mfk.ReferencedSchema + "." + mfk.ReferencedTable, out mtref)) { bool self = false; if (mfk.ReferencedSchema == mt.Schema && mfk.ReferencedTable == mt.Name) { self = true; } mtref = BuildMetadata(mdb, mfk.ReferencedTable, mfk.ReferencedSchema, PrimaryKeyIndexOnly, self); } for (int i = 1; i < vfk.values.Length; i++) { MetadataColumnReference mcf = new MetadataColumnReference() { ReferencedColumn = mtref[vfk.values[i].Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]], }; string from = vfk.values[i].Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[0]; if (from.StartsWith("\"")) { MetadataColumn mcVirtual = new MetadataColumn() { Name = from, IsForeignKey = true, ID = 0, SqlDataType = SqlDbType.NVarChar, Nullable = false, Length = 0, IsComputed = true, DataType = typeof(string), }; mcf.Column = mcVirtual; mcf.Name = from; } else { mcf.Column = mt[from]; mcf.Name = mcf.Column.Name; } mfk.ColumnReferences.Add(mcf); } mt.ForeignKeys.AddOrUpdate(mfk.Name, mfk, (k, v) => { return mfk; }); } }
public static bool MetadataDatabase_GetMatchingUnitDefs_Prefix(MetadataDatabase __instance) { return(true); }
private bool ToCache(MetadataDatabase mdb) { if (!UseCache) { return true; } return CacheMetadata(MetadataKey, mdb); }
public static void MetadataDatabase_GetMatchingUnitDefs_Postfix(MetadataDatabase __instance, DateTime?currentDate, ref List <UnitDef_MDD> __result) { }
static bool Prefix(UnitSpawnPointOverride __instance, LoadRequest request, MetadataDatabase mdd, string lanceName, string lanceDefId, string unitName, int unitIndex, DateTime?currentDate, TagSet companyTags) { if (__instance.IsUnitDefTagged && __instance.unitTagSet.Contains("unit_mech") && currentDate != null) { __instance.selectedUnitDefId = Core.xotlTables.RequestUnit(currentDate.Value, __instance.unitTagSet, __instance.unitExcludedTagSet, companyTags); __instance.selectedUnitType = UnitType.Mech; request.AddBlindLoadRequest(BattleTechResourceType.MechDef, __instance.selectedUnitDefId, new bool?(false)); return(false); } else { return(true); } }
private static IEnumerator StartGeneratePotentialContractsRoutine(SimGameState instance, bool clearExistingContracts, Action onContractGenComplete, StarSystem systemOverride, bool useCoroutine) { if (useCoroutine) { yield return(new WaitForSeconds(0.2f)); } bool usingBreadcrumbs = systemOverride != null; StarSystem system; List <Contract> contractList; if (systemOverride != null) { system = systemOverride; contractList = instance.CurSystem.SystemBreadcrumbs; } else { system = instance.CurSystem; contractList = instance.CurSystem.SystemContracts; } if (clearExistingContracts) { contractList.Clear(); } int maxContracts; if (systemOverride != null) { maxContracts = instance.CurSystem.CurMaxBreadcrumbs; } else { maxContracts = Mathf.CeilToInt(system.CurMaxContracts); } int debugCount = 0; while (contractList.Count < maxContracts && debugCount < 1000) { if (usingBreadcrumbs) { List <StarSystem> listsys = instance.StarSystems; listsys.Shuffle <StarSystem>(); system = listsys[0]; } int globalDifficulty = system.Def.Difficulty + Mathf.FloorToInt(instance.GlobalDifficulty); int minDiff; int maxDiff; int contractDifficultyVariance = instance.Constants.Story.ContractDifficultyVariance; minDiff = Mathf.Max(1, globalDifficulty - contractDifficultyVariance); maxDiff = Mathf.Max(1, globalDifficulty + contractDifficultyVariance); ContractDifficulty minDiffClamped = (ContractDifficulty)ReflectionHelper.InvokePrivateMethode(instance, "GetDifficultyEnumFromValue", new object[] { minDiff }); ContractDifficulty maxDiffClamped = (ContractDifficulty)ReflectionHelper.InvokePrivateMethode(instance, "GetDifficultyEnumFromValue", new object[] { maxDiff }); WeightedList <MapAndEncounters> contractMaps = new WeightedList <MapAndEncounters>(WeightedListType.SimpleRandom, null, null, 0); List <ContractType> contractTypes = new List <ContractType>(); Dictionary <ContractType, List <ContractOverride> > potentialOverrides = new Dictionary <ContractType, List <ContractOverride> >(); ContractType[] singlePlayerTypes = (ContractType[])ReflectionHelper.GetPrivateStaticField(typeof(SimGameState), "singlePlayerTypes"); using (MetadataDatabase metadataDatabase = new MetadataDatabase()) { foreach (Contract_MDD contract_MDD in metadataDatabase.GetContractsByDifficultyRangeAndScope((int)minDiffClamped, (int)maxDiffClamped, instance.ContractScope)) { ContractType contractType = contract_MDD.ContractTypeEntry.ContractType; if (singlePlayerTypes.Contains(contractType)) { if (!contractTypes.Contains(contractType)) { contractTypes.Add(contractType); } if (!potentialOverrides.ContainsKey(contractType)) { potentialOverrides.Add(contractType, new List <ContractOverride>()); } ContractOverride item = instance.DataManager.ContractOverrides.Get(contract_MDD.ContractID); potentialOverrides[contractType].Add(item); } } foreach (MapAndEncounters element in metadataDatabase.GetReleasedMapsAndEncountersByContractTypeAndTags(singlePlayerTypes, system.Def.MapRequiredTags, system.Def.MapExcludedTags, system.Def.SupportedBiomes)) { if (!contractMaps.Contains(element)) { contractMaps.Add(element, 0); } } } if (contractMaps.Count == 0) { Debug.LogError(string.Format("No valid map for System {0}", system.Name)); if (onContractGenComplete != null) { onContractGenComplete(); } yield break; } if (potentialOverrides.Count == 0) { Debug.LogError(string.Format("No valid contracts queried for difficulties between {0} and {1}, with a SCOPE of {2}", minDiffClamped, maxDiffClamped, instance.ContractScope)); if (onContractGenComplete != null) { onContractGenComplete(); } yield break; } contractMaps.Reset(false); WeightedList <Faction> validEmployers = new WeightedList <Faction>(WeightedListType.SimpleRandom, null, null, 0); Dictionary <Faction, WeightedList <Faction> > validTargets = new Dictionary <Faction, WeightedList <Faction> >(); Dictionary <Faction, FactionDef> factions = (Dictionary <Faction, FactionDef>)ReflectionHelper.GetPrivateField(instance, "factions"); foreach (Faction faction in system.Def.ContractEmployers) { foreach (Faction faction2 in factions[faction].Enemies) { if (system.Def.ContractTargets.Contains(faction2)) { if (!validTargets.ContainsKey(faction)) { validTargets.Add(faction, new WeightedList <Faction>(WeightedListType.PureRandom, null, null, 0)); } validTargets[faction].Add(faction2, 0); } } if (validTargets.ContainsKey(faction)) { validTargets[faction].Reset(false); validEmployers.Add(faction, 0); } } validEmployers.Reset(false); if (validEmployers.Count <= 0 || validTargets.Count <= 0) { Debug.LogError(string.Format("Cannot find any valid employers or targets for system {0}", system)); } if (validTargets.Count == 0 || validEmployers.Count == 0) { SimGameState.logger.LogError(string.Format("There are no valid employers or employers for the system of {0}. Num valid employers: {1}", system.Name, validEmployers.Count)); foreach (Faction faction3 in validTargets.Keys) { SimGameState.logger.LogError(string.Format("--- Targets for {0}: {1}", faction3, validTargets[faction3].Count)); } if (onContractGenComplete != null) { onContractGenComplete(); } yield break; } int i = debugCount; debugCount = i + 1; WeightedList <MapAndEncounters> activeMaps = new WeightedList <MapAndEncounters>(WeightedListType.SimpleRandom, contractMaps.ToList(), null, 0); List <MapAndEncounters> discardedMaps = new List <MapAndEncounters>(); List <string> mapDiscardPile = (List <string>)ReflectionHelper.GetPrivateField(instance, "mapDiscardPile"); for (int j = activeMaps.Count - 1; j >= 0; j--) { if (mapDiscardPile.Contains(activeMaps[j].Map.MapID)) { discardedMaps.Add(activeMaps[j]); activeMaps.RemoveAt(j); } } if (activeMaps.Count == 0) { mapDiscardPile.Clear(); foreach (MapAndEncounters element2 in discardedMaps) { activeMaps.Add(element2, 0); } } activeMaps.Reset(false); MapAndEncounters level = null; List <EncounterLayer_MDD> validEncounters = new List <EncounterLayer_MDD>(); Dictionary <ContractType, WeightedList <PotentialContract> > validContracts = new Dictionary <ContractType, WeightedList <PotentialContract> >(); WeightedList <PotentialContract> flatValidContracts = null; do { level = activeMaps.GetNext(false); if (level == null) { break; } validEncounters.Clear(); validContracts.Clear(); flatValidContracts = new WeightedList <PotentialContract>(WeightedListType.WeightedRandom, null, null, 0); foreach (EncounterLayer_MDD encounterLayer_MDD in level.Encounters) { ContractType contractType2 = encounterLayer_MDD.ContractTypeEntry.ContractType; if (contractTypes.Contains(contractType2)) { if (validContracts.ContainsKey(contractType2)) { validEncounters.Add(encounterLayer_MDD); } else { foreach (ContractOverride contractOverride2 in potentialOverrides[contractType2]) { bool flag = true; ContractDifficulty difficultyEnumFromValue = (ContractDifficulty)ReflectionHelper.InvokePrivateMethode(instance, "GetDifficultyEnumFromValue", new object[] { contractOverride2.difficulty }); Faction employer2 = Faction.INVALID_UNSET; Faction target2 = Faction.INVALID_UNSET; object[] args = new object[] { system, validEmployers, validTargets, contractOverride2.requirementList, employer2, target2 }; if (difficultyEnumFromValue >= minDiffClamped && difficultyEnumFromValue <= maxDiffClamped && (bool)ReflectionHelper.InvokePrivateMethode(instance, "GetValidFaction", args)) { employer2 = (Faction)args[4]; target2 = (Faction)args[5]; int difficulty = instance.NetworkRandom.Int(minDiff, maxDiff + 1); system.SetCurrentContractFactions(employer2, target2); int k = 0; while (k < contractOverride2.requirementList.Count) { RequirementDef requirementDef = new RequirementDef(contractOverride2.requirementList[k]); EventScope scope = requirementDef.Scope; TagSet curTags; StatCollection stats; switch (scope) { case EventScope.Company: curTags = instance.CompanyTags; stats = instance.CompanyStats; break; case EventScope.MechWarrior: case EventScope.Mech: goto IL_88B; case EventScope.Commander: goto IL_8E9; case EventScope.StarSystem: curTags = system.Tags; stats = system.Stats; break; default: goto IL_88B; } IL_803: for (int l = requirementDef.RequirementComparisons.Count - 1; l >= 0; l--) { ComparisonDef item2 = requirementDef.RequirementComparisons[l]; if (item2.obj.StartsWith("Target") || item2.obj.StartsWith("Employer")) { requirementDef.RequirementComparisons.Remove(item2); } } if (!SimGameState.MeetsRequirements(requirementDef, curTags, stats, null)) { flag = false; break; } k++; continue; IL_88B: if (scope != EventScope.Map) { throw new Exception("Contracts cannot use the scope of: " + requirementDef.Scope); } using (MetadataDatabase metadataDatabase2 = new MetadataDatabase()) { curTags = metadataDatabase2.GetTagSetForTagSetEntry(level.Map.TagSetID); stats = new StatCollection(); goto IL_803; } IL_8E9: curTags = instance.CommanderTags; stats = instance.CommanderStats; goto IL_803; } if (flag) { PotentialContract element3 = default(PotentialContract); element3.contractOverride = contractOverride2; element3.difficulty = difficulty; element3.employer = employer2; element3.target = target2; validEncounters.Add(encounterLayer_MDD); if (!validContracts.ContainsKey(contractType2)) { validContracts.Add(contractType2, new WeightedList <PotentialContract>(WeightedListType.WeightedRandom, null, null, 0)); } validContracts[contractType2].Add(element3, contractOverride2.weight); flatValidContracts.Add(element3, contractOverride2.weight); } } } } } } }while (validContracts.Count == 0 && level != null); system.SetCurrentContractFactions(Faction.INVALID_UNSET, Faction.INVALID_UNSET); if (validContracts.Count == 0) { if (mapDiscardPile.Count > 0) { mapDiscardPile.Clear(); } else { debugCount = 1000; SimGameState.logger.LogError(string.Format("[CONTRACT] Unable to find any valid contracts for available map pool. Alert designers.", new object[0])); } } else { GameContext gameContext = new GameContext(instance.Context); gameContext.SetObject(GameContextObjectTagEnum.TargetStarSystem, system); Dictionary <ContractType, List <EncounterLayer_MDD> > finalEncounters = new Dictionary <ContractType, List <EncounterLayer_MDD> >(); foreach (EncounterLayer_MDD encounterLayer_MDD2 in validEncounters) { ContractType contractType3 = encounterLayer_MDD2.ContractTypeEntry.ContractType; if (!finalEncounters.ContainsKey(contractType3)) { finalEncounters.Add(contractType3, new List <EncounterLayer_MDD>()); } finalEncounters[contractType3].Add(encounterLayer_MDD2); } List <PotentialContract> discardedContracts = new List <PotentialContract>(); List <string> contractDiscardPile = (List <string>)ReflectionHelper.GetPrivateField(instance, "contractDiscardPile"); for (int m = flatValidContracts.Count - 1; m >= 0; m--) { if (contractDiscardPile.Contains(flatValidContracts[m].contractOverride.ID)) { discardedContracts.Add(flatValidContracts[m]); flatValidContracts.RemoveAt(m); } } if ((float)discardedContracts.Count >= (float)flatValidContracts.Count * instance.Constants.Story.DiscardPileToActiveRatio || flatValidContracts.Count == 0) { contractDiscardPile.Clear(); foreach (PotentialContract element4 in discardedContracts) { flatValidContracts.Add(element4, 0); } } PotentialContract next = flatValidContracts.GetNext(true); ContractType finalContractType = next.contractOverride.contractType; finalEncounters[finalContractType].Shuffle <EncounterLayer_MDD>(); string encounterGuid = finalEncounters[finalContractType][0].EncounterLayerGUID; ContractOverride contractOverride3 = next.contractOverride; Faction employer3 = next.employer; Faction target3 = next.target; int targetDifficulty = next.difficulty; Contract con; if (usingBreadcrumbs) { con = (Contract)ReflectionHelper.InvokePrivateMethode(instance, "CreateTravelContract", new object[] { level.Map.MapName, level.Map.MapPath, encounterGuid, finalContractType, contractOverride3, gameContext, employer3, target3, employer3, false, targetDifficulty }); } else { con = new Contract(level.Map.MapName, level.Map.MapPath, encounterGuid, finalContractType, instance.BattleTechGame, contractOverride3, gameContext, true, targetDifficulty, 0, null); } mapDiscardPile.Add(level.Map.MapID); contractDiscardPile.Add(contractOverride3.ID); instance.PrepContract(con, employer3, target3, target3, level.Map.BiomeSkinEntry.BiomeSkin, con.Override.travelSeed, system); contractList.Add(con); if (useCoroutine) { yield return(new WaitForSeconds(0.2f)); } } } if (debugCount >= 1000) { SimGameState.logger.LogError("Unable to fill contract list. Please inform AJ Immediately"); } if (onContractGenComplete != null) { onContractGenComplete(); } yield break; }