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 + + + + + + + + + + + +