diff --git a/ChunkLabel.cs b/ChunkLabel.cs
deleted file mode 100644
index 10e5597..0000000
--- a/ChunkLabel.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using UnityEngine;
-
-namespace HeadsShouldersKneesAndToes
-{
- class ChunkLabel : CosmeticSprite
- {
- public ChunkLabel(BodyChunk chunk, int index)
- {
- this.chunk = chunk;
-
- // set label text properties
- label = new FLabel("DisplayFont", index.ToString())
- {
- color = Color.white,
- isVisible = TaggerMod.ChunkTagsVisible,
- anchorX = 0.5f,
- scale = 0.7f
- };
- }
-
- public override void Update(bool eu)
- {
- if (chunk.owner?.room?.abstractRoom?.name != TaggerMod.CurrentRoomName || chunk.owner.slatedForDeletetion)
- {
- Destroy();
- }
-
- base.Update(eu);
- }
-
- public override void Destroy()
- {
- label.isVisible = false;
- label.text = "";
- base.Destroy();
- }
-
- public override void InitiateSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam)
- {
- // set label background properties (sans color)
- sLeaser.sprites = new FSprite[1];
- sLeaser.sprites[0] = new FSprite("pixel", true);
- AddToContainer(sLeaser, rCam, null);
- }
-
- public override void DrawSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, float timeStacker, Vector2 camPos)
- {
- Vector2 pos = Vector2.Lerp(chunk.lastPos, chunk.pos, timeStacker) - camPos;
- sLeaser.sprites[0].SetPosition(pos);
- sLeaser.sprites[0].scaleX = sLeaser.sprites[0].scaleY = chunk.rad * 2;
- label.SetPosition(pos);
- sLeaser.sprites[0].isVisible = TaggerMod.ChunkTagsVisible;
- label.isVisible = TaggerMod.ChunkTagsVisible;
-
- base.DrawSprites(sLeaser, rCam, timeStacker, camPos);
- }
-
- public override void AddToContainer(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, FContainer newContatiner)
- {
- base.AddToContainer(sLeaser, rCam, null);
- label.RemoveFromContainer();
- sLeaser.sprites[0].RemoveFromContainer();
- rCam.ReturnFContainer("Foreground").AddChild(sLeaser.sprites[0]);
- rCam.ReturnFContainer("Foreground").AddChild(label);
- }
-
- public override void ApplyPalette(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, RoomPalette palette)
- {
- // set colour of label background
- Color color = palette.skyColor * 0.9f;
- color.a = 0.7f;
- sLeaser.sprites[0].color = color;
- }
-
- readonly BodyChunk chunk;
- readonly FLabel label;
- }
-}
diff --git a/HeadsShouldersKneesAndToes.csproj b/HeadsShouldersKneesAndToes.csproj
deleted file mode 100644
index 4000650..0000000
--- a/HeadsShouldersKneesAndToes.csproj
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {F66F844E-74DF-46B6-BDFF-F344B6A53410}
- Library
- Properties
- HeadsShouldersKneesAndToes
- HeadsShouldersKneesAndToes
- v3.5
- 512
- true
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\safe\Assembly-CSharp.dll
-
-
- ..\..\..\Games\Steam\steamapps\common\Rain World\BepInEx\core\BepInEx.dll
-
-
- ..\safe\HOOKS-Assembly-CSharp.dll
-
-
-
-
-
-
-
-
- ..\safe\UnityEngine.dll
-
-
-
-
-
-
-
-
-
-
-
- copy /Y $(TargetPath) "D:\Games\Steam\steamapps\common\Rain World\Mods"
-
-
-
\ No newline at end of file
diff --git a/HeadsShouldersKneesAndToes.sln b/HeadsShouldersKneesAndToes.sln
deleted file mode 100644
index cf40f0e..0000000
--- a/HeadsShouldersKneesAndToes.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30717.126
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeadsShouldersKneesAndToes", "HeadsShouldersKneesAndToes.csproj", "{F66F844E-74DF-46B6-BDFF-F344B6A53410}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F66F844E-74DF-46B6-BDFF-F344B6A53410}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F66F844E-74DF-46B6-BDFF-F344B6A53410}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F66F844E-74DF-46B6-BDFF-F344B6A53410}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F66F844E-74DF-46B6-BDFF-F344B6A53410}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {0DE8B880-2FE5-4D45-BDA7-2CD4793EA4C9}
- EndGlobalSection
-EndGlobal
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100644
index 7bb758d..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("HeadsShouldersKneesAndToes")]
-[assembly: AssemblyDescription("Adds body chunk labels for RW creatures")]
-[assembly: AssemblyCompany("casheww")]
-[assembly: AssemblyProduct("HeadsShouldersKneesAndToes")]
-[assembly: ComVisible(false)]
-[assembly: Guid("f66f844e-74df-46b6-bdff-f344b6a53410")]
-[assembly: AssemblyVersion("1.1.0.0")]
-[assembly: AssemblyFileVersion("1.1.0.0")]
diff --git a/README.md b/README.md
deleted file mode 100644
index b164ab5..0000000
--- a/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# RW-ToolBox
-BepInEx plugin for Rain World designed to help modders debug creature sprites, body chunks, and room tiles
-
-Due to the use of tile grid lines instead of tile node markers, performance impact appears to now be unnoticeable, so the warning that was here before can be disregarded.
-
-## Controls
-**Hyphen/minus key (`-`)** : toggle creature sprite tagger
-
-**Equals key (`=`)** : toggle body chunk tagger
-
-**Del/Delete Key** : toggle tile grid
diff --git a/SpriteLabel.cs b/SpriteLabel.cs
deleted file mode 100644
index 305dd03..0000000
--- a/SpriteLabel.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using System;
-using UnityEngine;
-
-namespace HeadsShouldersKneesAndToes
-{
- class SpriteLabel : CosmeticSprite
- {
- public SpriteLabel(FSprite sprite, UpdatableAndDeletable owner, int index)
- {
- this.sprite = sprite;
- this.owner = owner;
-
- // set label text properties
- label = new FLabel("DisplayFont", index.ToString())
- {
- color = Color.white,
- isVisible = TaggerMod.ChunkTagsVisible,
- anchorX = 0.5f,
- scale = 0.7f
- };
- }
-
- public override void Update(bool eu)
- {
- if (owner.room?.abstractRoom?.name != TaggerMod.CurrentRoomName || owner.slatedForDeletetion)
- {
- Destroy();
- }
-
- base.Update(eu);
- }
-
- public override void Destroy()
- {
- label.isVisible = false;
- label.text = "";
- base.Destroy();
- }
-
- public override void InitiateSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam)
- {
- // set label background properties (sans color)
- sLeaser.sprites = new FSprite[1];
- sLeaser.sprites[0] = new FSprite("pixel", true)
- {
- scaleX = 8f,
- scaleY = 8f
- };
- AddToContainer(sLeaser, rCam, null);
- }
-
- public override void DrawSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, float timeStacker, Vector2 camPos)
- {
- if (sprite is null) return;
-
- Vector2 pos = sprite.GetPosition();
- sLeaser.sprites[0].SetPosition(pos);
- label.SetPosition(pos);
- sLeaser.sprites[0].isVisible = TaggerMod.SpriteTagsVisible;
- label.isVisible = TaggerMod.SpriteTagsVisible;
-
- base.DrawSprites(sLeaser, rCam, timeStacker, camPos);
- }
-
- public override void AddToContainer(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, FContainer newContatiner)
- {
- base.AddToContainer(sLeaser, rCam, null);
- label.RemoveFromContainer();
- sLeaser.sprites[0].RemoveFromContainer();
- rCam.ReturnFContainer("Foreground").AddChild(sLeaser.sprites[0]);
- rCam.ReturnFContainer("Foreground").AddChild(label);
- }
-
- public override void ApplyPalette(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, RoomPalette palette)
- {
- // set colour of label background
- Color color = Color.red;
- color.a = 0.7f;
- sLeaser.sprites[0].color = color;
- }
-
- readonly FSprite sprite;
- readonly UpdatableAndDeletable owner;
- readonly FLabel label;
- }
-}
diff --git a/TaggerMod.cs b/TaggerMod.cs
deleted file mode 100644
index 7bb213b..0000000
--- a/TaggerMod.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using BepInEx;
-using UnityEngine;
-
-namespace HeadsShouldersKneesAndToes
-{
- [BepInPlugin("casheww.chunk_tagger", "Tagger", "1.1")]
- class TaggerMod : BaseUnityPlugin
- {
- public void OnEnable()
- {
- On.RoomCamera.SpriteLeaser.ctor += SpriteLeaser_ctor;
- ChunkTagsVisible = false;
- SpriteTagsVisible = false;
- TileGridVisible = false;
- }
-
- public void Update()
- {
- if (Input.GetKeyDown(KeyCode.Equals))
- {
- ChunkTagsVisible = !ChunkTagsVisible;
- }
- if (Input.GetKeyDown(KeyCode.Minus))
- {
- SpriteTagsVisible = !SpriteTagsVisible;
- }
- if (Input.GetKeyDown(KeyCode.Delete))
- {
- TileGridVisible = !TileGridVisible;
- }
- }
-
- private void SpriteLeaser_ctor(On.RoomCamera.SpriteLeaser.orig_ctor orig, RoomCamera.SpriteLeaser self, IDrawable obj, RoomCamera rCam)
- {
- orig(self, obj, rCam);
-
- if (!(obj is ChunkLabel || obj is SpriteLabel || obj is TileGridLine))
- {
- var physobjs = obj as PhysicalObject ?? (obj is GraphicsModule g ? g.owner : null);
-
- if (physobjs != null)
- {
- for (int i = 0; i < physobjs.bodyChunks.Length; i++)
- {
- ChunkLabel chunkLabel = new ChunkLabel(physobjs.bodyChunks[i], i);
- rCam.room.AddObject(chunkLabel);
- }
- for (int i = 0; i < self.sprites.Length; i++)
- {
- SpriteLabel spriteLabel = new SpriteLabel(self.sprites[i], physobjs, i);
- rCam.room.AddObject(spriteLabel);
- }
- }
-
- if (rCam.room.abstractRoom.name != CurrentRoomName)
- {
- for (int x = 0; x < rCam.room.TileWidth; x++)
- {
- TileGridLine tileMarker = new TileGridLine(TileGridLine.Orientation.Vertical, x);
- rCam.room.AddObject(tileMarker);
- }
- for (int y = 0; y < rCam.room.TileHeight; y++)
- {
- TileGridLine tileMarker = new TileGridLine(TileGridLine.Orientation.Horizontal, y);
- rCam.room.AddObject(tileMarker);
- }
- }
- }
-
- CurrentRoomName = rCam.room.abstractRoom.name;
- }
-
- public static string CurrentRoomName { get; private set; }
-
- public static bool ChunkTagsVisible { get; private set; }
- public static bool SpriteTagsVisible { get; private set; }
- public static bool TileGridVisible { get; private set; }
- }
-}
diff --git a/TileGridLine.cs b/TileGridLine.cs
deleted file mode 100644
index 9a8aeed..0000000
--- a/TileGridLine.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System;
-using UnityEngine;
-
-namespace HeadsShouldersKneesAndToes
-{
- class TileGridLine : CosmeticSprite
- {
- public TileGridLine(Orientation o, int n)
- {
- this.o = o;
- this.n = n;
- }
-
- readonly Orientation o;
- readonly int n;
-
- public override void Update(bool eu)
- {
- if (room.abstractRoom?.name != TaggerMod.CurrentRoomName)
- {
- Destroy();
- }
-
- base.Update(eu);
- }
-
- public override void InitiateSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam)
- {
- sLeaser.sprites = new FSprite[1];
- if (o == Orientation.Vertical)
- {
- sLeaser.sprites[0] = new FSprite("pixel", true)
- {
- scaleX = 1f,
- scaleY = rCam.room.PixelHeight
- };
- }
- else
- {
- sLeaser.sprites[0] = new FSprite("pixel", true)
- {
- scaleX = rCam.room.PixelWidth,
- scaleY = 1f
- };
- }
- AddToContainer(sLeaser, rCam, null);
- }
-
- public override void DrawSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, float timeStacker, Vector2 camPos)
- {
- sLeaser.sprites[0].isVisible = TaggerMod.TileGridVisible;
- if (o == Orientation.Vertical)
- {
- sLeaser.sprites[0].SetPosition(rCam.room.MiddleOfTile(n, rCam.room.TileHeight / 2) - camPos - new Vector2(10, 0));
- }
- else
- {
- sLeaser.sprites[0].SetPosition(rCam.room.MiddleOfTile(rCam.room.TileWidth / 2, n) - camPos - new Vector2(0, 10));
- }
- base.DrawSprites(sLeaser, rCam, timeStacker, camPos);
- }
-
- public override void AddToContainer(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, FContainer newContatiner)
- {
- base.AddToContainer(sLeaser, rCam, null);
- sLeaser.sprites[0].RemoveFromContainer();
- rCam.ReturnFContainer("Foreground").AddChild(sLeaser.sprites[0]);
- }
-
- public override void ApplyPalette(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, RoomPalette palette)
- {
- Color color = Color.white;
- color.a = 0.5f;
- sLeaser.sprites[0].color = color;
- }
-
- public enum Orientation
- {
- Vertical, Horizontal
- }
- }
-}
diff --git a/assets/modinfo.json b/assets/modinfo.json
new file mode 100644
index 0000000..ffed4b3
--- /dev/null
+++ b/assets/modinfo.json
@@ -0,0 +1,10 @@
+{
+ "id": "casheww.physical_object_tools",
+ "name": "Physical Object Tools",
+ "version": "0.3.0",
+ "authors": "casheww",
+ "description": "Adds visual debugging markers for index-labelling PhysicalObjects' sprites and body chunks, tile grids, etc. Contributions from Dual.",
+ "requirements": [],
+ "requirements_names": [],
+ "checksum_override_version": false
+}
diff --git a/assets/thumbnail.png b/assets/thumbnail.png
new file mode 100644
index 0000000..5e696a4
Binary files /dev/null and b/assets/thumbnail.png differ
diff --git a/lib/BepInEx.dll b/lib/BepInEx.dll
new file mode 100644
index 0000000..499c64a
Binary files /dev/null and b/lib/BepInEx.dll differ
diff --git a/lib/BepInEx.xml b/lib/BepInEx.xml
new file mode 100644
index 0000000..1c3d1c4
--- /dev/null
+++ b/lib/BepInEx.xml
@@ -0,0 +1,1657 @@
+
+
+
+ BepInEx
+
+
+
+
+ Base type of all classes representing and enforcing acceptable values of config settings.
+
+
+
+ Type of values that this class can Clamp.
+
+
+
+ Change the value to be acceptable, if it's not already.
+
+
+
+
+ Check if the value is an acceptable value.
+
+
+
+
+ Type of the supported values.
+
+
+
+
+ Get the string for use in config files.
+
+
+
+
+ Specify the list of acceptable values for a setting.
+
+
+
+
+ List of values that a setting can take.
+
+
+
+
+ Specify the list of acceptable values for a setting.
+ If the setting does not equal any of the values, it will be set to the first one.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Specify the range of acceptable values for a setting.
+
+
+
+ Lowest acceptable value
+ Highest acceptable value
+
+
+
+ Lowest acceptable value
+
+
+
+
+ Highest acceptable value
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Provides access to a single setting inside of a .
+
+ Type of the setting.
+
+
+
+ Fired when the setting is changed. Does not detect changes made outside from this object.
+
+
+
+
+ Value of this setting.
+
+
+
+
+
+
+
+ Container for a single setting of a .
+ Each config entry is linked to one config file.
+
+
+
+
+ Types of defaultValue and definition.AcceptableValues have to be the same as settingType.
+
+
+
+
+ Config file this entry is a part of.
+
+
+
+
+ Category and name of this setting. Used as a unique key for identification within a .
+
+
+
+
+ Description / metadata of this setting.
+
+
+
+
+ Type of the that this setting holds.
+
+
+
+
+ Default value of this setting (set only if the setting was not changed before).
+
+
+
+
+ Get or set the value of the setting.
+
+
+
+
+ Get the serialized representation of the value.
+
+
+
+
+ Set the value by using its serialized form.
+
+
+
+
+ If necessary, clamp the value to acceptable value range. T has to be equal to settingType.
+
+
+
+
+ Trigger setting changed event.
+
+
+
+
+ Write a description of this setting using all available metadata.
+
+
+
+
+ Section and key of a setting. Used as a unique key for identification within a .
+ The same definition can be used in multiple config files, it will point to different settings then.
+
+
+
+
+
+ Group of the setting. All settings within a config file are grouped by this.
+
+
+
+
+ Name of the setting.
+
+
+
+
+ Create a new definition. Definitions with same section and key are equal.
+
+ Group of the setting, case sensitive.
+ Name of the setting, case sensitive.
+
+
+
+
+
+
+ Check if the definitions are the same.
+
+
+
+
+
+ Check if the definitions are the same.
+
+
+
+
+
+
+
+ Check if the definitions are the same.
+
+
+
+
+ Check if the definitions are the same.
+
+
+
+
+
+
+
+ Metadata of a .
+
+
+
+
+ Create a new description.
+
+ Text describing the function of the setting and any notes or warnings.
+ Range of values that this setting can take. The setting's value will be automatically clamped.
+ Objects that can be used by user-made classes to add functionality.
+
+
+
+ Text describing the function of the setting and any notes or warnings.
+
+
+
+
+ Range of acceptable values for a setting.
+
+
+
+
+ Objects that can be used by user-made classes to add functionality.
+
+
+
+
+ An empty description.
+
+
+
+
+ A helper class to handle persistent data. All public methods are thread-safe.
+
+
+
+
+ All config entries inside
+
+
+
+
+ Create a list with all config entries inside of this config file.
+
+
+
+
+ Create an array with all config entries inside of this config file. Should be only used for metadata purposes.
+ If you want to access and modify an existing setting then use
+ instead with no description.
+
+
+
+
+ Full path to the config file. The file might not exist until a setting is added and changed, or is called.
+
+
+
+
+ If enabled, writes the config to disk every time a value is set.
+ If disabled, you have to manually use or the changes will be lost!
+
+
+
+
+
+
+
+ Create a new config file at the specified config path.
+
+ Full path to a file that contains settings. The file will be created as needed.
+ If the config file/directory doesn't exist, create it immediately.
+ Information about the plugin that owns this setting file.
+
+
+
+ Reloads the config from disk. Unsaved changes are lost.
+
+
+
+
+ Writes the config to disk.
+
+
+
+
+ Access one of the existing settings. If the setting has not been added yet, null is returned.
+ If the setting exists but has a different type than T, an exception is thrown.
+ New settings should be added with .
+
+ Type of the value contained in this setting.
+ Section and Key of the setting.
+
+
+
+ Access one of the existing settings. If the setting has not been added yet, null is returned.
+ If the setting exists but has a different type than T, an exception is thrown.
+ New settings should be added with .
+
+ Type of the value contained in this setting.
+ Section/category/group of the setting. Settings are grouped by this.
+ Name of the setting.
+
+
+
+ Access one of the existing settings. If the setting has not been added yet, false is returned. Otherwise, true.
+ If the setting exists but has a different type than T, an exception is thrown.
+ New settings should be added with .
+
+ Type of the value contained in this setting.
+ Section and Key of the setting.
+ The ConfigEntry value to return.
+
+
+
+ Access one of the existing settings. If the setting has not been added yet, null is returned.
+ If the setting exists but has a different type than T, an exception is thrown.
+ New settings should be added with .
+
+ Type of the value contained in this setting.
+ Section/category/group of the setting. Settings are grouped by this.
+ Name of the setting.
+ The ConfigEntry value to return.
+
+
+
+ Create a new setting. The setting is saved to drive and loaded automatically.
+ Each definition can be used to add only one setting, trying to add a second setting will throw an exception.
+
+ Type of the value contained in this setting.
+ Section and Key of the setting.
+ Value of the setting if the setting was not created yet.
+ Description of the setting shown to the user and other metadata.
+
+
+
+ Create a new setting. The setting is saved to drive and loaded automatically.
+ Each section and key pair can be used to add only one setting, trying to add a second setting will throw an exception.
+
+ Type of the value contained in this setting.
+ Section/category/group of the setting. Settings are grouped by this.
+ Name of the setting.
+ Value of the setting if the setting was not created yet.
+ Description of the setting shown to the user and other metadata.
+
+
+
+ Create a new setting. The setting is saved to drive and loaded automatically.
+ Each section and key pair can be used to add only one setting, trying to add a second setting will throw an exception.
+
+ Type of the value contained in this setting.
+ Section/category/group of the setting. Settings are grouped by this.
+ Name of the setting.
+ Value of the setting if the setting was not created yet.
+ Simple description of the setting shown to the user.
+
+
+
+ Create a new setting. The setting is saved to drive and loaded automatically.
+ Each definition can be used to add only one setting, trying to add a second setting will throw an exception.
+
+ Type of the value contained in this setting.
+ Section and Key of the setting.
+ Value of the setting if the setting was not created yet.
+ Description of the setting shown to the user and other metadata.
+
+
+
+ Create a new setting. The setting is saved to drive and loaded automatically.
+ Each section and key pair can be used to add only one setting, trying to add a second setting will throw an exception.
+
+ Type of the value contained in this setting.
+ Section/category/group of the setting. Settings are grouped by this.
+ Name of the setting.
+ Value of the setting if the setting was not created yet.
+ Description of the setting shown to the user and other metadata.
+
+
+
+ Create a new setting. The setting is saved to drive and loaded automatically.
+ Each section and key pair can be used to add only one setting, trying to add a second setting will throw an exception.
+
+ Type of the value contained in this setting.
+ Section/category/group of the setting. Settings are grouped by this.
+ Name of the setting.
+ Value of the setting if the setting was not created yet.
+ Simple description of the setting shown to the user.
+
+
+
+ Access a setting. Use Bind instead.
+
+
+
+
+ Access a setting. Use Bind instead.
+
+
+
+
+ An event that is fired every time the config is reloaded.
+
+
+
+
+ Fired when one of the settings is changed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Returns the ConfigDefinitions that the ConfigFile contains.
+ Creates a new array when the property is accessed. Thread-safe.
+
+
+
+
+ Returns the ConfigEntryBase values that the ConfigFile contains.
+ Creates a new array when the property is accessed. Thread-safe.
+
+
+
+
+ Provides access to a single setting inside of a .
+
+ Type of the setting.
+
+
+
+ Entry of this setting in the .
+
+
+
+
+ Unique definition of this setting.
+
+
+
+
+ Config file this setting is inside of.
+
+
+
+
+ Fired when the setting is changed. Does not detect changes made outside from this object.
+
+
+
+
+ Value of this setting.
+
+
+
+
+ A keyboard shortcut that can be used in Update method to check if user presses a key combo. The shortcut is only
+ triggered when the user presses the exact combination. For example, F + LeftCtrl will trigger only if user
+ presses and holds only LeftCtrl, and then presses F. If any other keys are pressed, the shortcut will not trigger.
+
+ Can be used as a value of a setting in
+ to allow user to change this shortcut and have the changes saved.
+
+ How to use: Use in this class instead of in the Update loop.
+
+
+
+
+ Shortcut that never triggers.
+
+
+
+
+ All KeyCode values that can be used in a keyboard shortcut.
+
+
+
+
+ Create a new keyboard shortcut.
+
+ Main key to press
+ Keys that should be held down before main key is registered
+
+
+
+ Main key of the key combination. It has to be pressed / let go last for the combination to be triggered.
+ If the combination is empty, is returned.
+
+
+
+
+ Modifiers of the key combination, if any.
+
+
+
+
+ Attempt to deserialize key combination from the string.
+
+
+
+
+ Serialize the key combination into a user readable string.
+
+
+
+
+ Check if the main key was just pressed (Input.GetKeyDown), and specified modifier keys are all pressed
+
+
+
+
+ Check if the main key is currently held down (Input.GetKey), and specified modifier keys are all pressed
+
+
+
+
+ Check if the main key was just lifted (Input.GetKeyUp), and specified modifier keys are all pressed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Arguments for events concerning a change of a setting.
+
+
+
+
+
+
+
+
+ Setting that was changed
+
+
+
+
+ Serializer/deserializer used by the config system.
+
+
+
+
+ Convert object of a given type to a string using available converters.
+
+
+
+
+ Convert string to an object of a given type using available converters.
+
+
+
+
+ Convert string to an object of a given type using available converters.
+
+
+
+
+ Get a converter for a given type if there is any.
+
+
+
+
+ Add a new type converter for a given type.
+ If a different converter is already added, this call is ignored and false is returned.
+
+
+
+
+ Check if a given type can be converted to and from string.
+
+
+
+
+ Give a list of types with registered converters.
+
+
+
+
+ For types that are in assemblies that can't get loaded before preloader runs (or it won't work on these assemblies)
+
+
+
+
+ A serializer/deserializer combo for some type(s). Used by the config system.
+
+
+
+
+ Used to serialize the type into a (hopefully) human-readable string.
+ Object is the instance to serialize, Type is the object's type.
+
+
+
+
+ Used to deserialize the type from a string.
+ String is the data to deserialize, Type is the object's type, should return instance to an object of Type.
+
+
+
+
+ True if an external console has been started, false otherwise.
+
+
+
+
+ The stream that writes to the standard out stream of the process. Should never be null.
+
+
+
+
+ The stream that writes to an external console. Null if no such console exists
+
+
+
+
+ Data class that represents information about a loadable BepInEx plugin.
+ Contains all metadata and additional info required for plugin loading by .
+
+
+
+
+ General metadata about a plugin.
+
+
+
+
+ Collection of attributes that describe what processes the plugin can run on.
+
+
+
+
+ Collection of attributes that describe what plugins this plugin depends on.
+
+
+
+
+ Collection of attributes that describe what plugins this plugin
+ is incompatible with.
+
+
+
+
+ File path to the plugin DLL
+
+
+
+
+ Instance of the plugin that represents this info. NULL if no plugin is instantiated from info (yet)
+
+
+
+
+
+
+
+ This attribute denotes that a class is a plugin, and specifies the required metadata.
+
+
+
+
+ The unique identifier of the plugin. Should not change between plugin versions.
+
+
+
+
+ The user friendly name of the plugin. Is able to be changed between versions.
+
+
+
+
+ The specfic version of the plugin.
+
+
+
+ The unique identifier of the plugin. Should not change between plugin versions.
+ The user friendly name of the plugin. Is able to be changed between versions.
+ The specfic version of the plugin.
+
+
+
+ This attribute specifies any dependencies that this plugin has on other plugins.
+
+
+
+
+ Flags that are applied to a dependency
+
+
+
+
+ The plugin has a hard dependency on the referenced plugin, and will not run without it.
+
+
+
+
+ This plugin has a soft dependency on the referenced plugin, and is able to run without it.
+
+
+
+
+ The GUID of the referenced plugin.
+
+
+
+
+ The flags associated with this dependency definition.
+
+
+
+
+ The minimum version of the referenced plugin.
+
+
+
+
+ Marks this as depenant on another plugin. The other plugin will be loaded before this one.
+ If the other plugin doesn't exist, what happens depends on the parameter.
+
+ The GUID of the referenced plugin.
+ The flags associated with this dependency definition.
+
+
+
+ Marks this as depenant on another plugin. The other plugin will be loaded before this one.
+ If the other plugin doesn't exist or is of a version below , this plugin will not load and an error will be logged instead.
+
+ The GUID of the referenced plugin.
+ The minimum version of the referenced plugin.
+ When version is supplied the dependency is always treated as HardDependency
+
+
+
+ This attribute specifies other plugins that are incompatible with this plugin.
+
+
+
+
+ The GUID of the referenced plugin.
+
+
+
+
+ Marks this as incompatible with another plugin.
+ If the other plugin exists, this plugin will not be loaded and a warning will be shown.
+
+ The GUID of the referenced plugin.
+
+
+
+ This attribute specifies which processes this plugin should be run for. Not specifying this attribute will load the plugin under every process.
+
+
+
+
+ The name of the process that this plugin will run under.
+
+
+
+ The name of the process that this plugin will run under.
+
+
+
+ Helper class to use for retrieving metadata about a plugin, defined as attributes.
+
+
+
+
+ Retrieves the BepInPlugin metadata from a plugin type.
+
+ The plugin type.
+ The BepInPlugin metadata of the plugin type.
+
+
+
+ Retrieves the BepInPlugin metadata from a plugin instance.
+
+ The plugin instance.
+ The BepInPlugin metadata of the plugin instance.
+
+
+
+ Gets the specified attributes of a type, if they exist.
+
+ The attribute type to retrieve.
+ The plugin type.
+ The attributes of the type, if existing.
+
+
+
+ Gets the specified attributes of an instance, if they exist.
+
+ The attribute type to retrieve.
+ The plugin instance.
+ The attributes of the instance, if existing.
+
+
+
+ Retrieves the dependencies of the specified plugin type.
+
+ The plugin type.
+ A list of all plugin types that the specified plugin type depends upon.
+
+
+
+ This class is appended to AssemblyInfo.cs when BepInEx is built via a CI pipeline.
+ It is mainly intended to signify that the current build is not a release build and is special, like for instance a bleeding edge build.
+
+
+
+
+ The manager and loader for all plugins, and the entry point for BepInEx plugin system.
+
+
+
+
+ The loaded and initialized list of plugins.
+
+
+
+
+ List of all loaded via the chainloader.
+
+
+
+
+ Collection of error chainloader messages that occured during plugin loading.
+ Contains information about what certain plugins were not loaded.
+
+
+
+
+ The GameObject that all plugins are attached to as components.
+
+
+
+
+ Initializes BepInEx to be able to start the chainloader.
+
+
+
+
+ Analyzes the given type definition and attempts to convert it to a valid
+
+ Type definition to analyze.
+ If the type represent a valid plugin, returns a instance. Otherwise, return null.
+
+
+
+ The entrypoint for the BepInEx plugin system.
+
+
+
+
+ A cacheable metadata item. Can be used with and to cache plugin metadata.
+
+
+
+
+ Serialize the object into a binary format.
+
+
+
+
+
+ Loads the object from binary format.
+
+
+
+
+
+ A cached assembly.
+
+
+
+
+
+ List of cached items inside the assembly.
+
+
+
+
+ Timestamp of the assembly. Used to check the age of the cache.
+
+
+
+
+ Provides methods for loading specified types from an assembly.
+
+
+
+
+ Default assembly resolved used by the
+
+
+
+
+ Default reader parameters used by
+
+
+
+
+ Event fired when fails to resolve a type during type loading.
+
+
+
+
+ Looks up assemblies in the given directory and locates all types that can be loaded and collects their metadata.
+
+ The specific base type to search for.
+ The directory to search for assemblies.
+ A function to check if a type should be selected and to build the type metadata.
+ A filter function to quickly determine if the assembly can be loaded.
+ The name of the cache to get cached types from.
+ A dictionary of all assemblies in the directory and the list of type metadatas of types that match the selector.
+
+
+
+ Loads an index of type metadatas from a cache.
+
+ Name of the cache
+ Cacheable item
+ Cached type metadatas indexed by the path of the assembly that defines the type. If no cache is defined, return null.
+
+
+
+ Saves indexed type metadata into a cache.
+
+ Name of the cache
+ List of plugin metadatas indexed by the path to the assembly that contains the types
+ Cacheable item
+
+
+
+ Converts TypeLoadException to a readable string.
+
+ TypeLoadException
+ Readable representation of the exception
+
+
+
+ The base plugin type that is used by the BepInEx plugin loader.
+
+
+
+
+ Information about this plugin as it was loaded.
+
+
+
+
+ Logger instance tied to this plugin.
+
+
+
+
+ Default config file tied to this plugin. The config file will not be created until
+ any settings are added and changed, or is called.
+
+
+
+
+ Create a new instance of a plugin and all of its tied in objects.
+
+ BepInPlugin attribute is missing.
+
+
+
+ Logs entries using Unity specific outputs.
+
+
+
+
+ Log levels to display.
+
+
+
+
+ Writer for the disk log.
+
+
+
+
+ Timer for flushing the logs to a file.
+
+
+
+
+ Whether to write Unity log messages to disk log.
+
+
+
+
+ Creates a new disk log listener.
+
+ Path to the log.
+ Log levels to display.
+ Whether to append logs to an already existing log file.
+ Whether to include Unity log into the disk log.
+
+
+
+
+
+
+
+
+
+ Disposes of Disk logger
+
+
+
+
+ Log event arguments. Contains info about the log message.
+
+
+
+
+ Logged data.
+
+
+
+
+ Log levels for the data.
+
+
+
+
+ Log source that emitted the log event.
+
+
+
+
+ Creates the log event args-
+
+ Logged data.
+ Log level of the data.
+ Log source that emits these args.
+
+
+
+
+
+
+ Like but appends newline at the end.
+
+ Same output as but with new line.
+
+
+
+ A static Logger instance.
+
+
+
+
+ Collection of all log listeners that receive log events.
+
+
+
+
+ Collection of all log source that output log events.
+
+
+
+
+ Logs an entry to the current logger instance.
+
+ The level of the entry.
+ The textual value of the entry.
+
+
+
+ Creates a new log source with a name and attaches it to log sources.
+
+ Name of the log source to create.
+ An instance of that allows to write logs.
+
+
+
+ The level, or severity of a log entry.
+
+
+
+
+ No level selected.
+
+
+
+
+ A fatal error has occurred, which cannot be recovered from.
+
+
+
+
+ An error has occured, but can be recovered from.
+
+
+
+
+ A warning has been produced, but does not necessarily mean that something wrong has happened.
+
+
+
+
+ An important message that should be displayed to the user.
+
+
+
+
+ A message of low importance.
+
+
+
+
+ A message that would likely only interest a developer.
+
+
+
+
+ All log levels.
+
+
+
+
+ Helper methods for log level handling.
+
+
+
+
+ Gets the highest log level when there could potentially be multiple levels provided.
+
+ The log level(s).
+ The highest log level supplied.
+
+
+
+ Returns a translation of a log level to it's associated console colour.
+
+ The log level(s).
+ A console color associated with the highest log level supplied.
+
+
+
+ A generic log listener that receives log events and can route them to some output (e.g. file, console, socket).
+
+
+
+
+ Handle an incoming log event.
+
+ Log source that sent the event. Don't use; instead use
+ Information about the log message.
+
+
+
+ Log source that can output log messages.
+
+
+
+
+ Name of the log source.
+
+
+
+
+ Event that sends the log message. Call to send a log message.
+
+
+
+
+ A generic, multi-purpose log source. Exposes simple API to manually emit logs.
+
+
+
+
+
+
+
+
+
+
+ Creates a manual log source.
+
+ Name of the log source.
+
+
+
+ Logs a message with the specified log level.
+
+ Log levels to attach to the message. Multiple can be used with bitwise ORing.
+ Data to log.
+
+
+
+ Logs a message with level.
+
+ Data to log.
+
+
+
+ Logs a message with level.
+
+ Data to log.
+
+
+
+ Logs a message with level.
+
+ Data to log.
+
+
+
+ Logs a message with level.
+
+ Data to log.
+
+
+
+ Logs a message with level.
+
+ Data to log.
+
+
+
+ Logs a message with level.
+
+ Data to log.
+
+
+
+
+
+
+ A source that routes all logs from API to BepInEx logger.
+
+
+
+
+
+ Whether Trace logs are rerouted.
+
+
+
+
+ Creates a new trace log source.
+
+ New log source (or already existing one).
+
+
+
+ Internal log source.
+
+
+
+
+ Creates a new trace log source.
+
+
+
+
+ Writes a message to the underlying instance.
+
+ The message to write.
+
+
+
+ Writes a message and a newline to the underlying instance.
+
+ The message to write.
+
+
+
+
+
+
+
+
+
+ Logs entries using Unity specific outputs.
+
+
+
+
+
+
+
+
+
+
+ Logs entries using Unity specific outputs.
+
+
+
+
+
+
+
+
+
+
+ Logs entries using Unity specific outputs.
+
+
+
+
+
+
+
+
+
+
+ Creates a new Unity log source.
+
+
+
+
+
+
+
+ Paths used by BepInEx
+
+
+
+
+ List of directories from where Mono will search assemblies before assembly resolving is invoked.
+
+
+
+
+ The directory that the core BepInEx DLLs reside in.
+
+
+
+
+ The path to the core BepInEx DLL.
+
+
+
+
+ The path to the main BepInEx folder.
+
+
+
+
+ The path of the currently executing program BepInEx is encapsulated in.
+
+
+
+
+ The directory that the currently executing process resides in.
+ On OSX however, this is the parent directory of the game.app folder.
+
+
+
+
+ The path to the Managed folder of the currently running Unity game.
+
+
+
+
+ The path to the config directory.
+
+
+
+
+ The path to the global BepInEx configuration file.
+
+
+
+
+ The path to temporary cache files.
+
+
+
+
+ The path to the patcher plugin folder which resides in the BepInEx folder.
+
+
+
+
+ The path to the plugin folder which resides in the BepInEx folder.
+
+ This is ONLY guaranteed to be set correctly when Chainloader has been initialized.
+
+
+
+
+
+ The name of the currently executing process.
+
+
+
+
+ Provides methods for running code on other threads and synchronizing with the main thread.
+
+
+
+
+ Current instance of the helper.
+
+
+
+
+ Gives methods for invoking delegates on the main unity thread, both synchronously and asynchronously.
+ Can be used in many built-in framework types, for example
+ and to make their events fire on the main unity thread.
+
+
+
+
+ Queue the delegate to be invoked on the main unity thread. Use to synchronize your threads.
+
+
+
+
+ Queue the delegate to be invoked on a background thread. Use this to run slow tasks without affecting the game.
+ NOTE: Most of Unity API can not be accessed while running on another thread!
+
+
+ Task to be executed on another thread. Can optionally return an Action that will be executed on the main thread.
+ You can use this action to return results of your work safely. Return null if this is not needed.
+
+
+
+
+ False if current code is executing on the main unity thread, otherwise True.
+ Warning: Will return true before the first frame finishes (i.e. inside plugin Awake and Start methods).
+
+
+
+
+
+ Convenience extensions for utilizing multiple threads and using the .
+
+
+
+
+
+
+
+ Apply a function to a collection of data by spreading the work on multiple threads.
+ Outputs of the functions are returned to the current thread and yielded one by one.
+
+ Type of the input values.
+ Type of the output values.
+ Input values for the work function.
+ Function to apply to the data on multiple threads at once.
+ Number of worker threads. By default SystemInfo.processorCount is used.
+ An exception was thrown inside one of the threads, and the operation was aborted.
+ Need at least 1 workerCount.
+
+
+
+ Generic helper properties and methods.
+
+
+
+
+ Whether current Common Language Runtime supports dynamic method generation using namespace.
+
+
+
+
+ An encoding for UTF-8 which does not emit a byte order mark (BOM).
+
+
+
+
+ Try to perform an action.
+
+ Action to perform.
+ Possible exception that gets returned.
+ True, if action succeeded, false if an exception occured.
+
+
+
+ Combines multiple paths together, as the specific method is not available in .NET 3.5.
+
+ The multiple paths to combine together.
+ A combined path.
+
+
+
+ Returns the parent directory of a path, optionally specifying the amount of levels.
+
+ The path to get the parent directory of.
+ The amount of levels to traverse. Defaults to 1
+ The parent directory.
+
+
+
+ Tries to parse a bool, with a default value if unable to parse.
+
+ The string to parse
+ The value to return if parsing is unsuccessful.
+ Boolean value of input if able to be parsed, otherwise default value.
+
+
+
+ Converts a file path into a UnityEngine.WWW format.
+
+ The file path to convert.
+ A converted file path.
+
+
+
+ Indicates whether a specified string is null, empty, or consists only of white-space characters.
+
+ The string to test.
+ True if the value parameter is null or empty, or if value consists exclusively of white-space characters.
+
+
+
+ Sorts a given dependency graph using a direct toposort, reporting possible cyclic dependencies.
+
+ Nodes to sort
+ Function that maps a node to a collection of its dependencies.
+ Type of the node in a dependency graph.
+ Collection of nodes sorted in the order of least dependencies to the most.
+ Thrown when a cyclic dependency occurs.
+
+
+
+ Checks whether a given cecil type definition is a subtype of a provided type.
+
+ Cecil type definition
+ Type to check against
+ Whether the given cecil type is a subtype of the type.
+
+
+
+ Try to resolve and load the given assembly DLL.
+
+ Name of the assembly, of the type .
+ Directory to search the assembly from.
+ The loaded assembly.
+ True, if the assembly was found and loaded. Otherwise, false.
+
+
+
+ Try to resolve and load the given assembly DLL.
+
+ Name of the assembly, of the type .
+ Directory to search the assembly from.
+ Reader parameters that contain possible custom assembly resolver.
+ The loaded assembly.
+ True, if the assembly was found and loaded. Otherwise, false.
+
+
+
+ Tries to create a file with the given name
+
+ Path of the file to create
+ File open mode
+ Resulting filestream
+ File access options
+ File share options
+
+
+
+
+ Try to parse given string as an assembly name
+
+ Fully qualified assembly name
+ Resulting instance
+ true, if parsing was successful, otherwise false
+
+ On some versions of mono, using fails because it runs on unmanaged side
+ which has problems with encoding.
+ Using solves this by doing parsing on managed side instead.
+
+
+
+
+ Gets unique files in all given directories. If the file with the same name exists in multiple directories,
+ only the first occurrence is returned.
+
+ Directories to search from.
+ File pattern to search.
+ Collection of all files in the directories.
+
+
+
+ Console class with safe handlers for Unity 4.x, which does not have a proper Console implementation
+
+
+
+
diff --git a/lib/HOOKS-Assembly-CSharp.dll b/lib/HOOKS-Assembly-CSharp.dll
new file mode 100644
index 0000000..fbf2b25
Binary files /dev/null and b/lib/HOOKS-Assembly-CSharp.dll differ
diff --git a/lib/Mono.Cecil.Rocks.dll b/lib/Mono.Cecil.Rocks.dll
new file mode 100644
index 0000000..a77ac87
Binary files /dev/null and b/lib/Mono.Cecil.Rocks.dll differ
diff --git a/lib/Mono.Cecil.dll b/lib/Mono.Cecil.dll
new file mode 100644
index 0000000..18735f9
Binary files /dev/null and b/lib/Mono.Cecil.dll differ
diff --git a/lib/MonoMod.RuntimeDetour.dll b/lib/MonoMod.RuntimeDetour.dll
new file mode 100644
index 0000000..a5f47d1
Binary files /dev/null and b/lib/MonoMod.RuntimeDetour.dll differ
diff --git a/lib/MonoMod.RuntimeDetour.xml b/lib/MonoMod.RuntimeDetour.xml
new file mode 100644
index 0000000..45e9d3b
--- /dev/null
+++ b/lib/MonoMod.RuntimeDetour.xml
@@ -0,0 +1,178 @@
+
+
+
+ MonoMod.RuntimeDetour
+
+
+
+
+ A fully managed detour.
+ Multiple Detours for a method to detour from can exist at any given time. Detours can be layered.
+ If you're writing your own detour manager or need to detour native functions, it's better to create instances of NativeDetour instead.
+
+
+
+
+ Mark the detour as applied in the detour chain. This can be done automatically when creating an instance.
+
+
+
+
+ Undo the detour without freeing it, allowing you to reapply it later.
+
+
+
+
+ Free the detour, while also permanently undoing it. This makes any further operations on this detour invalid.
+
+
+
+
+ Undo and free this temporary detour.
+
+
+
+
+ Generate a new DynamicMethod with which you can invoke the previous state.
+
+
+
+
+ Generate a new DynamicMethod with which you can invoke the previous state.
+
+
+
+
+ Generate a new DynamicMethod with which you can invoke the previous state.
+
+
+
+
+ A "raw" native detour, acting as a wrapper around NativeDetourData with a few helpers.
+ Only one NativeDetour for a method to detour from can exist at any given time. NativeDetours cannot be layered.
+ If you don't need the trampoline generator or any of the management helpers, use DetourManager.Native directly.
+ Unless you're writing your own detour manager or need to detour native functions, it's better to create instances of Detour instead.
+
+
+
+
+ Apply the native detour. This can be done automatically when creating an instance.
+
+
+
+
+ Undo the native detour without freeing the detour native data, allowing you to reapply it later.
+
+
+
+
+ Changes the source of this native detour to a new source address. This does not repair the old source location.
+ This also assumes that is simply a new address for the same method as this was constructed with.
+
+ The new source location.
+
+
+
+ Changed the target of this native detour to a new target.
+
+ The new target address.
+
+
+
+ Free the detour's data without undoing it. This makes any further operations on this detour invalid.
+
+
+
+
+ Undo and free this temporary detour.
+
+
+
+
+ Generate a new DynamicMethod with which you can invoke the previous state.
+ If the NativeDetour holds a reference to a managed method, a copy of the original method is returned.
+ If the NativeDetour holds a reference to a native function, an "undo-call-redo" trampoline with a matching signature is returned.
+
+
+
+
+ Generate a new delegate with which you can invoke the previous state.
+ If the NativeDetour holds a reference to a managed method, a copy of the original method is returned.
+ If the NativeDetour holds a reference to a native function, an "undo-call-redo" trampoline with a matching signature is returned.
+
+
+
+
+ Write the given value at the address to + offs, afterwards advancing offs by sizeof(byte).
+
+
+
+
+ Write the given value at the address to + offs, afterwards advancing offs by sizeof(ushort).
+
+
+
+
+ Write the given value at the address to + offs, afterwards advancing offs by sizeof(ushort).
+
+
+
+
+ Write the given value at the address to + offs, afterwards advancing offs by sizeof(ulong).
+
+
+
+
+ Generate a DynamicMethod to easily call the given native function from another DynamicMethod.
+
+ The pointer to the native function to call.
+ A MethodBase with the target function's signature.
+ The detoured DynamicMethod.
+
+
+
+ Fill the DynamicMethodDefinition with a throw.
+
+
+
+
+ Emit a call to DetourManager.Native.Copy using the given parameters.
+
+
+
+
+ Emit a call to DetourManager.Native.Apply using a copy of the given data.
+
+
+
+
+ The data forming a "raw" native detour, created and consumed by DetourManager.Native.
+
+
+
+
+ The method to detour from. Set when the structure is created by the IDetourNativePlatform.
+
+
+
+
+ The target method to be called instead. Set when the structure is created by the IDetourNativePlatform.
+
+
+
+
+ The type of the detour. Determined when the structure is created by the IDetourNativePlatform.
+
+
+
+
+ The size of the detour. Calculated when the structure is created by the IDetourNativePlatform.
+
+
+
+
+ DetourManager.Native-specific data.
+
+
+
+
diff --git a/lib/MonoMod.Utils.dll b/lib/MonoMod.Utils.dll
new file mode 100644
index 0000000..8fd1161
Binary files /dev/null and b/lib/MonoMod.Utils.dll differ
diff --git a/lib/MonoMod.Utils.xml b/lib/MonoMod.Utils.xml
new file mode 100644
index 0000000..98b3a7d
--- /dev/null
+++ b/lib/MonoMod.Utils.xml
@@ -0,0 +1,1465 @@
+
+
+
+ MonoMod.Utils
+
+
+
+
+ An IL manipulation "context" with various helpers and direct access to the MethodBody.
+
+
+
+
+ The manipulator callback, accepted by the Invoke method.
+
+
+
+
+
+ The manipulated method.
+
+
+
+
+ The manipulated method's IL processor.
+
+
+
+
+ The manipulated method body.
+
+
+
+
+ The manipulated method's module.
+
+
+
+
+ The manipulated method instructions.
+
+
+
+
+ A readonly list of all defined labels.
+
+
+
+
+ Has the context been made read-only? No further method access is possible, but the context has not yet been disposed.
+
+
+
+
+ Events which run when the context will be disposed.
+
+
+
+
+ The current reference bag. Used for methods such as EmitReference and EmitDelegate.
+
+
+
+
+ Invoke a given manipulator callback.
+
+ The manipulator to run in this context.
+
+
+
+ Mark this ILContext as read-only and prevent this context from further accessing the originally passed method.
+
+
+ If the method is altered prior to calling MakeReadOnly or afterwards by accessing the method directly, the results are undefined.
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ Define a new label to be marked with a cursor.
+
+ A label without a target instruction.
+
+
+
+ Define a new label pointing at a given instruction.
+
+ The instruction the label will point at.
+ A label pointing at the given instruction.
+
+
+
+ Determine the index of a given instruction.
+
+ The instruction to get the index of.
+ The instruction index, or the end of the method body if it hasn't been found.
+
+
+
+ Obtain all labels pointing at the given instruction.
+
+ The instruction to get all labels for.
+ All labels targeting the given instruction.
+
+
+
+ Bind an arbitary object to an ILContext for static retrieval.
+
+ The type of the object. The combination of typeparam and id provides the unique static reference.
+ The object to store.
+ The id to use in combination with the typeparam for object retrieval.
+
+
+
+ Dispose this context, making it read-only and invoking all OnDispose event listeners.
+
+
+
+
+ Obtain a string representation of this context (method ID and body).
+
+ A string representation of this context.
+
+
+
+ Specifies where a ILCursor should be positioned in relation to the target of a search function
+
+
+
+
+ Move the cursor before the first instruction in the match
+
+
+
+
+ Equivalent to Before with `cursor.MoveAfterLabels()` causing emitted instructions to become the target of incoming labels
+
+
+
+
+ Move the cursor after the last instruction in the match
+
+
+
+
+ Indicates whether the position of a ILCursor is the result of a search function and
+ if the next search should ignore the instruction preceeding or following this cursor.
+
+ SearchTarget.Next is the result of searching with MoveType.Before, and SearchTarget.Prev from MoveType.After
+
+
+
+
+ A foward searching function cannot match the Next instruction and must move the cursor forward
+
+
+
+
+ A reverse searching function cannot match the Next instruction and must move the cursor backward
+
+
+
+
+ A cursor used to manipulate a method body in an ILContext.
+
+
+
+
+ The context to which this cursor belongs to.
+
+
+
+
+ The instruction immediately following the cursor position or null if the cursor is at the end of the instruction list.
+
+
+
+
+ The instruction immediately preceding the cursor position or null if the cursor is at the start of the instruction list.
+
+
+
+
+ The instruction immediately preceding the cursor position or null if the cursor is at the start of the instruction list.
+
+
+
+
+ The index of the instruction immediately following the cursor position. Range: 0 to Instrs.Count
+ Setter accepts negative indexing by adding Instrs.Count to the operand
+
+
+
+
+ Indicates whether the position of a MMILCursor is the result of a search function and
+ if the next search should ignore the instruction preceeding or following this cursor.
+
+ See
+
+
+
+
+ Enumerates all labels which point to the current instruction (label.Target == Next)
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ Create a clone of this cursor.
+
+ The cloned cursor.
+
+
+
+ Is this cursor before the given instruction?
+
+ The instruction to check.
+ True if this cursor is before the given instruction, false otherwise.
+
+
+
+ Is this cursor after the given instruction?
+
+ The instruction to check.
+ True if this cursor is after the given instruction, false otherwise.
+
+
+
+ Obtain a string representation of this cursor (method ID, index, search target, surrounding instructions).
+
+ A string representation of this cursor.
+
+
+
+ Move the cursor to a target instruction. All other movements go through this.
+
+ The target instruction
+ Where to move in relation to the target instruction and incoming labels (branches)
+ Whether to set the `SearchTarget` and skip the target instruction with the next search function
+ this
+
+
+
+ Move the cursor after incoming labels (branches). If an instruction is emitted, all labels which currently point to Next, will point to the newly emitted instruction.
+
+ this
+
+
+
+ Move the cursor before incoming labels (branches). This is the default behaviour. Emitted instructions will not cause labels to change targets.
+
+ this
+
+
+
+ Move the cursor to a target index. Supports negative indexing. See
+
+ this
+
+
+
+ Overload for Goto(label.Target). defaults to MoveType.AfterLabel
+
+ this
+
+
+
+ Search forward and moves the cursor to the next sequence of instructions matching the corresponding predicates. See also
+
+ this
+ If no match is found
+
+
+
+ Search forward and moves the cursor to the next sequence of instructions matching the corresponding predicates.
+
+ True if a match was found
+
+
+
+ Search backward and moves the cursor to the next sequence of instructions matching the corresponding predicates. See also
+
+ this
+ If no match is found
+
+
+
+ Search backward and moves the cursor to the next sequence of instructions matching the corresponding predicates.
+
+ True if a match was found
+
+
+
+ Find the next occurences of a series of instructions matching the given set of predicates with gaps permitted.
+
+ An array of cursors corresponding to each found instruction (MoveType.Before)
+ If no match is found
+
+
+
+ Find the next occurences of a series of instructions matching the given set of predicates with gaps permitted.
+
+ An array of cursors corresponding to each found instruction (MoveType.Before)
+ True if a match was found
+
+
+
+ Search backwards for occurences of a series of instructions matching the given set of predicates with gaps permitted.
+
+ An array of cursors corresponding to each found instruction (MoveType.Before)
+ If no match is found
+
+
+
+ Search backwards for occurences of a series of instructions matching the given set of predicates with gaps permitted.
+
+ An array of cursors corresponding to each found instruction (MoveType.Before)
+ True if a match was found
+
+
+
+ Set the target of a label to the current position (label.Target = Next) and moves after it.
+
+ The label to mark
+
+
+
+ Create a new label targetting the current position (label.Target = Next) and moves after it.
+
+ The newly created label
+
+
+
+ Create a new label for use with
+
+ A new label with no target
+
+
+
+ Remove the Next instruction
+
+
+
+
+ Remove several instructions
+
+
+
+
+ Move the cursor and all labels the cursor is positioned after to a target instruction
+
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position.
+
+ The instruction opcode.
+ The instruction operand.
+ this
+
+
+
+ Emit a new instruction at this cursor's current position, accessing a given member.
+
+ The type in which the member is defined.
+ The instruction opcode.
+ The accessed member name.
+ this
+
+
+
+ Bind an arbitary object to an ILContext for static retrieval. See
+
+
+
+
+ Emit the IL to retrieve a stored reference of type with the given and place it on the stack.
+
+
+
+
+ Store an object in the reference store, and emit the IL to retrieve it and place it on the stack.
+
+
+
+
+ Emit the IL to invoke a delegate as if it were a method. Stack behaviour matches OpCodes.Call
+
+
+
+
+ A label to be used in ILContexts.
+
+
+
+
+ The target instruction this label points at.
+
+
+
+
+ All instructions using this label.
+
+
+
+
+ An IL inline reference bag used for ILContexts.
+
+
+
+
+ Get the object for the given ID.
+
+ The object type.
+ The object ID.
+ The stored object.
+
+
+
+ Get a MethodInfo for the getter.
+
+ The object type.
+ The getter method.
+
+
+
+ Store a new object.
+
+ The object type.
+ The object to be stored.
+ An ID to be used for all further operations.
+
+
+
+ Remove the object with the given ID from the bag, essentially clearing the ID's slot.
+
+ The object type.
+ The object ID.
+
+
+
+ Get a MethodInfo invoking a delegate of the given type, with the delegate at the top of the stack. Used by .
+
+ The delegate type.
+ A MethodInfo invoking a delegate of the given type.
+
+
+
+ The default IL reference bag. Throws NotSupportedException for every operation.
+
+
+
+
+ An IL reference bag implementation to be used for runtime-generated methods.
+
+
+
+
+ Collection of extensions used by MonoMod and other projects.
+
+
+
+
+ Create a hexadecimal string for the given bytes.
+
+ The input bytes.
+ The output hexadecimal string.
+
+
+
+ Invokes all delegates in the invocation list, passing on the result to the next.
+
+ Type of the result.
+ The multicast delegate.
+ The initial value and first parameter.
+ Any other arguments that may be passed.
+ The result of all delegates.
+
+
+
+ Invokes all delegates in the invocation list, as long as the previously invoked delegate returns true.
+
+
+
+
+ Invokes all delegates in the invocation list, as long as the previously invoked delegate returns false.
+
+
+
+
+ Invokes all delegates in the invocation list, as long as the previously invoked delegate returns null.
+
+
+
+
+ Split PascalCase words to become Pascal Case instead.
+
+ PascalCaseString
+ Pascal Case String
+
+
+
+ Read the string from the BinaryReader BinaryWriter in a C-friendly format.
+
+ The input which the method reads from.
+ The output string.
+
+
+
+ Write the string to the BinaryWriter in a C-friendly format.
+
+ The output which the method writes to.
+ The input string.
+
+
+
+ Cast a delegate from one type to another. Compatible with delegates holding an invocation list (combined delegates).
+
+ The input delegate.
+ The output delegate.
+
+
+
+ Cast a delegate from one type to another. Compatible with delegates holding an invocation list (combined delegates).
+
+ The input delegate.
+ The wanted output delegate type.
+ The output delegate.
+
+
+
+ Print the exception to the console, including extended loading / reflection data useful for mods.
+
+
+
+
+ Get the method of interest for a given state machine method.
+
+ The method creating the state machine.
+ The "main" method in the state machine.
+
+
+
+ Gets the actual generic method definition of a method, as defined on the fully open type.
+
+ The potentially instantiated method to find the definition of.
+ The original method definition, with no generic arguments filled in.
+
+
+
+ Safely resolve a reference, silently discarding any exceptions.
+
+ The reference to resolve.
+ The resolved definition or null.
+
+
+
+ Safely resolve a reference, silently discarding any exceptions.
+
+ The reference to resolve.
+ The resolved definition or null.
+
+
+
+ Safely resolve a reference, silently discarding any exceptions.
+
+ The reference to resolve.
+ The resolved definition or null.
+
+
+
+ Safely resolve a reference, silently discarding any exceptions.
+
+ The reference to resolve.
+ The resolved definition or null.
+
+
+
+ Get a certain custom attribute from an attribute provider.
+
+ The attribute provider.
+ The custom attribute name.
+ The first matching custom attribute, or null if no matching attribute has been found.
+
+
+
+ Determine if an attribute provider has got a specific custom attribute.
+
+ The attribute provider.
+ The custom attribute name.
+ true if the attribute provider contains the given custom attribute, false otherwise.
+
+
+
+ Get the integer value pushed onto the stack with this instruction.
+
+ The instruction to get the pushed integer value for.
+ The pushed integer value.
+
+
+
+ Get the integer value pushed onto the stack with this instruction.
+
+ The instruction to get the pushed integer value for.
+ The pushed integer value or null.
+
+
+
+ Determine if the method call is a base method call.
+
+ The caller method body.
+ The called method.
+ True if the called method is a base method of the caller method, false otherwise.
+
+
+
+ Determine if the given method can be preferably called using callvirt.
+
+ The called method.
+ True if the called method can be called using callvirt, false otherwise.
+
+
+
+ Determine if the given type is a struct (also known as "value type") or struct-alike (f.e. primitive).
+
+ The type to check.
+ True if the type is a struct, primitive or similar, false otherwise.
+
+
+
+ Get the long form opcode for any short form opcode.
+
+ The short form opcode.
+ The long form opcode.
+
+
+
+ Get the short form opcode for any long form opcode.
+
+ The long form opcode.
+ The short form opcode.
+
+
+
+ Calculate updated instruction offsets. Required for certain manual fixes.
+
+ The method to recalculate the IL instruction offsets for.
+
+
+
+ Fix (and optimize) any instructions which should use the long / short form opcodes instead.
+
+ The method to apply the fixes to.
+
+
+
+ Check if the signatures of a given System.Reflection and Mono.Cecil member reference match.
+
+ The System.Reflection member reference.
+ The Mono.Cecil member reference.
+ True if both references share the same signature, false otherwise.
+
+
+
+ Check if the signatures of a given System.Reflection and Mono.Cecil member reference match.
+
+ The Mono.Cecil member reference.
+ The System.Reflection member reference.
+ True if both references share the same signature, false otherwise.
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ See
+
+
+
+
+ Determine if two types are compatible with each other (f.e. object with string, or enums with their underlying integer type).
+
+ The first type.
+ The second type.
+ True if both types are compatible with each other, false otherwise.
+
+
+
+ Creates a delegate of the specified type from this method.
+
+ The method to create the delegate from.
+ The type of the delegate to create.
+ The delegate for this method.
+
+
+
+ Creates a delegate of the specified type with the specified target from this method.
+
+ The method to create the delegate from.
+ The type of the delegate to create.
+ The object targeted by the delegate.
+ The delegate for this method.
+
+
+
+ Creates a delegate of the specified type from this method.
+
+ The method to create the delegate from.
+ The type of the delegate to create.
+ The delegate for this method.
+
+
+
+ Creates a delegate of the specified type with the specified target from this method.
+
+ The method to create the delegate from.
+ The type of the delegate to create.
+ The object targeted by the delegate.
+ The delegate for this method.
+
+
+
+ Find a method for a given ID.
+
+ The type to search in.
+ The method ID.
+ Whether to perform a simple search pass as well or not.
+ The first matching method or null.
+
+
+
+ Find a method for a given ID recursively (including the passed type's base types).
+
+ The type to search in.
+ The method ID.
+ Whether to perform a simple search pass as well or not.
+ The first matching method or null.
+
+
+
+ Find a method for a given ID.
+
+ The type to search in.
+ The method ID.
+ Whether to perform a simple search pass as well or not.
+ The first matching method or null.
+
+
+
+ Find a method for a given ID recursively (including the passed type's base types).
+
+ The type to search in.
+ The method ID.
+ Whether to perform a simple search pass as well or not.
+ The first matching method or null.
+
+
+
+ Find a property for a given name.
+
+ The type to search in.
+ The property name.
+ The first matching property or null.
+
+
+
+ Find a property for a given name recursively (including the passed type's base types).
+
+ The type to search in.
+ The property name.
+ The first matching property or null.
+
+
+
+ Find a field for a given name.
+
+ The type to search in.
+ The field name.
+ The first matching field or null.
+
+
+
+ Find a field for a given name recursively (including the passed type's base types).
+
+ The type to search in.
+ The field name.
+ The first matching field or null.
+
+
+
+ Find an event for a given name.
+
+ The type to search in.
+ The event name.
+ The first matching event or null.
+
+
+
+ Find an event for a given name recursively (including the passed type's base types).
+
+ The type to search in.
+ The event name.
+ The first matching event or null.
+
+
+
+ Get a reference ID that is similar to the full name, but consistent between System.Reflection and Mono.Cecil.
+
+ The method to get the ID for.
+ The name to use instead of the reference's own name.
+ The ID to use instead of the reference's declaring type ID.
+ Whether the type ID should be included or not. System.Reflection avoids it by default.
+ Whether the ID should be "simple" (name only).
+ The ID.
+
+
+
+ Get a reference ID that is similar to the full name, but consistent between System.Reflection and Mono.Cecil.
+
+ The call site to get the ID for.
+ The ID.
+
+
+
+ Get a reference ID that is similar to the full name, but consistent between System.Reflection and Mono.Cecil.
+
+ The method to get the ID for.
+ The name to use instead of the reference's own name.
+ The ID to use instead of the reference's declaring type ID.
+ Whether the type ID should be included or not. System.Reflection avoids it by default.
+ Whether the method is regarded as a proxy method or not. Setting this paramater to true will skip the first parameter.
+ Whether the ID should be "simple" (name only).
+ The ID.
+
+
+
+ Get the "patch name" - the name of the target to patch - for the given member.
+
+ The member to get the patch name for.
+ The patch name.
+
+
+
+ Get the "patch name" - the name of the target to patch - for the given member.
+
+ The member to get the patch name for.
+ The patch name.
+
+
+
+ Clone the given method definition.
+
+ The original method.
+ The method definition to apply the cloning process onto, or null to create a new method.
+ A clone of the original method.
+
+
+
+ Clone the given method body.
+
+ The original method body.
+ The method which will own the newly cloned method body.
+ A clone of the original method body.
+
+
+
+ Force-update a generic parameter's position and type.
+
+ The generic parameter to update.
+ The new position.
+ The new type.
+ The updated generic parameter.
+
+
+
+ Resolve a given generic parameter in another context.
+
+ The new context.
+ The original generic parameter.
+ A generic parameter provided by the given context which matches the original generic parameter.
+
+
+
+ Relink the given member reference (metadata token provider).
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Relink the given type reference.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Relink the given method reference.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Relink the given callsite.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Relink the given field reference.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Relink the given parameter definition.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Clone the given parameter definition.
+
+ The original parameter definition.
+ A clone of the original parameter definition.
+
+
+
+ Relink the given custom attribute.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Clone the given custom attribute.
+
+ The original custom attribute.
+ A clone of the original custom attribute.
+
+
+
+ Relink the given generic parameter reference.
+
+ The reference to relink.
+ The relinker to use during the relinking process.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Clone the given generic parameter.
+
+ The original generic parameter.
+ A clone of the original generic parameter.
+
+
+
+ Get the managed size of a given type. This matches an IL-level sizeof(t), even if it cannot be determined normally in C#.
+ Note that sizeof(t) != Marshal.SizeOf(t), f.e. when t is char.
+
+ The type to get the size from.
+ The managed type size.
+
+
+
+ Get a type which matches what the method should receive via ldarg.0
+
+ The method to obtain the "this" parameter type from.
+ The "this" parameter type.
+
+
+
+ Get a native function pointer for a given method. This matches an IL-level ldftn.
+
+
+ The result of ldftn doesn't always match that of MethodHandle.GetFunctionPointer().
+ For example, ldftn doesn't JIT-compile the method on mono, which thus keeps the class constructor untouched.
+ And on .NET, struct overrides (f.e. ToString) have got multiple entry points pointing towards the same code.
+
+ The method to get a native function pointer for.
+ The native function pointer.
+
+
+
+ A variant of ILGenerator which uses Mono.Cecil under the hood.
+
+
+
+
+ The underlying Mono.Cecil.Cil.ILProcessor.
+
+
+
+
+ Abstract version of System.Reflection.Emit.ILGenerator. See for proper documentation.
+
+
+
+
+ Get a "real" ILGenerator for this ILGeneratorShim.
+
+ A "real" ILGenerator.
+
+
+
+ Get the proxy type for a given ILGeneratorShim type. The proxy type implements ILGenerator.
+
+ The ILGeneratorShim type.
+ The "real" ILGenerator type.
+
+
+
+ Get the proxy type for a given ILGeneratorShim type. The proxy type implements ILGenerator.
+
+ The ILGeneratorShim type.
+ The "real" ILGenerator type.
+
+
+
+ Get the non-generic proxy type implementing ILGenerator.
+
+ The "real" ILGenerator type, non-generic.
+
+
+
+ A DynamicMethodDefinition "generator", responsible for generating a runtime MethodInfo from a DMD MethodDefinition.
+
+
+
+
+
+ A DMDGenerator implementation using Mono.Cecil to build an in-memory assembly.
+
+
+
+
+ Fill the DynamicMethod with a stub.
+
+
+
+
+ Fill the DynamicMethod with a stub.
+
+
+
+
+ Emit a reference to an arbitrary object. Note that the references "leak."
+
+
+
+
+ Emit a reference to an arbitrary object. Note that the references "leak."
+
+
+
+
+ Emit a reference to an arbitrary object. Note that the references "leak."
+
+
+
+
+ Emit a reference to an arbitrary object. Note that the references "leak."
+
+
+
+
+ Allows you to remap library paths / names and specify loading flags. Useful for cross-platform compatibility. Applies only to DynDll.
+
+
+
+
+ Open a given library and get its handle.
+
+ The library name.
+ Whether to skip using the mapping or not.
+ Any optional platform-specific flags.
+ The library handle.
+
+
+
+ Try to open a given library and get its handle.
+
+ The library name.
+ The library handle, or null if it failed loading.
+ Whether to skip using the mapping or not.
+ Any optional platform-specific flags.
+ True if the handle was obtained, false otherwise.
+
+
+
+ Release a library handle obtained via OpenLibrary. Don't release the result of OpenLibrary(null)!
+
+ The library handle.
+
+
+
+ Get a function pointer for a function in the given library.
+
+ The library handle.
+ The function name.
+ The function pointer.
+
+
+
+ Get a function pointer for a function in the given library.
+
+ The library handle.
+ The function name.
+ The function pointer, or null if it wasn't found.
+ True if the function pointer was obtained, false otherwise.
+
+
+
+ Extension method wrapping Marshal.GetDelegateForFunctionPointer
+
+
+
+
+ Fill all static delegate fields with the DynDllImport attribute.
+ Call this early on in the static constructor.
+
+ The type containing the DynDllImport delegate fields.
+ Any optional mappings similar to the static mappings.
+
+
+
+ Fill all instance delegate fields with the DynDllImport attribute.
+ Call this early on in the constructor.
+
+ An instance of a type containing the DynDllImport delegate fields.
+ Any optional mappings similar to the static mappings.
+
+
+
+ Similar to DllImport, but requires you to run typeof(DeclaringType).ResolveDynDllImports();
+
+
+
+
+ The library or library alias to use.
+
+
+
+
+ A list of possible entrypoints that the function can be resolved to. Implicitly includes the field name and delegate name.
+
+
+
+ The library or library alias to use.
+ A list of possible entrypoints that the function can be resolved to. Implicitly includes the field name and delegate name.
+
+
+
+ A mapping entry, to be used by .
+
+
+
+
+ The name as which the library will be resolved as. Useful to remap libraries or to provide full paths.
+
+
+
+
+ Platform-dependent loading flags.
+
+
+
+ The name as which the library will be resolved as. Useful to remap libraries or to provide full paths.
+ Platform-dependent loading flags.
+
+
+
+ The relinker callback delegate type.
+
+ The reference (metadata token provider) to relink.
+ The generic context provided to relink generic references.
+ A relinked reference.
+
+
+
+ Generic platform enum.
+
+
+
+
+ Bit applied to all OSes (Unknown, Windows, MacOS, ...).
+
+
+
+
+ On demand 64-bit platform bit.
+
+
+
+
+ Applied to all NT and NT-oid platforms (Windows).
+
+
+
+
+ Applied to all Unix and Unix-oid platforms (macOS, Linux, ...).
+
+
+
+
+ On demand ARM platform bit.
+
+
+
+
+ Unknown OS.
+
+
+
+
+ Windows, using the NT kernel.
+
+
+
+
+ macOS, using the Darwin kernel.
+
+
+
+
+ Linux.
+
+
+
+
+ Android, using the Linux kernel.
+
+
+
+
+ iOS, sharing components with macOS.
+
+
+
+
diff --git a/lib/MonoMod.dll b/lib/MonoMod.dll
new file mode 100644
index 0000000..facf3c1
Binary files /dev/null and b/lib/MonoMod.dll differ
diff --git a/lib/PUBLIC-Assembly-CSharp.dll b/lib/PUBLIC-Assembly-CSharp.dll
new file mode 100644
index 0000000..bb4bb9f
Binary files /dev/null and b/lib/PUBLIC-Assembly-CSharp.dll differ
diff --git a/lib/UnityEngine.CoreModule.dll b/lib/UnityEngine.CoreModule.dll
new file mode 100644
index 0000000..f98502a
Binary files /dev/null and b/lib/UnityEngine.CoreModule.dll differ
diff --git a/lib/UnityEngine.InputLegacyModule.dll b/lib/UnityEngine.InputLegacyModule.dll
new file mode 100755
index 0000000..71cb132
Binary files /dev/null and b/lib/UnityEngine.InputLegacyModule.dll differ
diff --git a/lib/UnityEngine.dll b/lib/UnityEngine.dll
new file mode 100644
index 0000000..16ab5f1
Binary files /dev/null and b/lib/UnityEngine.dll differ
diff --git a/src/Config.cs b/src/Config.cs
new file mode 100644
index 0000000..84dd682
--- /dev/null
+++ b/src/Config.cs
@@ -0,0 +1,40 @@
+using Menu.Remix.MixedUI;
+
+namespace PhysicalObjectTools;
+
+public sealed class ConfigOI : OptionInterface {
+ public ConfigOI(Plugin plugin) {
+ this.plugin = plugin;
+ ChunkKey = config.Bind("chunk_key", KeyCode.Minus);
+ SpriteKey = config.Bind("sprite_key", KeyCode.Equals);
+ TileGridKey = config.Bind("tile_grid_key", KeyCode.Delete);
+ }
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ Tabs = new OpTab[1] {new OpTab(this)};
+ OpTab t = Tabs[0];
+
+ t.AddItems(
+ new OpLabel(new Vector2(150f, 550f), new Vector2(300f, 30f), plugin.Info.Metadata.Name, bigText: true),
+ new OpLabel(new Vector2(150f, 520f), new Vector2(300f, 30f), plugin.Info.Metadata.Version.ToString())
+ );
+
+ t.AddItems(
+ new OpLabel(75f, 475f, "Chunk key"),
+ new OpKeyBinder(ChunkKey, new Vector2(180f, 475f), new Vector2(80f, 30f)),
+ new OpLabel(75f, 440f, "Sprite key"),
+ new OpKeyBinder(SpriteKey, new Vector2(180f, 440f), new Vector2(80f, 30f)),
+ new OpLabel(75f, 405f, "Tile grid key"),
+ new OpKeyBinder(TileGridKey, new Vector2(180f, 405f), new Vector2(80f, 30f))
+ );
+ }
+
+ private readonly Plugin plugin;
+ public static Configurable ChunkKey {get; private set;}
+ public static Configurable SpriteKey {get; private set;}
+ public static Configurable TileGridKey {get; private set;}
+
+}
diff --git a/src/DebuggingSprites/ChunkLabel.cs b/src/DebuggingSprites/ChunkLabel.cs
new file mode 100644
index 0000000..2442a26
--- /dev/null
+++ b/src/DebuggingSprites/ChunkLabel.cs
@@ -0,0 +1,76 @@
+
+namespace PhysicalObjectTools.DebuggingSprites;
+
+class ChunkLabel : CosmeticSprite
+{
+ public ChunkLabel(BodyChunk chunk, int index)
+ {
+ this.chunk = chunk;
+
+ // set label text properties
+ label = new FLabel("DisplayFont", index.ToString())
+ {
+ color = Color.white,
+ isVisible = Plugin.ChunkTagsVisible,
+ anchorX = 0.5f,
+ scale = 0.7f
+ };
+ }
+
+ public override void Update(bool eu)
+ {
+ if (chunk.owner?.room?.abstractRoom?.name != Plugin.CurrentRoomName || chunk.owner.slatedForDeletetion)
+ {
+ Destroy();
+ }
+
+ base.Update(eu);
+ }
+
+ public override void Destroy()
+ {
+ label.isVisible = false;
+ label.text = "";
+ base.Destroy();
+ }
+
+ public override void InitiateSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam)
+ {
+ // set label background properties (sans color)
+ sLeaser.sprites = new FSprite[1];
+ sLeaser.sprites[0] = new FSprite("pixel", true);
+ AddToContainer(sLeaser, rCam, null);
+ }
+
+ public override void DrawSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, float timeStacker, Vector2 camPos)
+ {
+ Vector2 pos = Vector2.Lerp(chunk.lastPos, chunk.pos, timeStacker) - camPos;
+ sLeaser.sprites[0].SetPosition(pos);
+ sLeaser.sprites[0].scaleX = sLeaser.sprites[0].scaleY = chunk.rad * 2;
+ label.SetPosition(pos);
+ sLeaser.sprites[0].isVisible = Plugin.ChunkTagsVisible;
+ label.isVisible = Plugin.ChunkTagsVisible;
+
+ base.DrawSprites(sLeaser, rCam, timeStacker, camPos);
+ }
+
+ public override void AddToContainer(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, FContainer newContatiner)
+ {
+ base.AddToContainer(sLeaser, rCam, null);
+ label.RemoveFromContainer();
+ sLeaser.sprites[0].RemoveFromContainer();
+ rCam.ReturnFContainer("Foreground").AddChild(sLeaser.sprites[0]);
+ rCam.ReturnFContainer("Foreground").AddChild(label);
+ }
+
+ public override void ApplyPalette(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, RoomPalette palette)
+ {
+ // set colour of label background
+ Color color = palette.skyColor * 0.9f;
+ color.a = 0.7f;
+ sLeaser.sprites[0].color = color;
+ }
+
+ readonly BodyChunk chunk;
+ readonly FLabel label;
+}
diff --git a/src/DebuggingSprites/SpriteLabel.cs b/src/DebuggingSprites/SpriteLabel.cs
new file mode 100644
index 0000000..f99537b
--- /dev/null
+++ b/src/DebuggingSprites/SpriteLabel.cs
@@ -0,0 +1,83 @@
+
+namespace PhysicalObjectTools.DebuggingSprites;
+
+class SpriteLabel : CosmeticSprite
+{
+ public SpriteLabel(FSprite sprite, UpdatableAndDeletable owner, int index)
+ {
+ this.sprite = sprite;
+ this.owner = owner;
+
+ // set label text properties
+ label = new FLabel("DisplayFont", index.ToString())
+ {
+ color = Color.white,
+ isVisible = Plugin.ChunkTagsVisible,
+ anchorX = 0.5f,
+ scale = 0.7f
+ };
+ }
+
+ public override void Update(bool eu)
+ {
+ if (owner.room?.abstractRoom?.name != Plugin.CurrentRoomName || owner.slatedForDeletetion)
+ {
+ Destroy();
+ }
+
+ base.Update(eu);
+ }
+
+ public override void Destroy()
+ {
+ label.isVisible = false;
+ label.text = "";
+ base.Destroy();
+ }
+
+ public override void InitiateSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam)
+ {
+ // set label background properties (sans color)
+ sLeaser.sprites = new FSprite[1];
+ sLeaser.sprites[0] = new FSprite("pixel", true)
+ {
+ scaleX = 8f,
+ scaleY = 8f
+ };
+ AddToContainer(sLeaser, rCam, null);
+ }
+
+ public override void DrawSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, float timeStacker, Vector2 camPos)
+ {
+ if (sprite is null) return;
+
+ Vector2 pos = sprite.GetPosition();
+ sLeaser.sprites[0].SetPosition(pos);
+ label.SetPosition(pos);
+ sLeaser.sprites[0].isVisible = Plugin.SpriteTagsVisible;
+ label.isVisible = Plugin.SpriteTagsVisible;
+
+ base.DrawSprites(sLeaser, rCam, timeStacker, camPos);
+ }
+
+ public override void AddToContainer(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, FContainer newContatiner)
+ {
+ base.AddToContainer(sLeaser, rCam, null);
+ label.RemoveFromContainer();
+ sLeaser.sprites[0].RemoveFromContainer();
+ rCam.ReturnFContainer("Foreground").AddChild(sLeaser.sprites[0]);
+ rCam.ReturnFContainer("Foreground").AddChild(label);
+ }
+
+ public override void ApplyPalette(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, RoomPalette palette)
+ {
+ // set colour of label background
+ Color color = Color.red;
+ color.a = 0.7f;
+ sLeaser.sprites[0].color = color;
+ }
+
+ readonly FSprite sprite;
+ readonly UpdatableAndDeletable owner;
+ readonly FLabel label;
+}
diff --git a/src/DebuggingSprites/TileGridLine.cs b/src/DebuggingSprites/TileGridLine.cs
new file mode 100644
index 0000000..770372e
--- /dev/null
+++ b/src/DebuggingSprites/TileGridLine.cs
@@ -0,0 +1,78 @@
+
+namespace PhysicalObjectTools.DebuggingSprites;
+class TileGridLine : CosmeticSprite
+{
+ public TileGridLine(Orientation o, int n)
+ {
+ this.o = o;
+ this.n = n;
+ }
+
+ readonly Orientation o;
+ readonly int n;
+
+ public override void Update(bool eu)
+ {
+ if (room.abstractRoom?.name != Plugin.CurrentRoomName)
+ {
+ Destroy();
+ }
+
+ base.Update(eu);
+ }
+
+ public override void InitiateSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam)
+ {
+ sLeaser.sprites = new FSprite[1];
+ if (o == Orientation.Vertical)
+ {
+ sLeaser.sprites[0] = new FSprite("pixel", true)
+ {
+ scaleX = 1f,
+ scaleY = rCam.room.PixelHeight
+ };
+ }
+ else
+ {
+ sLeaser.sprites[0] = new FSprite("pixel", true)
+ {
+ scaleX = rCam.room.PixelWidth,
+ scaleY = 1f
+ };
+ }
+ AddToContainer(sLeaser, rCam, null);
+ }
+
+ public override void DrawSprites(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, float timeStacker, Vector2 camPos)
+ {
+ sLeaser.sprites[0].isVisible = Plugin.TileGridVisible;
+ if (o == Orientation.Vertical)
+ {
+ sLeaser.sprites[0].SetPosition(rCam.room.MiddleOfTile(n, rCam.room.TileHeight / 2) - camPos - new Vector2(10, 0));
+ }
+ else
+ {
+ sLeaser.sprites[0].SetPosition(rCam.room.MiddleOfTile(rCam.room.TileWidth / 2, n) - camPos - new Vector2(0, 10));
+ }
+ base.DrawSprites(sLeaser, rCam, timeStacker, camPos);
+ }
+
+ public override void AddToContainer(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, FContainer newContatiner)
+ {
+ base.AddToContainer(sLeaser, rCam, null);
+ sLeaser.sprites[0].RemoveFromContainer();
+ rCam.ReturnFContainer("Foreground").AddChild(sLeaser.sprites[0]);
+ }
+
+ public override void ApplyPalette(RoomCamera.SpriteLeaser sLeaser, RoomCamera rCam, RoomPalette palette)
+ {
+ Color color = Color.white;
+ color.a = 0.5f;
+ sLeaser.sprites[0].color = color;
+ }
+
+ public enum Orientation
+ {
+ Vertical, Horizontal
+ }
+}
diff --git a/src/Plugin.cs b/src/Plugin.cs
new file mode 100644
index 0000000..a67eb32
--- /dev/null
+++ b/src/Plugin.cs
@@ -0,0 +1,106 @@
+global using UnityEngine;
+
+using BepInEx;
+using System.Security.Permissions;
+
+#pragma warning disable CS0618 // Do not remove the following line.
+[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
+
+namespace PhysicalObjectTools;
+using DebuggingSprites;
+
+[BepInPlugin("casheww.physical_object_tools", "Physical Object Tools", "0.3.0")]
+public sealed class Plugin : BaseUnityPlugin
+{
+ public void OnEnable()
+ {
+ On.RainWorld.OnModsInit += (orig, rw) => {
+ orig(rw);
+ ChunkTagsVisible = false;
+ SpriteTagsVisible = false;
+ TileGridVisible = false;
+
+ try {
+ MachineConnector.SetRegisteredOI(Info.Metadata.GUID, new ConfigOI(this));
+ }
+ catch (System.Exception e) {
+ Logger.LogError(e);
+ }
+ };
+
+ On.Player.Update += (orig, self, eu) => {
+ orig(self, eu);
+ if (self.room?.abstractRoom != null)
+ CurrentRoomName = self.room.abstractRoom.name;
+ };
+
+ On.RoomCamera.SpriteLeaser.ctor += SpriteLeaser_ctor;
+ }
+
+ public void Update() {
+ if (ConfigOI.ChunkKey == null)
+ return;
+
+ if (Input.GetKeyDown(ConfigOI.ChunkKey.Value))
+ ChunkTagsVisible = !ChunkTagsVisible;
+
+ if (Input.GetKeyDown(ConfigOI.SpriteKey.Value))
+ SpriteTagsVisible = !SpriteTagsVisible;
+
+ if (Input.GetKeyDown(ConfigOI.TileGridKey.Value))
+ TileGridVisible = !TileGridVisible;
+ }
+
+ private void SpriteLeaser_ctor(On.RoomCamera.SpriteLeaser.orig_ctor orig, RoomCamera.SpriteLeaser self,
+ IDrawable obj, RoomCamera rCam) {
+ orig(self, obj, rCam);
+
+ bool roomChanged = CurrentRoomName != rCam.room.abstractRoom.name;
+ CurrentRoomName = rCam.room.abstractRoom.name;
+
+ if (obj is ChunkLabel || obj is SpriteLabel || obj is TileGridLine)
+ return;
+
+ PhysicalObject physobj = obj as PhysicalObject ?? (obj is GraphicsModule g ? g.owner : null);
+
+ if (physobj != null) {
+ AddChunkLabels(self, physobj);
+ AddSpriteLabels(self, physobj);
+ }
+
+ if (roomChanged) {
+ AddTileGrid(rCam.room);
+ }
+ }
+
+ public void AddChunkLabels(RoomCamera.SpriteLeaser sLeaser, PhysicalObject physobj) {
+ for (int i = 0; i < physobj.bodyChunks.Length; i++) {
+ ChunkLabel l = new ChunkLabel(physobj.bodyChunks[i], i);
+ physobj.room.AddObject(l);
+ }
+ }
+
+ public void AddSpriteLabels(RoomCamera.SpriteLeaser sLeaser, PhysicalObject physobj) {
+ for (int i = 0; i < sLeaser.sprites.Length; i++) {
+ SpriteLabel l = new SpriteLabel(sLeaser.sprites[i], physobj, i);
+ physobj.room.AddObject(l);
+ }
+ }
+
+ public void AddTileGrid(Room room) {
+ for (int x = 0; x < room.TileWidth; x++) {
+ TileGridLine l = new TileGridLine(TileGridLine.Orientation.Vertical, x);
+ room.AddObject(l);
+ }
+ for (int y = 0; y < room.TileHeight; y++) {
+ TileGridLine l = new TileGridLine(TileGridLine.Orientation.Horizontal, y);
+ room.AddObject(l);
+ }
+ }
+
+
+ public static bool ChunkTagsVisible { get; private set; }
+ public static bool SpriteTagsVisible { get; private set; }
+ public static bool TileGridVisible { get; private set; }
+ public static string CurrentRoomName { get; private set;}
+}
diff --git a/src/casheww.physical_object_tools.csproj b/src/casheww.physical_object_tools.csproj
new file mode 100644
index 0000000..cb94d7f
--- /dev/null
+++ b/src/casheww.physical_object_tools.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net48
+ 11
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+