Files
Performance-Fish/Source/PerformanceFish/Utility/MiscExtensions.cs
T

140 lines
4.6 KiB
C#

// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Security;
using Verse.Sound;
namespace PerformanceFish.Utility;
public static class MiscExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[SecuritySafeCritical]
public static bool AsBool(this int value) // ref on parameter instead of var would enforce stack allocation
{
var temp = (byte)value; // bool is 32 bits in .NET, but the jit compiler only eliminates when casting to byte first
return Unsafe.As<byte, bool>(ref temp); // result is a direct return with no instructions whatsoever
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[SecuritySafeCritical]
public static int AsInt(this bool value)
{
var temp = value;
return Unsafe.As<bool, byte>(ref temp);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsItem(this Thing thing) => thing.def.category == ThingCategory.Item;
public static ISlotGroupParent? GetSlotGroupParent(this in IntVec3 position, Map map)
=> map.haulDestinationManager.SlotGroupAt(position)?.parent;
public static ISlotGroupParent? StoringSlotGroupParent(this Thing thing)
=> thing.Position.GetSlotGroupParent(thing.GetMap());
public static int SlotGroupCellCount(this Thing thing) => ((ISlotGroupParent)thing).AllSlotCellsList().Count;
public static List<Thing> GetThingListUnchecked(this in IntVec3 cell, Map map)
=> map.thingGrid.ThingsListAtFast(cell.CellToIndex(map));
public static List<Thing> GetThingListUnchecked(this IntVec2 cell, Map map)
=> map.thingGrid.ThingsListAtFast(cell.CellToIndex(map));
public static Region? RegionAtUnchecked(this IntVec3 c, Map map,
RegionType allowedRegionTypes = RegionType.Set_Passable)
{
map.regionAndRoomUpdater.TryRebuildDirtyRegionsAndRooms();
return map.regionGrid.regionGrid[c.CellToIndex(map)] is { valid: true } region
&& (region.type & allowedRegionTypes) != RegionType.None
? region
: null;
}
public static Region? GetValidRegionAtUnchecked(this RegionGrid grid, in IntVec3 c)
{
var map = grid.map;
map.regionAndRoomUpdater.TryRebuildDirtyRegionsAndRooms();
return grid.regionGrid[c.CellToIndex(map)] is { valid: true } region ? region : null;
}
public static bool ContainsThingStackableWith(this List<Thing> thingsOfSingleDef, Thing t)
{
var def = t.def;
for (var i = thingsOfSingleDef.Count; i-- > 0;)
{
if (thingsOfSingleDef[i].stackCount < def.stackLimit && thingsOfSingleDef[i].CanStackWith(t))
return true;
}
return false;
}
public static Map? TryGetMapHeld(this Thing thing)
{
var maps = Current.Game.Maps;
var mapIndex = (uint)thing.mapIndexOrState;
return mapIndex < (uint)maps.Count
? maps[(int)mapIndex]
: thing.ParentHolder is { } parentHolder
? ThingOwnerUtility.GetRootMap(parentHolder)
: null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Map? TryGetMap(this Thing thing)
{
var maps = Current.Game.Maps;
var mapIndex = (uint)thing.mapIndexOrState;
return mapIndex < (uint)maps.Count ? maps[(int)mapIndex] : null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Map GetMap(this Thing thing) => Current.Game.Maps[thing.mapIndexOrState];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Map GetMap(this Region region) => Current.Game.Maps[region.mapIndex];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsSpawned(this Thing thing) => (uint)thing.mapIndexOrState < (uint)Current.Game.Maps.Count;
public static void InvokeWhenCellIndicesReady(this Map map, Action<Map> action)
{
if (map.cellIndices != null)
action(map);
else
map.Events().ComponentsConstructed += action;
}
public static void AddLetterSilently(this LetterStack letterStack, Letter letter, Color color, bool playSound = false,
string? debugInfo = null)
{
var letterDef = letter.def.MemberwiseClone();
letterDef.index = 0;
letterDef.shortHash = 0;
letterDef.color = color;
letterDef.flashColor = color;
letter.def = letterDef;
letterStack.AddLetterSilently(letter, playSound, debugInfo);
}
public static void AddLetterSilently(this LetterStack letterStack, Letter letter, bool playSound = false,
string? debugInfo = null)
{
if (playSound)
letter.def.arriveSound.PlayOneShotOnCamera();
letter.arrivalTime = Time.time;
letter.arrivalTick = Find.TickManager.TicksGame;
letter.debugInfo = debugInfo;
letterStack.letters.Add(letter);
letter.Received();
}
}