/// <summary> /// Scrubs the config of mods that Steam got around to actually updating. /// </summary> private static void DoScrubConfig() { var settings = ModUpdateInfo.Settings; var existing = settings?.ModUpdates; var manager = Global.Instance.modManager; if (existing != null && manager != null) { // Anything that is up to date gets purged var remove = HashSetPool <ModUpdateData, ModUpdateHandler> .Allocate(); foreach (var info in existing) { ulong id = info.ID; if (CheckMod(manager, id)) { remove.Add(info); } if (info.Status == ModUpdateStatus.PendingUpdate) { // Purge the temporary zip ExtensionMethods.RemoveOldDownload(ModUpdateHandler.GetDownloadPath(id)); info.Status = ModUpdateStatus.UpdatedByThisMod; } } // Remove the obsolete entries foreach (var info in remove) { existing.Remove(info); } remove.Recycle(); POptions.WriteSettingsForAssembly(settings); } }
/// <summary> /// Applied after UpdateAchievementData runs. /// </summary> internal static void Postfix(Dictionary <string, GameObject> ___achievementEntries, string[] newlyAchieved) { var newly = HashSetPool <string, AchievementStateComponent> .Allocate(); // Achievements just obtained should always be shown if (newlyAchieved != null) { foreach (string achieved in newlyAchieved) { newly.Add(achieved); } } foreach (var pair in ___achievementEntries) { var obj = pair.Value; string id = pair.Key; MultiToggle toggle; var info = MoreAchievementsAPI.TranslateAchievement(id); if (obj != null && (toggle = obj.GetComponent <MultiToggle>()) != null && info.Hidden) { // Inactivate achievements that have never been achieved obj.SetActive(toggle.CurrentState != 2 || newly.Contains(id)); } } newly.Recycle(); }
public override void Update() { int x1, x2, y1, y2; var intersecting = HashSetPool <Uprootable, PipPlantOverlay> .Allocate(); base.Update(); // SimDebugView is updated on a background thread, so since plant checking // must be done on the FG thread, it is updated here Grid.GetVisibleExtents(out Vector2I min, out Vector2I max); x1 = min.x; x2 = max.x; y1 = min.y; y2 = max.y; // Refresh plant list with plants on the screen RemoveOffscreenTargets(layerTargets, min, max, null); partition.GetAllIntersecting(new Vector2(x1, y1), new Vector2(x2, y2), intersecting); foreach (var uprootable in intersecting) { AddTargetIfVisible(uprootable, min, max, layerTargets, targetLayer); } for (int y = y1; y <= y2; y++) { for (int x = x1; x <= x2; x++) { int cell = Grid.XYToCell(x, y); if (Grid.IsValidCell(cell)) { cells[cell] = PipPlantOverlayTests.CheckCell(cell); } } } UpdateHighlightTypeOverlay(min, max, layerTargets, plants, conditions, OverlayModes.BringToFrontLayerSetting.Constant, targetLayer); intersecting.Recycle(); }
/// <summary> /// Retrieves a list of KSelectable objects currently under the mouse cursor. /// </summary> /// <param name="cell">The cell that the cursor occupies.</param> /// <param name="coords">The raw mouse coordinates.</param> /// <param name="previousItems">The previously selected items.</param> /// <param name="hits">The location where the hits will be stored.</param> /// <returns>true to reset the cycle count, or false to leave it as is.</returns> private static bool GetAllSelectables(int cell, Vector3 coords, HashSet <Component> previousItems, List <KSelectable> hits) { var compareSet = HashSetPool <Component, InterfaceTool> .Allocate(); bool reset = false; if (Grid.IsVisible(cell)) { FindSelectables(cell, coords, hits, compareSet); } if (compareSet.Count < 1) { previousItems.Clear(); } else if (!previousItems.SetEquals(compareSet)) { reset = true; previousItems.Clear(); // Copy for next time previousItems.UnionWith(compareSet); } compareSet.Recycle(); return(reset); }
protected override void OnDragTool(int cell, int distFromOrigin) { var gameObject = Grid.Objects[cell, (int)ObjectLayer.Pickupables]; if (gameObject != null && TypeSelect != null) { // Linked list of debris in layer 3 var objectListNode = gameObject.GetComponent <Pickupable>().objectLayerListItem; var priority = ToolMenu.Instance.PriorityScreen.GetLastSelectedPriority(); if (cachedTypes == null) { // Build the list cachedTypes = HashSetPool <Tag, FilteredClearTool> .Allocate(); TypeSelect.AddTypesToSweep(cachedTypes); } while (objectListNode != null) { var content = objectListNode.gameObject; objectListNode = objectListNode.nextItem; // Ignore Duplicants if (content != null && content.GetComponent <MinionIdentity>() == null) { MarkForClear(content, priority); } } } }
/// <summary> /// Destroys debris in the cell. /// </summary> /// <param name="cell">The cell to destroy.</param> private void DestroyItems(int cell) { var destroy = HashSetPool <GameObject, FilteredDestroyTool> .Allocate(); var gameObject = Grid.Objects[cell, (int)ObjectLayer.Pickupables]; if (gameObject != null) { // Linked list of debris in layer 3 var objectListNode = gameObject.GetComponent <Pickupable>().objectLayerListItem; while (objectListNode != null) { var content = objectListNode.gameObject; objectListNode = objectListNode.nextItem; // Ignore Duplicants if (content != null && content.GetComponent <MinionIdentity>() == null) { var cc = content.GetComponent <Clearable>(); if (cc != null && cc.isClearable) { destroy.Add(content); } } } } DestroyAndRecycle(destroy); }
/// <summary> /// Looks up a particular item tag to see what foods it can be used to produce. /// </summary> /// <param name="tag">The item tag to look up.</param> /// <returns>The foods for which it can be used, or an empty array if it cannot be used /// for any foods.</returns> public FoodResult[] Lookup(Tag tag) { if (tag == null) { throw new ArgumentNullException("tag"); } // Check for existing list if (!cache.TryGetValue(tag, out IList <FoodResult> items)) { var seen = HashSetPool <Tag, FoodRecipeCache> .Allocate(); try { items = new List <FoodResult>(); SearchForRecipe(tag, items, seen, 1.0f); cache.Add(tag, items); } finally { seen.Recycle(); } } // Create a copy of the results int n = items.Count; var result = new FoodResult[n]; if (n > 0) { items.CopyTo(result, 0); } return(result); }
protected override void OnDragTool(int cell, int distFromOrigin) { var gameObject = Grid.Objects[cell, (int)ObjectLayer.Pickupables]; if (gameObject != null && TypeSelect != null) { // Linked list of debris in layer 3 var objectListNode = gameObject.GetComponent<Pickupable>().objectLayerListItem; var priority = ToolMenu.Instance.PriorityScreen.GetLastSelectedPriority(); if (cachedTypes == null) { // Build the list cachedTypes = HashSetPool<Tag, FilteredClearTool>.Allocate(); TypeSelect.AddTypesToSweep(cachedTypes); } var types = cachedTypes; while (objectListNode != null) { var content = objectListNode.gameObject; objectListNode = objectListNode.nextItem; // Ignore Duplicants if (content != null && content.GetComponent<MinionIdentity>() == null) { var cc = content.GetComponent<Clearable>(); if (cc != null && cc.isClearable && types.Contains(content.PrefabID())) { // Parameter is whether to force, not remove sweep errand! cc.MarkForClear(false); var pr = content.GetComponent<Prioritizable>(); if (pr != null) pr.SetMasterPriority(priority); } } } } }
/// <summary> /// Removes all invalid (dead, deleted) Duplicants from the access list if it is not /// set to Public. /// </summary> public void CleanupAccess() { if (allowIDs != null) { var preserve = HashSetPool <int, WorkshopProfile> .Allocate(); var intersection = ListPool <int, WorkshopProfile> .Allocate(); KPrefabID minionID; // Add all living Duplicants foreach (var id in Components.LiveMinionIdentities.Items) { if (id != null && (minionID = id.GetComponent <KPrefabID>()) != null) { preserve.Add(minionID.InstanceID); } } // Remove all dead ones foreach (int id in allowIDs) { if (preserve.Contains(id)) { intersection.Add(id); } } allowIDs.Clear(); // Copy back since removing from active enumeration is an error foreach (var id in intersection) { allowIDs.Add(id); } intersection.Recycle(); preserve.Recycle(); } }
/// <summary> /// Applied before RefreshRows runs. /// </summary> internal static bool Prefix(TableScreen __instance) { var identities = HashSetPool<IAssignableIdentity, TableScreen>.Allocate(); var living = Components.LiveMinionIdentities.Items; StoredMinionIdentity smi; // Living Duplicants for (int i = 0; i < living.Count; i++) { var dupe = living[i]; if (dupe != null) identities.Add(dupe); } // Duplicants in vanilla rockets and similar foreach (var minionStorage in Components.MinionStorages.Items) foreach (var info in minionStorage.GetStoredMinionInfo()) { var dupe = info.serializedMinion; if (dupe != null && (smi = dupe.Get<StoredMinionIdentity>()) != null) __instance.AddRow(smi); } ClearAndAddRows(__instance, identities); // Add the missing rows foreach (var missingMinion in identities) __instance.AddRow(missingMinion); identities.Recycle(); if (DlcManager.FeatureClusterSpaceEnabled()) AddDividers(__instance); SortRows(__instance); __instance.rows_dirty = false; return false; }
/// <summary> /// Refreshes one set of required conditions. /// </summary> /// <param name="conditionType">The condition type to refresh.</param> /// <param name="nh">The number of header rows allocated.</param> /// <param name="nr">The number of content rows allocated.</param> private void RefreshProcessConditions(ProcessConditionType conditionType, ref int nh, ref int nr) { var conditions = lastSelection.conditions.GetConditionSet(conditionType); int n = conditions.Count; if (n > 0) { int nHeaders = nh, nRows = nr; var pr = processRows; var ph = processHeaders; string conditionName = StringFormatter.ToUpper(conditionType.ToString()); var seen = HashSetPool <ProcessCondition, SimpleInfoScreen> .Allocate(); ProcessConditionRow row; // Grab a cached header if possible if (nHeaders >= ph.Count) { ph.Add(row = new ProcessConditionRow(Util.KInstantiateUI(sis. processConditionHeader.gameObject, conditionParent, true), true)); } else { row = ph[nHeaders]; row.SetActive(true); } row.SetTitle(Strings.Get("STRINGS.UI.DETAILTABS.PROCESS_CONDITIONS." + conditionName), Strings.Get("STRINGS.UI.DETAILTABS.PROCESS_CONDITIONS." + conditionName + "_TOOLTIP")); processVisible.Add(row); nh = nHeaders + 1; for (int i = 0; i < n; i++) { var condition = conditions[i]; if (condition.ShowInUI() && (condition is RequireAttachedComponent || seen. Add(condition))) { if (nRows >= pr.Count) { row = new ProcessConditionRow(Util.KInstantiateUI(sis. processConditionRow, conditionParent, true), false); pr.Add(row); } else { row = pr[nRows]; row.SetActive(true); } processVisible.Add(row); row.SetCondition(condition); nRows++; } } nr = nRows; seen.Recycle(); } }
/// <summary> /// Destroys plants in the cell. /// </summary> /// <param name="cell">The cell to destroy.</param> private void DestroyPlants(int cell) { var destroy = HashSetPool <GameObject, FilteredDestroyTool> .Allocate(); foreach (var crop in Components.Uprootables.Items) { if (Grid.PosToCell(crop) == cell) { destroy.Add(crop.gameObject); } } DestroyAndRecycle(destroy); }
/// <summary> /// Populates the pinned critters in the resource panel, creating new rows if needed. /// </summary> internal void PopulatePinnedRows() { var ci = ClusterManager.Instance.activeWorld.GetComponent <CritterInventory>(); if (ci != null) { var seen = HashSetPool <Tag, PinnedCritterManager> .Allocate(); foreach (var pair in pinnedObjects) { var type = pair.Key; var have = pair.Value; foreach (var species in ci.GetPinnedSpecies(type)) { // Check for existing pinned row if (!have.TryGetValue(species, out var entry)) { have.Add(species, entry = Create(species, type)); } var row = entry.gameObject; if (!row.activeSelf) { row.SetActive(true); } seen.Add(species); } // Hide entries that have been removed from pinned list foreach (var speciesPair in have) { var row = speciesPair.Value.gameObject; if (!seen.Contains(speciesPair.Key)) { if (row.activeSelf) { row.SetActive(false); } } else { // These will be traversed in sorted order row.transform.SetAsLastSibling(); } } seen.Clear(); } seen.Recycle(); // Move the buttons to the end pinnedResources.clearNewButton.transform.SetAsLastSibling(); pinnedResources.seeAllButton.transform.SetAsLastSibling(); } }
/// <summary> /// Displays the biomes present on the given planetoid. /// </summary> /// <param name="biomes">The biomes found on this planetoid.</param> /// <param name="biomeRows">The cached list of all biomes seen so far.</param> internal void AddBiomes(IList <string> biomes, IDictionary <Tag, GameObject> biomeRows) { var parent = sis.worldBiomesPanel.Content.gameObject; int n = biomes.Count; var setInactive = HashSetPool <Tag, SimpleInfoScreen> .Allocate(); foreach (var pair in biomeRows) { if (pair.Value.activeSelf) { setInactive.Add(pair.Key); } } for (int i = 0; i < n; i++) { string id = biomes[i]; var idTag = new Tag(id); if (biomeRows.TryGetValue(idTag, out GameObject row)) { setInactive.Remove(idTag); } else { row = Util.KInstantiateUI(sis.bigIconLabelRow, parent, true); if (row.TryGetComponent(out HierarchyReferences hr)) { string upperID = StringFormatter.ToUpper(id); hr.GetReference <Image>("Icon").sprite = GameUtil.GetBiomeSprite(id); // These are forgivable as they only run once hr.GetReference <LocText>("NameLabel").SetText(STRINGS.UI. FormatAsLink(Strings.Get("STRINGS.SUBWORLDS." + upperID + ".NAME"), "BIOME" + upperID)); hr.GetReference <LocText>("DescriptionLabel").SetText(Strings.Get( "STRINGS.SUBWORLDS." + upperID + ".DESC")); } biomeRows[id] = row; } row.SetActive(true); } // Only turn off that which needs to be turned off foreach (var id in setInactive) { if (biomeRows.TryGetValue(id, out GameObject row)) { row.SetActive(false); } } setInactive.Recycle(); }
/// <summary> /// Destroys Duplicants and Critters in the cell. /// </summary> /// <param name="cell">The cell to destroy.</param> private void DestroyCreatures(int cell) { var destroy = HashSetPool <GameObject, FilteredDestroyTool> .Allocate(); // Critters, Duplicants, etc foreach (var brain in Components.Brains.Items) { if (Grid.PosToCell(brain) == cell) { destroy.Add(brain.gameObject); } } DestroyAndRecycle(destroy); }
/// <summary> /// Removes and pools any existing rows. Leaves the default and header row if present, /// otherwise creates and adds one when requested. /// </summary> /// <param name="instance">The table screen to clear.</param> /// <param name="toAdd">The Duplicants to be added or updated.</param> private static void ClearAndAddRows(TableScreen instance, ISet<IAssignableIdentity> toAdd) { var columns = instance.columns; var hr = instance.header_row; List<TableRow> rows = instance.rows, sortableRows = instance.all_sortable_rows; int n = rows.Count; TableRow defaultRow = null, headerRow = null; var newRows = TableRowList.Allocate(); var deadRows = HashSetPool<TableRow, TableScreen>.Allocate(); IAssignableIdentity minion; for (int i = 0; i < n; i++) { var row = rows[i]; var go = row.gameObject; // Do not destroy the default or header; pull out any rows for existing minion // identities if (row.rowType == TableRow.RowType.Default) { ThawLayout(go); defaultRow = row; } else if (go == hr && hr != null) { ThawLayout(go); headerRow = row; } else if (row.rowType != TableRow.RowType.WorldDivider && (minion = row. minion) != null && toAdd.Remove(minion)) { ThawLayout(go); ConfigureContent(row, minion, columns, instance); newRows.Add(row); } else deadRows.Add(row); } sortableRows.Clear(); rows.Clear(); // Restore cached default and header rows; header first if (headerRow != null) { ConfigureContent(headerRow, null, columns, instance); rows.Add(headerRow); } else instance.AddRow(null); if (defaultRow != null) { ConfigureContent(defaultRow, null, columns, instance); rows.Add(defaultRow); } else if (instance.has_default_duplicant_row) instance.AddDefaultRow(); // Add reused rows, delete removed rows sortableRows.AddRange(newRows); rows.AddRange(newRows); newRows.Recycle(); TakeOutTrash(instance, deadRows); deadRows.Recycle(); }
/// <summary> /// Destroys buildings in the cell which match the filter layer as used by the /// DeconstructTool. /// </summary> /// <param name="cell">The cell to destroy.</param> /// <param name="filter">The layer to match.</param> private void DestroyBuildings(int cell, string filter) { var destroy = HashSetPool <GameObject, FilteredDestroyTool> .Allocate(); var inst = DeconstructTool.Instance; for (int i = 0; i < (int)ObjectLayer.NumLayers; i++) { var obj = Grid.Objects[cell, i]; if (obj != null && inst.GetFilterLayerFromGameObject(obj) == filter) { // Buldings, either finished or under construction destroy.Add(obj); } } DestroyAndRecycle(destroy); }
private static string MakeModList(List <Event> events) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(); HashSetPool <string, Manager> .PooledHashSet pooledHashSet = HashSetPool <string, Manager> .Allocate(); foreach (Event @event in events) { Event current = @event; if (pooledHashSet.Add(current.mod.title)) { stringBuilder.AppendLine(current.mod.title); } } pooledHashSet.Recycle(); return(stringBuilder.ToString()); }
/// <summary> /// Destroys everything in the cell. /// </summary> /// <param name="cell">The cell to destroy.</param> private void DestroyAll(int cell) { var destroy = HashSetPool <GameObject, FilteredDestroyTool> .Allocate(); DestroyElement(cell); DestroyItems(cell); DestroyPlants(cell); DestroyCreatures(cell); // All buildings, no exceptions for (int i = 0; i < (int)ObjectLayer.NumLayers; i++) { var obj = Grid.Objects[cell, i]; if (obj != null) { destroy.Add(obj); } } DestroyAndRecycle(destroy); }
/// <summary> /// Disturbs all Duplicants in range. /// </summary> /// <param name="source">The source of the disturbance.</param> /// <param name="radius">The disturbance radius.</param> internal static void DisturbInRange(GameObject source, float radius) { var effects = Db.Get().effects; Vector2 loc = source.transform.GetPosition(); // Radius is 3 in the base game float radSq = radius * radius; var cells = HashSetPool <int, TraitTemplate> .Allocate(); // Determine who gets disturbed (ouch private method) // Disable cast warning, cast is to ensure correct method selection #pragma warning disable IDE0004 ACOUSTIC_TRAVERSE.CallMethod("DetermineCellsInRadius", Grid.PosToCell(source), 0, Mathf.CeilToInt(radius), (HashSet <int>)cells); #pragma warning restore IDE0004 foreach (var dupe in Components.LiveMinionIdentities.Items) { var newObj = dupe.gameObject; if (newObj != null && newObj != source) { // Is this dupe in range? Vector2 newLoc = dupe.transform.GetPosition(); if (Vector2.SqrMagnitude(loc - newLoc) <= radSq) { int cell = Grid.PosToCell(newLoc); var sleepMonitor = dupe.GetSMI <StaminaMonitor.Instance>(); if (cells.Contains(cell) && (sleepMonitor == null || !sleepMonitor. IsSleeping())) { #if DEBUG PUtil.LogDebug("Disturbing " + newObj.name); #endif // Not happy at hearing snoring newObj.GetSMI <ThoughtGraph.Instance>()?.AddThought(Db.Get(). Thoughts.Unhappy); // Inflict disturbed effect newObj.GetComponent <Effects>()?.Add(effects.Get(TraitTuning. DISTURBED_EFFECT), true); } } } } cells.Recycle(); }
public void GetTopLevelItems(List <FileSystemItem> file_system_items) { HashSetPool <string, ZipFile> .PooledHashSet pooledHashSet = HashSetPool <string, ZipFile> .Allocate(); foreach (ZipEntry item in zipfile) { string[] array = FileSystem.Normalize(item.FileName).Split('/'); string text = array[0]; if (pooledHashSet.Add(text)) { file_system_items.Add(new FileSystemItem { name = text, type = ((1 >= array.Length) ? FileSystemItem.ItemType.File : FileSystemItem.ItemType.Directory) }); } } pooledHashSet.Recycle(); }
/// <summary> /// Bans food items from a duplicant. /// </summary> /// <param name="banned">The foods to ban.</param> /// <param name="instance">The consumer who cannot eat these items.</param> private static void BanFoods(IEnumerable <string> banned, ConsumableConsumer instance) { var set = HashSetPool <Tag, ConsumableConsumer> .Allocate(); foreach (var tag in instance.forbiddenTags) { set.Add(tag); } foreach (var bannedTag in banned) { set.Add(bannedTag); } // Create new tag list var newTags = new Tag[set.Count]; set.CopyTo(newTags, 0); set.Recycle(); instance.forbiddenTags = newTags; }
public void Sim33ms(float dt) { EntombedItemVisualizer component = Game.Instance.GetComponent <EntombedItemVisualizer>(); HashSetPool <Pickupable, EntombedItemManager> .PooledHashSet pooledHashSet = HashSetPool <Pickupable, EntombedItemManager> .Allocate(); foreach (Pickupable pickupable in pickupables) { if (CanEntomb(pickupable)) { pooledHashSet.Add(pickupable); } } pickupables.Clear(); foreach (Pickupable item in pooledHashSet) { int num = Grid.PosToCell(item); PrimaryElement component2 = item.GetComponent <PrimaryElement>(); SimHashes elementID = component2.ElementID; float mass = component2.Mass; float temperature = component2.Temperature; byte diseaseIdx = component2.DiseaseIdx; int diseaseCount = component2.DiseaseCount; Element element = Grid.Element[num]; if (elementID == element.id && mass > 0.0100000007f && Grid.Mass[num] + mass < element.maxMass) { SimMessages.AddRemoveSubstance(num, ElementLoader.FindElementByHash(elementID).idx, CellEventLogger.Instance.ElementConsumerSimUpdate, mass, temperature, diseaseIdx, diseaseCount, true, -1); } else { component.AddItem(num); cells.Add(num); elementIds.Add((int)elementID); masses.Add(mass); temperatures.Add(temperature); diseaseIndices.Add(diseaseIdx); diseaseCounts.Add(diseaseCount); } Util.KDestroyGameObject(item.gameObject); } pooledHashSet.Recycle(); }
/// <summary> /// Creates or updates the visualizers as necessary. /// </summary> private void CreateVisualizers() { var visCells = HashSetPool <VisCellData, ColoredRangeVisualizer> .Allocate(); var newCells = ListPool <VisCellData, ColoredRangeVisualizer> .Allocate(); try { if (gameObject != null) { VisualizeCells(visCells); } // Destroy cells that are not used in the new one foreach (var cell in cells) { if (visCells.Remove(cell)) { newCells.Add(cell); } else { cell.Destroy(); } } // Newcomers get their controller created and added to the list foreach (var newCell in visCells) { newCell.CreateController(Layer); newCells.Add(newCell); } // Copy back to global cells.Clear(); foreach (var cell in newCells) { cells.Add(cell); } } finally { visCells.Recycle(); newCells.Recycle(); } }
/// <summary> /// Sets the type selections from the specified tag list. All types not in the list /// are deselected. /// /// Tags in unknown categories will not be selected. /// </summary> /// <param name="selected">The tag types to select.</param> public void SetSelections(IEnumerable <Tag> selected) { if (selected != null) { var tagSet = HashSetPool <Tag, TypeSelectControl> .Allocate(); // Make a quick list to look up foreach (var tag in selected) { tagSet.Add(tag); } // Cycle through all discovered categories foreach (var pair in children) { foreach (var tagPair in pair.Value.children) { tagPair.Value.SetSelected(tagSet.Contains(tagPair.Key)); } } tagSet.Recycle(); } }
private bool LoadTranslations() { string path = FileSystem.Normalize(label.install_path); if (!System.IO.Directory.Exists(path)) { return(false); } DirectoryInfo directoryInfo = new DirectoryInfo(path); HashSetPool <Localization.Locale, Mod> .PooledHashSet pooledHashSet = HashSetPool <Localization.Locale, Mod> .Allocate(); FileInfo[] files = directoryInfo.GetFiles(); foreach (FileInfo fileInfo in files) { if (!(fileInfo.Extension.ToLower() != ".po")) { string[] lines = File.ReadAllLines(fileInfo.FullName, Encoding.UTF8); pooledHashSet.Add(Localization.GetLocale(lines)); Dictionary <string, string> translated_strings = Localization.ExtractTranslatedStrings(lines, false); Localization.OverloadStrings(translated_strings); } } if (pooledHashSet.Count == 0) { return(false); } Localization.Locale new_locale = pooledHashSet.First(); if (!pooledHashSet.All((Localization.Locale locale) => locale == new_locale)) { return(false); } Localization.SetLocale(new_locale); Localization.SwapToLocalizedFont(new_locale.FontName); KPlayerPrefs.SetString(Localization.SELECTED_LANGUAGE_TYPE_KEY, 2.ToString()); KPlayerPrefs.SetString(Localization.SELECTED_LANGUAGE_CODE_KEY, new_locale.Code); return(true); }
/// <summary> /// Applied before Success runs. /// </summary> internal static bool Prefix(ProduceXEngeryWithoutUsingYList __instance, ref bool __result) { float total = 0f; var disallow = HashSetPool <Tag, ProduceXEngeryWithoutUsingYList> .Allocate(); // Set is faster than a List here, as the test is expected to fail most times if // this achievement is still achievable foreach (var tag in __instance.disallowedBuildings) { disallow.Add(tag); } foreach (var pair in Game.Instance.savedInfo.powerCreatedbyGeneratorType) { if (!disallow.Contains(pair.Key)) { total += pair.Value; } } disallow.Recycle(); __result = total * 0.001f > __instance.amountToProduce; return(false); }
/// <summary> /// Destroys the element (liquid, solid, or gas) in the cell. /// </summary> /// <param name="cell">The cell to destroy.</param> private void DestroyElement(int cell) { pendingCells.Add(cell); // Register a sim callback to unhighlight the cells when destroyed int index = Game.Instance.callbackManager.Add(new Game.CallbackInfo(delegate() { pendingCells.Remove(cell); })).index; SimMessages.ReplaceElement(cell, SimHashes.Vacuum, CellEventLogger.Instance. SandBoxTool, 0.0f, 0.0f, Klei.SimUtil.DiseaseInfo.Invalid.idx, 0, index); // Destroy any solid tiles / doors on the area as well to avoid bad states var destroy = HashSetPool <GameObject, FilteredDestroyTool> .Allocate(); for (int i = 0; i < (int)ObjectLayer.NumLayers; i++) { var obj = Grid.Objects[cell, i]; if (obj != null && obj.GetComponentSafe <SimCellOccupier>() != null) { destroy.Add(obj); } } DestroyAndRecycle(destroy); }
protected override void VisualizeCells(ICollection <VisCellData> newCells) { // Rotation is only used to rotate the offset, radius is the same in all directions int startCell = RotateOffsetCell(Grid.PosToCell(gameObject), offset); if (Grid.IsValidCell(startCell) && Grid.Element[startCell]?.IsSolid == false) { var queue = new PriorityDictionary <int, int>(radius * radius); // Initial cell is seen var seen = HashSetPool <int, ElementConsumerVisualizer> .Allocate(); try { queue.Enqueue(0, startCell); seen.Add(startCell); // Dijkstra's algorithm do { queue.Dequeue(out int cost, out int newCell); if (cost < radius - 1) { // Cardinal directions EnqueueIfPassable(seen, Grid.CellLeft(newCell), cost + 1, queue); EnqueueIfPassable(seen, Grid.CellRight(newCell), cost + 1, queue); EnqueueIfPassable(seen, Grid.CellAbove(newCell), cost + 1, queue); EnqueueIfPassable(seen, Grid.CellBelow(newCell), cost + 1, queue); } } while (queue.Count > 0); // Add all cells as normal color foreach (var cell in seen) { newCells.Add(new VisCellData(cell, color)); } } finally { seen.Recycle(); } } }
/// <summary> /// Creates a ZIP file of the old mod contents merged with the saved configs at /// tempFilePath. /// </summary> /// <param name="copied">The number of configuration files backed up.</param> /// <returns>true if successful, or false if an I/O error occurred.</returns> public bool CreateMergedPackage(out int copied) { bool ok = false; var toCopy = HashSetPool <string, ConfigBackupUtility> .Allocate(); var toAdd = DictionaryPool <string, string, ConfigBackupUtility> .Allocate(); // Open old ZIP file copied = 0; try { using (var src = new ZipFile(oldFilePath)) { foreach (var entry in src) { // Klei normalizes the file names to forward slashes toCopy.Add(FileSystem.Normalize(entry.FileName)); } FindFilesToCopy(toCopy, toAdd); using (var dst = new ZipFile(tempFilePath)) { CopyFiles(src, dst, toCopy, toAdd); dst.Save(); copied = toAdd.Count; PUtil.LogDebug("Config backup for {0} copied {1:D} files".F(modFolder, copied)); } } ok = true; } catch (IOException e) { PUtil.LogWarning("Unable to backup mod configs:"); PUtil.LogExcWarn(e); } catch (UnauthorizedAccessException e) { PUtil.LogWarning("Unable to backup mod configs:"); PUtil.LogExcWarn(e); } toAdd.Recycle(); toCopy.Recycle(); return(ok); }