EnumExtender
Legacy article
This article contains information that is only relevant for legacy versions of the game (1.5 or lower)
|
"EnumExtender" | |
---|---|
No image | |
Details | |
Tool type |
Dependency library |
License |
CC0 |
Authors |
Bee |
Release links |
source, latest build |
EnumExtender or EE is a tool mod which allows adding entries to Enum
s. It is widely used as a dependency library.
Features[edit source]
EE allows the user to add entries to enums at runtime in two ways:
- Automatic (does not require referencing EE assembly in your project)
- Manual (requires referencing EE assembly in your project)
Usage[edit source]
Automatic extension[edit source]
On initialization, EE scans all loaded classes, looking for public static class
with names starting with EnumExt_
.
Extensions are created from public static
fields with the type of target enum. Created entries have the same name as the field, and the field gets the value of the new entry. Example use:
public static class EnumExt_MyMod
{ // You can have multiple EnumExt_ classes in your assembly if you need multiple items with the same name for the different enum
//this adds entry "Vultures" to enum "CreatureCommnuities.CommunityID"
public static CreatureCommnuities.CommunityID Vultures;
//this adds "YellowishWhite" to "SlugcatStats.Name"
public static SlugcatStats.Name YellowishWhite;
public static SlugcatStats.Name WhitishYellow;
}
To access these new enum items, instead of [enum].[item]
, use that static field.
To compare it, use if
statements (unfortunately, you can not use static fields for branches in a switch
statement). Example use:
public static SlugStatsPatch(On.SlugcatStats.orig_ctor orig, SlugcatStats stats, int slugcatNumber, bool malnourished)
{
orig.Invoke(stats, slugcatNumber, malnourished);
if (stats.name == EnumExt_MyMod.YellowishWhite)
{
stats.runspeedFac = 1.2f;
stats.poleClimbSpeedFac = 1.25f;
stats.corridorClimbSpeedFac = 1.2f;
}
}
However, if EnumExtender is not present in runtime (for instance, the user forgot to install EnumExtender), these fields won't be initialized and will always stay at 0.
This can be used to easily detect whether EnumExtender is installed or not.
public static bool HasEnumExt => (int)EnumExt_MyMod.YellowishWhite > 0;
// This property returns true after EE initializes (after OnEnable)
Switch statement workaround[edit source]
If you have multiple new items and really want to use switches, you can do something like the following:
public static class EnumSwitch
{
//the intermediary enum
public enum SlugcatStatsName
{
DEFAULT = -1, // unrelated to this mod
YellowishWhite,
WhitishYellow
};
public static SlugcatStatsName GetSlugStatsNameInterm(SlugcatStats.Name name)
{
if (!HasEnumExt) { return SlugcatStatsName.DEFAULT; } // EnumExt is not installed
if (name == EnumExt_MyMod.YellowishWhite) { return SlugcatStatsName.YellowishWhite; }
if (name == EnumExt_MyMod.WhitishYellow) { return SlugcatStatsName.WhitishYellow; }
return SlugcatStatsName.DEFAULT;
}
}
And when you need to use switch later,
switch (EnumSwitch.GetSlugStatsNameInterm(name))
{
default:
case SlugcatStatsName.DEFAULT: break;
case SlugcatStatsName.YellowishWhite:
break;
case SlugcatStatsName.WhitishYellow:
break;
}
Manual extension[edit source]
This method is useful when you don't know what name your new entries will have to have. It is more cumbersome to use and less safe, but
- Ensure that EE has been initialized. You can either wait until the
EnumExt_
get appropriate values, or callPastebinMachine.EnumExtender.EnsureInit()
- Call
PastebinMachine.EnumExtender.AddDeclaration(Type, string)
one or more times. First parameter isType
of the enum, second is the name of new entry. Ensuring there are no name collisions is on you! - Call
PastebinMachine.EnumExtender.ExtendEnumsAgain
once to register all your new enums.
NOTE: Last step may have a noticeable overhead, and each call to ExtendEnumsAgain
causes a small but permanent memory leak. Do not overuse.
ExtendEnumsAgain
does not return the added values, you have to obtain them manually through Enum.GetNames()
or Enum.GetValues()
. Storing the resulting values correctly is the user's responsibility.
Summary[edit source]
Both modes allow you to use methods like Enum.Parse
with extended values freely. RW codebase uses enums pretty much everywhere, so EnumExtender is a often a vital dependency.