├── .gitignore ├── .gitmodules ├── Assembly-CSharp.Base.mm ├── Assembly-CSharp.Base.mm.csproj ├── Properties │ └── AssemblyInfo.cs ├── res │ └── idmaps │ │ └── items.txt └── src │ ├── API │ ├── IDPool.cs │ └── Prefab.cs │ ├── AnimDumper │ ├── CollectionDumper.cs │ └── GridPacker.cs │ ├── AnimLoader │ ├── Animation.cs │ ├── AnimatorGenerator.cs │ ├── Collection.cs │ ├── CollectionGenerator.cs │ └── YAMLMapping.cs │ ├── Console │ ├── AutoCompletor.cs │ ├── Backend.cs │ ├── Command.cs │ ├── DefaultCommands.cs │ ├── DualWieldForcer.cs │ ├── History.cs │ ├── Menu.cs │ └── Parser │ │ ├── AST.cs │ │ ├── Executor.cs │ │ ├── Lexer.cs │ │ ├── Parser.cs │ │ └── Token.cs │ ├── External │ ├── ReflectionHelper.cs │ ├── SGUI │ │ ├── .gitignore │ │ ├── README.md │ │ └── src │ │ │ ├── Animations │ │ │ ├── SAnimationSequence.cs │ │ │ ├── SEasings.cs │ │ │ ├── SFadeAnimation.cs │ │ │ ├── SFadeInAnimation.cs │ │ │ ├── SFadeOutAnimation.cs │ │ │ ├── SFadeOutShrinkSequence.cs │ │ │ └── SShrinkAnimation.cs │ │ │ ├── Backends │ │ │ └── SGUIIMBackend.cs │ │ │ ├── DFEXT │ │ │ └── SGUIDFInput.cs │ │ │ ├── DotNetEXT │ │ │ ├── AddingNewEventArgs.cs │ │ │ ├── AddingNewEventHandler.cs │ │ │ ├── ICancelAddNew.cs │ │ │ └── IRaiseItemChangedEvents.cs │ │ │ ├── EMouseStatus.cs │ │ │ ├── Elements │ │ │ ├── SButton.cs │ │ │ ├── SGroup.cs │ │ │ ├── SImage.cs │ │ │ ├── SLabel.cs │ │ │ ├── SPreloader.cs │ │ │ ├── SRect.cs │ │ │ ├── STextField.cs │ │ │ └── SWindowTitleBar.cs │ │ │ ├── ISGUIBackend.cs │ │ │ ├── Modifiers │ │ │ ├── SInGameModifier.cs │ │ │ └── SRandomLabelModifier.cs │ │ │ ├── SAnimation.cs │ │ │ ├── SElement.cs │ │ │ ├── SGUIExtensions.cs │ │ │ ├── SGUIRoot.cs │ │ │ └── SModifier.cs │ └── ZipStorer.cs │ ├── GUI │ ├── Backend.cs │ └── Font.cs │ ├── Hooks │ └── RuntimeHooks.cs │ ├── Lua │ ├── Globals.cs │ ├── Hooks.cs │ ├── LuaTool.cs │ └── Triggers.cs │ ├── Menu │ └── Menu.cs │ ├── ModLoader │ ├── AssemblyNameMap.cs │ ├── Metadata.cs │ ├── ModInfo.cs │ └── ModLoader.cs │ ├── ModResources │ ├── LoadedResource.cs │ ├── ModInfoResources.cs │ └── ResourcePool.cs │ ├── ModTheGungeon │ ├── API.cs │ ├── IDMaps.cs │ └── ModTheGungeon.cs │ ├── Notifications │ ├── Animations.cs │ ├── Notification.cs │ └── NotificationController.cs │ ├── Patches │ ├── ModOptions.cs │ ├── patch_MainMenuFoyerController.cs │ ├── patch_dfButton.cs │ ├── patch_dfInputManager.cs │ └── patch_tk2dSpriteDefinition.cs │ └── PrefabricTest.cs ├── Assembly-CSharp.Core.mm ├── Assembly-CSharp.Core.mm.csproj └── src │ ├── Core │ ├── Backend.cs │ ├── Core.cs │ ├── EventHooks.cs │ ├── Logger.cs │ ├── Paths.cs │ └── UnityUtil.cs │ ├── Extensions │ ├── BinaryReader.cs │ └── String.cs │ ├── External │ └── ObjectDumper.cs │ └── Patches │ ├── patch_FoyerPreloader.cs │ ├── patch_GameManager.cs │ └── patch_MainMenuFoyerController.cs ├── Assembly-CSharp.TexMod.mm ├── Assembly-CSharp.TexMod.mm.csproj ├── Properties │ └── AssemblyInfo.cs └── src │ ├── Patches │ ├── DF_Ident │ │ └── patch_MainMenuFoyerController.cs │ ├── patch_GameObject.cs │ ├── patch_dfTextureSprite.cs │ ├── patch_tk2dBaseSprite.cs │ ├── patch_tk2dSpriteAnimator.cs │ └── patch_tk2dSpriteCollectionData.cs │ └── TexMod │ ├── TexMod.cs │ └── TexModExtra.cs ├── ETGModNeo.sln ├── LICENSE_MODTHEGUNGEON ├── LICENSE_MONO ├── Plugins ├── Linux │ ├── 32 │ │ └── liblua5.1.so │ └── 64 │ │ └── liblua5.1.so ├── MacOS │ └── lua5.1.bundle └── Windows │ ├── 32 │ └── lua5.1.dll │ └── 64 │ └── lua5.1.dll ├── README.md ├── Resources ├── bullet.png ├── idmaps │ ├── enemies.txt │ └── items.txt ├── logo.coll.yml ├── logo.png ├── lua │ ├── env.lua │ └── sandbox.lua └── prefabric_test.json ├── UnityEngine.Base.mm ├── Properties │ └── AssemblyInfo.cs ├── UnityEngine.CoreModule.Base.mm.csproj └── src │ ├── Extensions │ └── Texture2DExt.cs │ └── Patches │ └── patch_Resources.cs ├── UnityEngine.Core.mm ├── Properties │ └── AssemblyInfo.cs ├── UnityEngine.CoreModule.Core.mm.csproj └── src │ └── Patches │ └── patch_Logger.cs ├── build-files ├── build.bat ├── build.sh ├── libs ├── Assembly-CSharp.dll ├── Ionic.Zip.dll ├── Mono.Cecil.dll ├── UnityEngine.CoreModule.dll ├── UnityEngine.IMGUIModule.dll ├── UnityEngine.ImageConversionModule.dll ├── UnityEngine.InputModule.dll ├── UnityEngine.TextRenderingModule.dll ├── UnityEngine.UIModule.dll └── UnityEngine.dll └── metadata.yml /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | # *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ 246 | 247 | # Mod the Gungeon build script result 248 | /build/ 249 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libs/YamlDotNet"] 2 | path = libs/YamlDotNet 3 | url = https://github.com/aaubry/YamlDotNet 4 | [submodule "libs/zipstorer"] 5 | path = libs/zipstorer 6 | url = https://github.com/jaime-olivares/zipstorer 7 | [submodule "libs/MonoMod"] 8 | path = libs/MonoMod 9 | url = https://github.com/0x0ade/MonoMod 10 | [submodule "Assembly-CSharp.GUI.mm/src/External/SGUI"] 11 | path = Assembly-CSharp.GUI.mm/src/External/SGUI 12 | url = https://github.com/ModTheGungeon/SGUI 13 | [submodule "ETGModResources/lua/libs/json"] 14 | path = Resources/lua/libs/json 15 | url = https://github.com/rxi/json.lua 16 | [submodule "libs/Logger"] 17 | path = libs/Logger 18 | url = https://github.com/modthegungeon/Logger 19 | [submodule "libs/MicroLua"] 20 | path = libs/MicroLua 21 | url = https://github.com/modthegungeon/MicroLua 22 | [submodule "libs/Prefabric"] 23 | path = libs/Prefabric 24 | url = https://github.com/modthegungeon/Prefabric 25 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("AssemblyCSharp")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | [assembly: AssemblyInformationalVersion("0.1.0-beta2")] 17 | 18 | // The following attributes are used to specify the signing key for the assembly, 19 | // if desired. See the Mono documentation for more information about signing. 20 | 21 | //[assembly: AssemblyDelaySign(false)] 22 | //[assembly: AssemblyKeyFile("")] 23 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/API/Prefab.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace ModTheGungeon.API { 5 | public static class FakePrefab { 6 | public static GameObject Clone(GameObject obj) { 7 | var was_active = obj.activeSelf; 8 | if (was_active) obj.SetActive(false); 9 | var fakeprefab = UnityEngine.Object.Instantiate(obj); 10 | if (was_active) obj.SetActive(true); 11 | return fakeprefab; 12 | } 13 | 14 | public static GameObject Instantiate(GameObject obj) { 15 | var inst = UnityEngine.Object.Instantiate(obj); 16 | inst.SetActive(true); 17 | return inst; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/AutoCompletor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ModTheGungeon.GUI.Console { 5 | public struct AutoCompletionEntry { 6 | public string Label { get; private set; } 7 | public string Content { get; private set; } 8 | 9 | public AutoCompletionEntry(string label, string content) { 10 | Label = label; 11 | Content = content; 12 | } 13 | } 14 | 15 | public class AutoCompletor { 16 | // full_str, current_arg, [return] list of entries 17 | private Func> _Func; 18 | 19 | public AutoCompletor(Func> f) { 20 | _Func = f; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/Command.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ModTheGungeon.GUI.Console { 6 | public class Command { 7 | public string Name { get; protected set; } 8 | public Dictionary SubCommands = new Dictionary(); 9 | public Func, int?, Command, string> Callback { get; private set; } 10 | public AutoCompletor AutoCompletor { get; private set; } 11 | 12 | public string HelpText = ""; 13 | 14 | public Command(string name, Func, int?, Command, string> callback) { 15 | Name = name; 16 | Callback = callback; 17 | } 18 | 19 | public Command(string name, Func, int?, string> callback) 20 | : this(name, (args, histindex, _) => callback(args, histindex)) {} 21 | 22 | public Command(string name, Func, string> callback) 23 | : this(name, (args, _, _2) => callback(args)) {} 24 | 25 | public Command WithHelpText(string text) { 26 | HelpText = text; 27 | return this; 28 | } 29 | 30 | public Command WithSubCommand(Command sub) { 31 | SubCommands[sub.Name] = sub; 32 | return this; 33 | } 34 | 35 | public Command WithSubCommand(string name, Func, int?, Command, string> callback) { 36 | SubCommands[name] = new Command(name, callback); 37 | return this; 38 | } 39 | 40 | public Command WithSubCommand(string name, Func, int?, string> callback) { 41 | SubCommands[name] = new Command(name, callback); 42 | return this; 43 | } 44 | 45 | public Command WithSubCommand(string name, Func, string> callback) { 46 | SubCommands[name] = new Command(name, callback); 47 | return this; 48 | } 49 | 50 | public Command WithSubGroup(Group group) { 51 | SubCommands[group.Name] = group; 52 | return this; 53 | } 54 | 55 | public Command WithSubGroup(string name) { 56 | SubCommands[name] = new Group(name); 57 | return this; 58 | } 59 | 60 | public Command WithAutoCompletor(AutoCompletor completor) { 61 | AutoCompletor = completor; 62 | return this; 63 | } 64 | 65 | public virtual string Run(List args, int? history_index = null) { 66 | return Callback.Invoke(args, history_index, this); 67 | } 68 | } 69 | 70 | public class Group : Command { 71 | public Group(string name) : base(name, (Func, int?, Command, string>)null) {} 72 | 73 | public new Group WithHelpText(string text) { 74 | return (Group)base.WithHelpText(text); 75 | } 76 | 77 | public new Group WithSubCommand(Command sub) { 78 | return (Group)base.WithSubCommand(sub); 79 | } 80 | 81 | public new Group WithSubCommand(string name, Func, int?, Command, string> callback) { 82 | return WithSubCommand(new Command(name, callback)); 83 | } 84 | 85 | public new Group WithSubCommand(string name, Func, int?, string> callback) { 86 | return WithSubCommand(new Command(name, callback)); 87 | } 88 | 89 | public new Group WithSubCommand(string name, Func, string> callback) { 90 | return WithSubCommand(new Command(name, callback)); 91 | } 92 | 93 | public new Group WithSubGroup(Group group) { 94 | return (Group)base.WithSubGroup(group); 95 | } 96 | 97 | public new Group WithSubGroup(string name) { 98 | return WithSubGroup(name); 99 | } 100 | 101 | public new Group WithAutoCompletor(AutoCompletor completor) { 102 | return (Group)base.WithAutoCompletor(completor); 103 | } 104 | 105 | public override string Run(List args, int? history_index = null) { 106 | var b = new StringBuilder(); 107 | b.AppendLine($"Can't execute command group '{Name}'. Did you mean:"); 108 | foreach (var c in SubCommands) { 109 | b.AppendLine($"- {Name}{Console.COMMAND_PATH_SEPARATOR}{c.Key}"); 110 | } 111 | throw new Exception(b.ToString()); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/DualWieldForcer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace ModTheGungeon.GUI.Console { 5 | public class DualWieldForcer : MonoBehaviour { 6 | // 7 | // Fields 8 | // 9 | 10 | public int PartnerGunID; 11 | public PlayerController TargetPlayer; 12 | 13 | public Gun Gun; 14 | private bool m_isCurrentlyActive; 15 | 16 | // 17 | // Methods 18 | // 19 | public void Activate() { 20 | if (EffectValid(TargetPlayer)) { 21 | m_isCurrentlyActive = true; 22 | TargetPlayer.inventory.SetDualWielding(true, "synergy"); 23 | int indexForGun = GetIndexForGun(TargetPlayer, Gun.PickupObjectId); 24 | int indexForGun2 = GetIndexForGun(TargetPlayer, PartnerGunID); 25 | TargetPlayer.inventory.SwapDualGuns(); 26 | if (indexForGun >= 0 && indexForGun2 >= 0) { 27 | while (TargetPlayer.inventory.CurrentGun.PickupObjectId != PartnerGunID) { 28 | TargetPlayer.inventory.ChangeGun(1, false); 29 | } 30 | } 31 | TargetPlayer.inventory.SwapDualGuns(); 32 | if (TargetPlayer.CurrentGun && !TargetPlayer.CurrentGun.gameObject.activeSelf) { 33 | TargetPlayer.CurrentGun.gameObject.SetActive(true); 34 | } 35 | if (TargetPlayer.CurrentSecondaryGun && !TargetPlayer.CurrentSecondaryGun.gameObject.activeSelf) { 36 | TargetPlayer.CurrentSecondaryGun.gameObject.SetActive(true); 37 | } 38 | TargetPlayer.GunChanged += new Action(HandleGunChanged); 39 | } 40 | } 41 | 42 | public void Awake() { 43 | Gun = GetComponent(); 44 | } 45 | 46 | private void CheckStatus() { 47 | if (m_isCurrentlyActive) { 48 | if (!PlayerUsingCorrectGuns() || !EffectValid(TargetPlayer)) { 49 | System.Console.WriteLine("DISABLING EFFECT"); 50 | DisableEffect(); 51 | } 52 | } else if (Gun && Gun.CurrentOwner is PlayerController) { 53 | PlayerController playerController = Gun.CurrentOwner as PlayerController; 54 | if (playerController.inventory.DualWielding && playerController.CurrentSecondaryGun.PickupObjectId == Gun.PickupObjectId && playerController.CurrentGun.PickupObjectId == PartnerGunID) { 55 | m_isCurrentlyActive = true; 56 | TargetPlayer = playerController; 57 | return; 58 | } 59 | Activate(); 60 | } 61 | } 62 | 63 | private void DisableEffect() { 64 | if (m_isCurrentlyActive) { 65 | m_isCurrentlyActive = false; 66 | TargetPlayer.inventory.SetDualWielding(false, "synergy"); 67 | TargetPlayer.GunChanged -= new Action(HandleGunChanged); 68 | TargetPlayer.stats.RecalculateStats(TargetPlayer, false, false); 69 | TargetPlayer = null; 70 | } 71 | } 72 | 73 | private bool EffectValid(PlayerController p) { 74 | if (!p) { 75 | System.Console.WriteLine("NULL PLAYER"); 76 | return false; 77 | } 78 | if (Gun.CurrentAmmo == 0) { 79 | System.Console.WriteLine("CURAMMO 0"); 80 | return false; 81 | } 82 | if (!m_isCurrentlyActive) { 83 | int indexForGun = GetIndexForGun(p, PartnerGunID); 84 | if (indexForGun < 0) { 85 | System.Console.WriteLine("IDX4GUN <0"); 86 | return false; 87 | } 88 | if (p.inventory.AllGuns[indexForGun].CurrentAmmo == 0) { 89 | System.Console.WriteLine("PARTNERAMMO 0"); 90 | return false; 91 | } 92 | } else if (p.CurrentSecondaryGun != null && p.CurrentSecondaryGun.PickupObjectId == PartnerGunID && p.CurrentSecondaryGun.CurrentAmmo == 0) { 93 | System.Console.WriteLine("SECONDARYAMMO 0"); 94 | return false; 95 | } 96 | System.Console.WriteLine("EFFECT VALID"); 97 | return true; 98 | } 99 | 100 | private int GetIndexForGun(PlayerController p, int gunID) { 101 | for (int i = 0; i < p.inventory.AllGuns.Count; i++) { 102 | if (p.inventory.AllGuns[i].PickupObjectId == gunID) { 103 | return i; 104 | } 105 | } 106 | return -1; 107 | } 108 | 109 | private void HandleGunChanged(Gun arg1, Gun newGun, bool arg3) { 110 | CheckStatus(); 111 | } 112 | 113 | private bool PlayerUsingCorrectGuns() { 114 | return Gun && Gun.CurrentOwner && TargetPlayer && TargetPlayer.inventory.DualWielding && (!(TargetPlayer.CurrentGun != Gun) || TargetPlayer.CurrentGun.PickupObjectId == PartnerGunID) && (!(TargetPlayer.CurrentSecondaryGun != Gun) || TargetPlayer.CurrentSecondaryGun.PickupObjectId == PartnerGunID); 115 | } 116 | 117 | private void Update() { 118 | CheckStatus(); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/History.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ModTheGungeon.GUI.Console { 5 | public class CommandHistory { 6 | public List Entries = new List { "" }; 7 | public int CurrentIndex = 0; 8 | 9 | private Parser.Executor _Executor; 10 | private Parser.Parser _Parser; 11 | 12 | public CommandHistory(Parser.Executor exec, Parser.Parser parser) { 13 | _Executor = exec; 14 | _Parser = parser; 15 | } 16 | 17 | public string Execute(int index) { 18 | if (index < 0 || index >= Entries.Count) throw new Exception("Tried to execute command from history at nonexistant index."); 19 | 20 | return _Executor.ExecuteCommand(_Parser.Parse(Entries[index]), index); 21 | } 22 | 23 | public string Entry { 24 | get { 25 | return Entries[CurrentIndex]; 26 | } 27 | set { 28 | Entries[CurrentIndex] = value; 29 | } 30 | } 31 | 32 | public string LastEntry { 33 | get { 34 | return Entries[Entries.Count - 1]; 35 | } 36 | set { 37 | Entries[Entries.Count - 1] = value; 38 | } 39 | } 40 | 41 | public bool IsLastIndex { 42 | get { 43 | return CurrentIndex == Entries.Count - 1; 44 | } 45 | } 46 | 47 | public int LastIndex { 48 | get { 49 | return Entries.Count - 1; 50 | } 51 | } 52 | 53 | public void MoveUp(int n = 1) { 54 | CurrentIndex -= n; 55 | if (CurrentIndex < 0) CurrentIndex = 0; 56 | } 57 | 58 | public void MoveDown(int n = 1) { 59 | CurrentIndex += n; 60 | if (CurrentIndex > Entries.Count - 1) CurrentIndex = Entries.Count - 1; 61 | } 62 | 63 | public void Push() { 64 | if (!IsLastIndex) LastEntry = Entry; 65 | Entries.Add(""); 66 | CurrentIndex = LastIndex; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/Menu.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SGUI; 4 | using UnityEngine; 5 | using ModTheGungeon.GUI; 6 | using System.Text; 7 | 8 | namespace ModTheGungeon.GUI.Console { 9 | public partial class ConsoleMenu : Menu { 10 | public static ConsoleMenu Instance; 11 | 12 | internal SGroup OutputBox { 13 | get { 14 | return (SGroup)Window[(int)WindowChild.OutputBox]; 15 | } 16 | } 17 | internal SGroup AutocompleteBox { 18 | get { 19 | return (SGroup)Window[(int)WindowChild.AutocompleteBox]; 20 | } 21 | } 22 | internal STextField InputBox { 23 | get { 24 | return (STextField)Window[(int)WindowChild.InputBox]; 25 | } 26 | } 27 | 28 | private enum WindowChild { 29 | OutputBox, 30 | AutocompleteBox, 31 | InputBox 32 | } 33 | 34 | public override SElement CreateWindow() { 35 | Instance = this; 36 | var ModTheGungeon = Backend.SearchForBackend("ModTheGungeon"); 37 | 38 | Console.Instance.AddDefaultCommands(); 39 | 40 | return new SGroup { 41 | Background = new Color(0, 0f, 0f, 0.8f), 42 | 43 | OnUpdateStyle = elem => { 44 | elem.Fill(0); 45 | }, 46 | 47 | Children = { 48 | new SGroup { // OutputBox 49 | Background = new Color(0, 0, 0, 0), 50 | AutoLayout = (self) => self.AutoLayoutVertical, 51 | ScrollDirection = SGroup.EDirection.Vertical, 52 | OnUpdateStyle = (elem) => { 53 | elem.Fill(0); 54 | elem.Size -= new Vector2(0, elem.Backend.LineHeight); 55 | }, 56 | Children = { 57 | new SLabel($"ModTheGungeon v{ModTheGungeon.BestMatch?.Instance.StringVersion ?? "?"}") { 58 | Foreground = UnityUtil.NewColorRGB(0, 161, 231), 59 | Modifiers = { 60 | new STest() 61 | } 62 | } 63 | } 64 | }, 65 | new SGroup { // AutocompleteBox 66 | Background = new Color(0.2f, 0.2f, 0.2f, 0.9f), 67 | AutoLayout = (self) => self.AutoLayoutVertical, 68 | ScrollDirection = SGroup.EDirection.Vertical, 69 | OnUpdateStyle = (elem) => { 70 | elem.Size.x = elem.Parent.InnerSize.x; 71 | elem.Size.y = elem.Parent.InnerSize.y / 10; // 10% 72 | elem.Position.y = elem.Parent.InnerSize.y - elem.Parent[(int)WindowChild.InputBox].Size.y - elem.Size.y; 73 | }, 74 | Children = {}, 75 | Visible = false 76 | }, 77 | new STextField { // InputBox 78 | OverrideTab = true, 79 | 80 | OnUpdateStyle = (elem) => { 81 | elem.Size.x = elem.Parent.InnerSize.x; 82 | elem.Position.x = 0; 83 | elem.Position.y = elem.Parent.InnerSize.y - elem.Size.y; 84 | }, 85 | 86 | OnKey = (self, is_down, key) => { 87 | if (!is_down || key == KeyCode.Return || key == KeyCode.KeypadEnter) return; 88 | 89 | switch(key) { 90 | case KeyCode.Home: 91 | self.MoveCursor(0); 92 | break; 93 | case KeyCode.Escape: 94 | case KeyCode.F2: 95 | Hide(); 96 | break; 97 | case KeyCode.Tab: 98 | Console.Instance.DoAutoComplete(); 99 | break; 100 | case KeyCode.UpArrow: 101 | Console.Instance.History.MoveUp(); 102 | self.MoveCursor(Console.Instance.History.Entry.Length); 103 | break; 104 | case KeyCode.DownArrow: 105 | Console.Instance.History.MoveDown(); 106 | self.MoveCursor(Console.Instance.History.Entry.Length); 107 | break; 108 | default: 109 | Console.Instance.History.LastEntry = self.Text; 110 | Console.Instance.History.CurrentIndex = Console.Instance.History.LastIndex; 111 | break; 112 | } 113 | 114 | self.Text = Console.Instance.History.Entry; 115 | }, 116 | 117 | OnSubmit = (elem, text) => { 118 | if (text.Trim().Length == 0) return; 119 | Console.Instance.History.Push(); 120 | if (Console.Instance.LuaMode) { 121 | Console.Instance.ExecuteLuaAndPrintResult(text); 122 | } else { 123 | Console.Instance.ExecuteCommandAndPrintResult(text); 124 | } 125 | } 126 | } 127 | } 128 | }; 129 | } 130 | 131 | public override void OnShow() { 132 | Window[(int)WindowChild.InputBox].Focus(); 133 | } 134 | 135 | public override void OnHide() { 136 | Console.Instance.DiscardAutocomplete(dont_reset_text: true); 137 | Console.Instance.History.LastEntry = Console.Instance.Text = ""; 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/Parser/AST.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ModTheGungeon.GUI.Console.Parser { 6 | public struct Position { 7 | public int FirstLine; 8 | public int LastLine; 9 | public int FirstChar; 10 | public int LastChar; 11 | 12 | public Position(int first_line, int first_char, int last_line, int last_char) { 13 | FirstLine = first_line; 14 | FirstChar = first_char; 15 | LastLine = last_line; 16 | LastChar = last_char; 17 | } 18 | } 19 | 20 | public interface ASTNode { 21 | Position Position { get; } 22 | } 23 | 24 | public struct Argument : ASTNode { 25 | public Position Position { get; } 26 | public List Content; 27 | 28 | public Argument(List content, Position position) { 29 | Position = position; 30 | Content = content; 31 | } 32 | 33 | public override string ToString() { 34 | var builder = new StringBuilder("["); 35 | for (int i = 0; i < Content.Count; i++) { 36 | builder.Append(Content[i].ToString()); 37 | if (i != Content.Count - 1) builder.Append(", "); 38 | } 39 | builder.Append("]"); 40 | 41 | return builder.ToString(); 42 | } 43 | } 44 | 45 | public struct Literal : ASTNode { 46 | public Position Position { get; } 47 | public string Content; 48 | 49 | public Literal(string content, Position position) { 50 | Position = position; 51 | Content = content; 52 | } 53 | 54 | public override string ToString() { 55 | return $"\"{Content}\""; 56 | } 57 | } 58 | 59 | public struct Command : ASTNode { 60 | public Position Position { get; } 61 | public Argument Name; 62 | public List Args; 63 | 64 | public Command(Argument name, List args, Position position) { 65 | Position = position; 66 | Name = name; 67 | Args = args; 68 | } 69 | 70 | public override string ToString() { 71 | var builder = new StringBuilder(Name.ToString()); 72 | builder.Append('('); 73 | for (int i = 0; i < Args.Count; i++) { 74 | builder.Append(Args[i].ToString()); 75 | if (i != Args.Count - 1) builder.Append(", "); 76 | } 77 | builder.Append(')'); 78 | return builder.ToString(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/Parser/Executor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | 5 | namespace ModTheGungeon.GUI.Console.Parser { 6 | public class Executor { 7 | public delegate string ExecFunc(string name, List args, int? history_index); 8 | 9 | public ExecFunc Exec; 10 | 11 | public Executor(ExecFunc exec) { 12 | Exec = exec; 13 | } 14 | 15 | public string EvaluateArgument(Argument arg) { 16 | var builder = new StringBuilder(); 17 | for (int i = 0; i < arg.Content.Count; i++) { 18 | var node = arg.Content[i]; 19 | if (node is Literal) { 20 | builder.Append(((Literal)node).Content); 21 | } else if (node is Command) { 22 | builder.Append(ExecuteCommand((Command)node) ?? ""); 23 | } 24 | } 25 | return builder.ToString(); 26 | } 27 | 28 | public string ExecuteCommand(Command cmd, int? history_index = null) { 29 | var name = EvaluateArgument(cmd.Name); 30 | var args = new List(); 31 | for (int i = 0; i < cmd.Args.Count; i++) { 32 | args.Add(EvaluateArgument(cmd.Args[i])); 33 | } 34 | 35 | 36 | return Exec.Invoke(name, args, history_index); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/Parser/Parser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ModTheGungeon.GUI.Console.Parser { 6 | public class Parser { 7 | public class ParserException : Exception { 8 | public Token? Token { set; get; } = null; 9 | 10 | public ParserException(Token token, string msg) : base($"[{token.PositionInfo} {token.Type}] {msg}") { 11 | Token = token; 12 | } 13 | 14 | public ParserException(string msg) : base(msg) {} 15 | } 16 | 17 | private Lexer _Lexer = new Lexer(); 18 | private Token _Token; 19 | private bool _Lenient = false; 20 | 21 | public Command Parse(string cmd, bool lenient = false) { 22 | _Lenient = lenient; 23 | _Lexer.Reset(cmd); 24 | _NextToken(); 25 | return _ReadCommand(); 26 | } 27 | 28 | private void _NextToken() { 29 | _Token = _Lexer.NextToken(); 30 | } 31 | 32 | private ParserException _Error(string msg) { 33 | return new ParserException(_Token, msg); 34 | } 35 | 36 | private Command _ReadCommand() { 37 | var pos = new Position(); 38 | 39 | pos.FirstChar = _Token.FirstCharacter; 40 | pos.FirstLine = _Token.FirstLine; 41 | _NextToken(); 42 | 43 | var args = new List(); 44 | Argument name = default(Argument); 45 | 46 | var no_name_yet = true; 47 | while (_Token.Type != TokenType.CommandEnd) { 48 | if (_Token.Type == TokenType.Separator) _NextToken(); 49 | if (no_name_yet) { 50 | name = _ReadArgument(); 51 | no_name_yet = false; 52 | } else args.Add(_ReadArgument()); 53 | } 54 | 55 | if (no_name_yet) throw new ParserException("No command provided"); 56 | 57 | pos.LastChar = _Token.LastCharacter; 58 | pos.LastLine = _Token.LastLine; 59 | _NextToken(); 60 | 61 | return new Command(name, args, pos); 62 | } 63 | 64 | private Literal _ReadLiteral() { 65 | if (!_Lenient && _Token.LiteralInfo?.IsTerminated == false) { 66 | throw new ParserException(_Token, $"Unterminated quote ('{_Token.LiteralInfo.QuoteChar}')"); 67 | } 68 | var content = _Token.Content; 69 | var pos = new Position(_Token.FirstLine, _Token.FirstCharacter, _Token.LastLine, _Token.LastCharacter); 70 | _NextToken(); 71 | return new Literal(content, pos); 72 | } 73 | 74 | private Argument _ReadArgument() { 75 | var content = new List(); 76 | 77 | while (_Token.Type != TokenType.Separator && _Token.Type != TokenType.CommandEnd) { 78 | if (_Token.Type == TokenType.CommandStart) { 79 | content.Add(_ReadCommand()); 80 | } else if (_Token.Type == TokenType.Literal) { 81 | content.Add(_ReadLiteral()); 82 | } 83 | } 84 | 85 | var first_line = content.Count == 0 ? 0 : content[0].Position.FirstLine; 86 | var first_char = content.Count == 0 ? 0 : content[0].Position.FirstChar; 87 | var last_line = content.Count == 0 ? 0 : content[content.Count - 1].Position.LastLine; 88 | var last_char = content.Count == 0 ? 0 : content[content.Count - 1].Position.LastChar; 89 | 90 | return new Argument(content, new Position(first_line, first_char, last_line, last_char)); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Console/Parser/Token.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ModTheGungeon.GUI.Console.Parser { 6 | public enum TokenType { 7 | CommandStart, 8 | CommandEnd, 9 | Separator, 10 | Literal 11 | } 12 | 13 | public enum QuoteType { 14 | Normal, 15 | Verbatim 16 | } 17 | 18 | public class LiteralInfo { 19 | public QuoteType QuoteType; 20 | public bool IsTerminated = true; 21 | 22 | public char QuoteChar { 23 | get { 24 | switch(QuoteType) { 25 | case QuoteType.Normal: return '"'; 26 | case QuoteType.Verbatim: return '{'; 27 | } 28 | return '?'; 29 | } 30 | } 31 | } 32 | 33 | public struct Token { 34 | public TokenType Type; 35 | public string Content; 36 | public LiteralInfo LiteralInfo; 37 | public bool IsFinalToken; 38 | 39 | public int FirstLine; 40 | public int FirstCharacter; 41 | public int LastLine; 42 | public int LastCharacter; 43 | 44 | public string PositionInfo { 45 | get { 46 | if (FirstLine == LastLine && FirstCharacter == LastCharacter) { 47 | return $"{FirstLine}:{FirstCharacter}"; 48 | } else { 49 | return $"{FirstLine}:{FirstCharacter}-{LastLine}:{LastCharacter}"; 50 | } 51 | } 52 | } 53 | 54 | public Token(TokenType type, string content, int first_line, int first_character, int last_line, int last_character) { 55 | IsFinalToken = false; 56 | LiteralInfo = null; 57 | FirstLine = first_line; 58 | FirstCharacter = first_character; 59 | LastLine = last_line; 60 | LastCharacter = last_character; 61 | Type = type; 62 | Content = content; 63 | } 64 | 65 | public static string EscapeNormal(string s) { 66 | var builder = new StringBuilder(); 67 | for (int i = 0; i < s.Length; i++) { 68 | var c = s[i]; 69 | switch(c) { 70 | case '\n': builder.Append("\\n"); break; 71 | case '\t': builder.Append("\\t"); break; 72 | case '"': builder.Append("\\\""); break; 73 | case '\\': builder.Append("\\\\"); break; 74 | default: builder.Append(c); break; 75 | } 76 | } 77 | return builder.ToString(); 78 | } 79 | 80 | public static string EscapeVerbatim(string s) { 81 | var builder = new StringBuilder(); 82 | for (int i = 0; i < s.Length; i++) { 83 | var c = s[i]; 84 | switch (c) { 85 | case '}': builder.Append("\\}"); break; 86 | case '\\': builder.Append("\\\\"); break; 87 | default: builder.Append(c); break; 88 | } 89 | } 90 | return builder.ToString(); 91 | } 92 | 93 | public static string EscapeUnquoted(string s) { 94 | var builder = new StringBuilder(); 95 | for (int i = 0; i < s.Length; i++) { 96 | var c = s[i]; 97 | if (Array.IndexOf(Lexer.SPECIAL_UNQUOTED_LITERAL_CHARS, c) != -1) { 98 | builder.Append("\\"); 99 | } 100 | builder.Append(c); 101 | } 102 | return builder.ToString(); 103 | } 104 | 105 | public override string ToString() { 106 | if (Type == TokenType.Literal) { 107 | if (LiteralInfo == null) return EscapeUnquoted(Content); 108 | switch (LiteralInfo.QuoteType) { 109 | //FIXME unterminated strings 110 | case QuoteType.Normal: return $"\"{EscapeNormal(Content)}\""; 111 | case QuoteType.Verbatim: return $"\"{EscapeVerbatim(Content)}\""; 112 | } 113 | } 114 | return Content; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/.gitignore: -------------------------------------------------------------------------------- 1 | *.meta 2 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/README.md: -------------------------------------------------------------------------------- 1 | #SGUI - Scripted GUI 2 | ### Editor - and mod - compatible Unity GUI "framework" using IMGUI 3 | ##### MIT-licensed 4 | ---- 5 | 6 | # WIP 7 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Animations/SAnimationSequence.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SAnimationSequence : SAnimation { 6 | public List Sequence = new List(); 7 | 8 | protected float[] _Offsets; 9 | 10 | protected int _CurrentIndex; 11 | public int CurrentIndex { 12 | get { 13 | return _CurrentIndex; 14 | } 15 | } 16 | public SAnimation Current { 17 | get { 18 | return _CurrentIndex < 0 || Sequence.Count <= _CurrentIndex ? null : Sequence[_CurrentIndex]; 19 | } 20 | } 21 | public float CurrentOffset { 22 | get { 23 | return _CurrentIndex < 0 || Sequence.Count <= _CurrentIndex ? 0f : _Offsets[_CurrentIndex]; 24 | } 25 | } 26 | public EStatus CurrentStatus { 27 | get { 28 | return _CurrentIndex < 0 || Sequence.Count <= _CurrentIndex ? EStatus.Finished : Sequence[_CurrentIndex].Status; 29 | } 30 | } 31 | 32 | public SAnimationSequence() 33 | : base(0f) { 34 | } 35 | 36 | public override void OnStart() { 37 | Duration = 0f; 38 | _CurrentIndex = 0; 39 | 40 | _Offsets = new float[Sequence.Count]; 41 | for (int i = 0; i < Sequence.Count; i++) { 42 | SAnimation anim = Sequence[i]; 43 | if (anim == null) continue; 44 | _Offsets[i] = Duration; 45 | Duration += anim.Duration; 46 | anim.Loop = false; 47 | anim.AutoStart = false; 48 | anim.Elem = anim.Elem ?? Elem; 49 | anim.Init(); 50 | } 51 | 52 | Current.Start(); 53 | } 54 | 55 | public override void Animate(float t) { 56 | if (CurrentStatus == EStatus.Finished) { 57 | if (Current != null) Current.End(); 58 | _CurrentIndex++; 59 | if (Current != null) Current.Start(); 60 | } 61 | 62 | if (Current == null) return; 63 | 64 | t = ((t * Duration) - CurrentOffset) / Current.Duration; 65 | Current.Animate(Current.Easing(t)); 66 | if (t >= 1f) Current.End(); 67 | } 68 | 69 | public override void OnEnd() { 70 | base.OnEnd(); 71 | if (Current != null) Current.End(); 72 | _CurrentIndex = 0; 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Animations/SFadeAnimation.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using UnityEngine; 3 | using System.Linq.Expressions; 4 | using System.Linq; 5 | 6 | namespace SGUI { 7 | public abstract class SFadeAnimation : SAnimation { 8 | 9 | public SFadeAnimation() 10 | : this(0.3f) { 11 | } 12 | 13 | public SFadeAnimation(float duration) 14 | : base(duration) { 15 | } 16 | 17 | public Color[] OrigColors; 18 | 19 | public override void OnInit() { 20 | OrigColors = new Color[Elem.Colors.Length]; 21 | Elem.Colors.CopyTo(OrigColors, 0); 22 | } 23 | 24 | public abstract void CopyTo(SElement elem); 25 | 26 | public override void OnStart() { 27 | for (int i = 0; i < Elem.Children.Count; i++) { 28 | CopyTo(Elem.Children[i]); 29 | } 30 | } 31 | 32 | public override void Animate(float t) { 33 | for (int i = 0; i < OrigColors.Length; i++) { 34 | Elem.Colors[i] = Animate(t, OrigColors[i]); 35 | } 36 | } 37 | 38 | public abstract Color Animate(float t, Color c); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Animations/SFadeInAnimation.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SFadeInAnimation : SFadeAnimation { 6 | 7 | public SFadeInAnimation() 8 | : this(0.3f) { 9 | } 10 | 11 | public SFadeInAnimation(float duration) 12 | : base(duration) { 13 | } 14 | 15 | public override Color Animate(float t, Color c) { 16 | c.a *= t; 17 | return c; 18 | } 19 | 20 | public override void CopyTo(SElement elem) { 21 | elem.Modifiers.Add(new SFadeInAnimation(Duration)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Animations/SFadeOutAnimation.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SFadeOutAnimation : SFadeAnimation { 6 | 7 | public SFadeOutAnimation() 8 | : this(0.3f) { 9 | } 10 | 11 | public SFadeOutAnimation(float duration) 12 | : base(duration) { 13 | } 14 | 15 | public override Color Animate(float t, Color c) { 16 | c.a *= 1f - t; 17 | return c; 18 | } 19 | 20 | public override void CopyTo(SElement elem) { 21 | elem.Modifiers.Add(new SFadeOutAnimation(Duration)); 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Animations/SFadeOutShrinkSequence.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SFadeOutShrinkSequence : SAnimationSequence { 6 | 7 | public SFadeOutAnimation FadeOut; 8 | public SShrinkAnimation Shrink; 9 | 10 | public float FadeOutDuration; 11 | public float ShrinkDuration; 12 | 13 | public SFadeOutShrinkSequence() 14 | : this(0.3f, 0.5f) { 15 | } 16 | public SFadeOutShrinkSequence(float durationFadeOut, float durationShrink) { 17 | FadeOutDuration = durationFadeOut; 18 | ShrinkDuration = durationShrink; 19 | } 20 | 21 | public override void OnStart() { 22 | if (FadeOut == null) { 23 | Sequence.Insert(0, FadeOut = new SFadeOutAnimation(FadeOutDuration)); 24 | } 25 | 26 | if (Shrink == null) { 27 | Sequence.Add(Shrink = new SShrinkAnimation(ShrinkDuration)); 28 | } 29 | 30 | base.OnStart(); 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Animations/SShrinkAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using UnityEngine; 4 | 5 | namespace SGUI { 6 | public class SShrinkAnimation : SAnimation { 7 | 8 | public SShrinkAnimation() 9 | : this(0.3f) { 10 | } 11 | public SShrinkAnimation(float duration) 12 | : base(duration) { 13 | } 14 | 15 | protected Vector2 _OriginalSize; 16 | 17 | public override void OnInit() { 18 | AutoStart = false; 19 | Elem.UpdateBounds = false; 20 | } 21 | 22 | public override void OnStart() { 23 | Loop = false; 24 | 25 | _OriginalSize = Elem.Size; 26 | } 27 | 28 | public override void Animate(float t) { 29 | Elem.Size = _OriginalSize * (1f - t); 30 | if (Elem.Parent != null) Elem.Parent.UpdateStyle(); 31 | } 32 | 33 | public override void OnEnd() { 34 | Elem.Remove(); 35 | base.OnEnd(); 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/DFEXT/SGUIDFInput.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | #if SGUI_DaikonForge 6 | public class SGUIDFInput : IInputAdapter { 7 | 8 | protected readonly static Vector2 NULLV2 = new Vector2(-1, -1); 9 | 10 | public readonly IInputAdapter Base; 11 | private ISGUIBackend _Backend; 12 | public ISGUIBackend Backend { 13 | get { 14 | return _Backend ?? SGUIRoot.Main?.Backend; 15 | } 16 | set { 17 | _Backend = value; 18 | } 19 | } 20 | 21 | public SGUIDFInput(IInputAdapter @base) { 22 | Base = @base; 23 | if (@base == null) { 24 | throw new NullReferenceException("SDGUIFInput cannot be instantiated without base input!"); 25 | } 26 | } 27 | 28 | public bool GetKeyDown(KeyCode key) { 29 | if (Backend != null && Backend.LastKeyEventConsumed) { 30 | return false; 31 | } 32 | return Base.GetKeyDown(key); 33 | } 34 | 35 | public bool GetKeyUp(KeyCode key) { 36 | if (Backend != null && Backend.LastKeyEventConsumed) { 37 | return false; 38 | } 39 | return Base.GetKeyUp(key); 40 | } 41 | 42 | public float GetAxis(string axisName) { 43 | return Base.GetAxis(axisName); 44 | } 45 | 46 | public Vector2 GetMousePosition() { 47 | if (Backend != null && Backend.LastMouseEventConsumed) { 48 | return NULLV2; 49 | } 50 | return Base.GetMousePosition(); 51 | } 52 | 53 | public bool GetMouseButton(int button) { 54 | if (Backend != null && Backend.LastMouseEventConsumed) { 55 | return false; 56 | } 57 | return Base.GetMouseButton(button); 58 | } 59 | 60 | public bool GetMouseButtonDown(int button) { 61 | if (Backend != null && Backend.LastMouseEventConsumed) { 62 | return false; 63 | } 64 | return Base.GetMouseButtonDown(button); 65 | } 66 | 67 | public bool GetMouseButtonUp(int button) { 68 | if (Backend != null && Backend.LastMouseEventConsumed) { 69 | return true; 70 | } 71 | return Base.GetMouseButtonUp(button); 72 | } 73 | 74 | } 75 | #endif 76 | } 77 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/DotNetEXT/AddingNewEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | using System.Security.Permissions; 8 | 9 | namespace System.ComponentModel 10 | { 11 | /// 12 | /// Provides data for an event that signals the adding of a new object 13 | /// to a list, allowing any event handler to supply the new object. If 14 | /// no event handler supplies a new object to use, the list should create 15 | /// one itself. 16 | /// 17 | public class AddingNewEventArgs : EventArgs 18 | { 19 | private object _newObject = null; 20 | 21 | /// 22 | /// Initializes a new instance of the class, 23 | /// with no new object defined. 24 | /// 25 | public AddingNewEventArgs() : base() 26 | { 27 | } 28 | 29 | /// 30 | /// Initializes a new instance of the class, 31 | /// with the specified object defined as the default new object. 32 | /// 33 | public AddingNewEventArgs(object newObject) : base() 34 | { 35 | _newObject = newObject; 36 | } 37 | 38 | /// 39 | /// Gets or sets the new object that will be added to the list. 40 | /// 41 | public object NewObject 42 | { 43 | get 44 | { 45 | return _newObject; 46 | } 47 | 48 | set 49 | { 50 | _newObject = value; 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/DotNetEXT/AddingNewEventHandler.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | using System.Security.Permissions; 8 | 9 | namespace System.ComponentModel 10 | { 11 | /// 12 | /// Represents the method that will handle the AddingNew event on a list, 13 | /// and provide the new object to be added to the list. 14 | /// 15 | public delegate void AddingNewEventHandler(object sender, AddingNewEventArgs e); 16 | } 17 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/DotNetEXT/ICancelAddNew.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace System.ComponentModel 8 | { 9 | /// 10 | /// Interface implemented by a list that allows the addition of a new item 11 | /// to be either cancelled or committed. 12 | /// 13 | /// Note: In some scenarios, specifically Windows Forms complex data binding, 14 | /// the list may recieve CancelNew or EndNew calls for items other than the 15 | /// new item. These calls should be ignored, ie. the new item should only be 16 | /// cancelled or committed when that item's index is specified. 17 | /// 18 | public interface ICancelAddNew 19 | { 20 | /// 21 | /// If a new item has been added to the list, and is the position of that item, 22 | /// then this method should remove it from the list and cancel the add operation. 23 | /// 24 | void CancelNew(int itemIndex); 25 | 26 | /// 27 | /// If a new item has been added to the list, and is the position of that item, 28 | /// then this method should leave it in the list and complete the add operation. 29 | /// 30 | void EndNew(int itemIndex); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/DotNetEXT/IRaiseItemChangedEvents.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.ComponentModel 6 | { 7 | public interface IRaiseItemChangedEvents 8 | { 9 | /// 10 | /// 11 | bool RaisesItemChangedEvents { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/EMouseStatus.cs: -------------------------------------------------------------------------------- 1 | namespace SGUI { 2 | public enum EMouseStatus { 3 | Outside, 4 | Inside, 5 | Up, 6 | Down, 7 | Drag 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/SButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SButton : SElement { 6 | 7 | public string Text; 8 | public Texture Icon; 9 | 10 | public Vector2 IconScale = Vector2.one; 11 | public Color IconColor { 12 | get { 13 | return Colors[1]; 14 | } 15 | set { 16 | Colors[1] = value; 17 | } 18 | } 19 | 20 | public TextAnchor Alignment = TextAnchor.MiddleCenter; 21 | 22 | public Vector2 Border = new Vector2(4f, 4f); 23 | 24 | public Action OnClick; 25 | 26 | public bool StatusPrev { get; protected set; } 27 | public bool Status { get; protected set; } 28 | 29 | public override bool IsInteractive { 30 | get { 31 | return true; 32 | } 33 | } 34 | 35 | public bool IsClicked { get; protected set; } 36 | 37 | public SButton() 38 | : this("") { } 39 | public SButton(string text) { 40 | Text = text; 41 | ColorCount = 3; 42 | IconColor = Color.white; 43 | } 44 | 45 | public override void UpdateStyle() { 46 | // This will get called again once this element gets added to the root. 47 | if (Root == null) return; 48 | 49 | if (UpdateBounds) { 50 | float iconWidth = Icon == null ? 0 : Icon.width * IconScale.x + 1f + Backend.IconPadding; 51 | if (Parent == null) { 52 | Size = Backend.MeasureText(ref Text, font: Font); 53 | } else { 54 | Size = Backend.MeasureText(ref Text, Parent.InnerSize.x - Border.x * 2f - iconWidth, font: Font); 55 | } 56 | if (Icon != null) { 57 | Size.y = Mathf.Max(Size.y, Icon.height * IconScale.y + Backend.IconPadding); 58 | } 59 | Size = new Vector2(Size.x + iconWidth, Size.y); 60 | Size += Border * 2f; 61 | } 62 | 63 | base.UpdateStyle(); 64 | } 65 | 66 | public override void RenderBackground() { } 67 | public override void Render() { 68 | // Do not render background - background should be handled by Draw.Button 69 | 70 | Draw.Button(this, Vector2.zero, Size, Text, Alignment, Icon); 71 | } 72 | 73 | public override void MouseStatusChanged(EMouseStatus e, Vector2 pos) { 74 | base.MouseStatusChanged(e, pos); 75 | 76 | if (e == EMouseStatus.Down) { 77 | IsClicked = true; 78 | } 79 | if (e == EMouseStatus.Up && IsClicked) { 80 | if (OnClick != null) OnClick(this); 81 | IsClicked = false; 82 | } 83 | if (e == EMouseStatus.Outside) { 84 | IsClicked = false; 85 | } 86 | } 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/SImage.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace SGUI { 4 | public class SImage : SElement { 5 | 6 | public Texture Texture; 7 | 8 | public SImage() 9 | : this(null) { } 10 | public SImage(Texture texture) 11 | : this(texture, Color.white) { } 12 | public SImage(Texture texture, Color color) { 13 | Texture = texture; 14 | ColorCount = 1; 15 | Foreground = color; 16 | } 17 | 18 | public override void UpdateStyle() { 19 | // This will get called again once this element gets added to the root. 20 | if (Root == null) return; 21 | 22 | if (UpdateBounds && Texture != null) { 23 | Size = new Vector2(Texture.width, Texture.height); 24 | } 25 | 26 | base.UpdateStyle(); 27 | } 28 | 29 | public override void Render() { 30 | Draw.Texture(this, Vector2.zero, Size, Texture, Foreground); 31 | 32 | RenderChildren(); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/SLabel.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace SGUI { 4 | public class SLabel : SElement { 5 | 6 | public string Text; 7 | public Texture Icon; 8 | public FontStyle FontStyle = FontStyle.Normal; 9 | 10 | public Vector2 IconScale = Vector2.one; 11 | public Color IconColor { 12 | get { 13 | return Colors[1]; 14 | } 15 | set { 16 | Colors[1] = value; 17 | } 18 | } 19 | 20 | public TextAnchor Alignment = TextAnchor.MiddleLeft; 21 | 22 | public SLabel() 23 | : this("") { } 24 | public SLabel(string text) { 25 | Text = text; 26 | ColorCount = 3; 27 | IconColor = UnityEngine.Color.white; 28 | Background = Background * 0f; 29 | } 30 | 31 | public override void UpdateStyle() { 32 | // This will get called again once this element gets added to the root. 33 | if (Root == null) return; 34 | 35 | if (UpdateBounds) { 36 | if (Parent == null) { 37 | Size = Backend.MeasureText(ref Text); 38 | } else { 39 | Size = Backend.MeasureText(ref Text, Parent.InnerSize.x - (Icon == null ? 0 : Icon.width * IconScale.x + 1f + Backend.IconPadding), font: Font); 40 | } 41 | if (Icon != null) { 42 | Size.y = Mathf.Max(Size.y, Icon.height * IconScale.y + Backend.IconPadding); 43 | } 44 | } 45 | 46 | base.UpdateStyle(); 47 | } 48 | 49 | public override void Render() { 50 | RenderBackground(); 51 | Draw.Text(this, Vector2.zero, Size, Text, Alignment, Icon, Foreground); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/SPreloader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SPreloader : SElement { 6 | 7 | public Vector2 IndividualSize = new Vector2(1f, 1f); 8 | public Vector2 Padding = new Vector2(0f, 0f); 9 | public Vector2 Count = new Vector2(32, 32); 10 | 11 | public bool IsCentered = true; 12 | 13 | public Func Function = DefaultFunction; 14 | 15 | public override Vector2 InnerSize { 16 | get { 17 | return new Vector2( 18 | (IndividualSize.x + Padding.x) * Count.x - Padding.x, 19 | (IndividualSize.y + Padding.y) * Count.y - Padding.y 20 | ); 21 | } 22 | } 23 | 24 | public override Vector2 InnerOrigin { 25 | get { 26 | if (!IsCentered) { 27 | return base.InnerOrigin; 28 | } 29 | return base.InnerOrigin + Size * 0.5f - InnerSize * 0.5f; 30 | } 31 | } 32 | 33 | public float TimeStart; 34 | 35 | public SPreloader() 36 | : this(Color.white) { } 37 | public SPreloader(Color color) { 38 | ColorCount = 1; 39 | Foreground = color; 40 | TimeStart = SGUIRoot.TimeUnscaled; 41 | } 42 | 43 | public override void UpdateStyle() { 44 | // This will get called again once this element gets added to the root. 45 | if (Root == null) return; 46 | 47 | if (UpdateBounds) { 48 | Size = InnerSize; 49 | if (Parent != null) Size.x = Parent.InnerSize.x; 50 | } 51 | 52 | base.UpdateStyle(); 53 | } 54 | 55 | public override void Render() { 56 | float t = SGUIRoot.TimeUnscaled - TimeStart; 57 | float dx = IndividualSize.x + Padding.x; 58 | float dy = IndividualSize.y + Padding.y; 59 | for (int y = 0; y < Count.y; y++) { 60 | for (int x = 0; x < Count.x; x++) { 61 | Color color = Foreground; 62 | color.a *= Function((x + 0.5f) / Count.x, (y + 0.5f) / Count.y, t); 63 | Draw.Texture(this, new Vector2( 64 | dx * x, 65 | dy * y 66 | ), IndividualSize, SGUIRoot.White, color); 67 | } 68 | } 69 | } 70 | 71 | internal readonly static Vector2 _V2_05_05 = new Vector2(0.5f, 0.5f); 72 | internal static float _PSIN(float a) { return 0.5f + 0.5f * Mathf.Sin(a); } 73 | internal static float _SmoothStep(float a, float b, float x) { 74 | float t = Mathf.Clamp01((x - a) / (b - a)); 75 | return t * t * (3f - (2f * t)); 76 | } 77 | internal static float _SS(float s, float r, float v) { return _SmoothStep(s - r , s + r , v); } 78 | internal static float _SS(float s, float v ) { return _SmoothStep(s - 0.02f, s + 0.02f, v); } 79 | 80 | 81 | internal static float _Circle(Vector2 xy, float or, float ir) { 82 | float r = (xy - _V2_05_05).magnitude; 83 | return (1f - _SS(or, r)) * _SS(or - ir, r); 84 | } 85 | 86 | public static float LoadRot(Vector2 xy, float f) { 87 | f = ((f * 0.5f) % 1f) * -Mathf.PI * 2f; 88 | xy -= _V2_05_05; 89 | xy /= xy.magnitude; 90 | return _SS(0.5f, xy.x * Mathf.Cos(f) + xy.y * Mathf.Sin(f)); 91 | } 92 | 93 | public static float LoadJump(Vector2 xy, float f) { 94 | f = (f % 1f) * 2f - 2f; 95 | xy -= _V2_05_05; 96 | xy /= xy.magnitude; 97 | 98 | float rf = 0f; 99 | float ss = 0f; 100 | 101 | rf += _SS(ss, xy.y * Mathf.Cos(Mathf.PI * Mathf.Min(0f, f))); 102 | rf += _SS(ss, xy.x * Mathf.Sin(Mathf.PI * Mathf.Min(0.5f, f))); 103 | rf += _SS(ss, -xy.y * -Mathf.Cos(Mathf.PI * Mathf.Min(1f, f))); 104 | rf += _SS(ss, -xy.x * -Mathf.Sin(Mathf.PI * Mathf.Min(1.5f, f))); 105 | 106 | return 1f - Mathf.Clamp01(rf); 107 | } 108 | 109 | public static float DefaultFunction(float x, float y, float t) { 110 | y = 1f - y; 111 | Vector2 xy = new Vector2(x, y); 112 | float a = _Circle(xy, 0.45f, 0.1f); 113 | 114 | a *= Mathf.Abs(LoadRot(xy, t)); 115 | 116 | return a; 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/SRect.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace SGUI { 4 | public class SRect : SElement { 5 | 6 | public bool Filled = true; 7 | public float Thickness = 1f; 8 | 9 | public SRect() 10 | : this(Color.white) { } 11 | public SRect(Color color) { 12 | ColorCount = 1; 13 | Foreground = color; 14 | } 15 | 16 | public override void UpdateStyle() { 17 | // This will get called again once this element gets added to the root. 18 | if (Root == null) return; 19 | 20 | base.UpdateStyle(); 21 | } 22 | 23 | public override void Render() { 24 | if (Filled) { 25 | Draw.Rect(this, Vector2.zero, Size, Foreground); 26 | } else { 27 | Draw.Rect(this, new Vector2(0f, 0f), new Vector2(Thickness, Size.y), Foreground); 28 | Draw.Rect(this, new Vector2(Thickness, 0f), new Vector2(Size.x - Thickness, Thickness), Foreground); 29 | Draw.Rect(this, new Vector2(Size.x - 1f - Thickness, Thickness), new Vector2(Thickness, Size.y - Thickness), Foreground); 30 | Draw.Rect(this, new Vector2(Thickness, Size.y - 1f - Thickness), new Vector2(Size.x - Thickness * 2f, Thickness), Foreground); 31 | } 32 | 33 | RenderChildren(); 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/STextField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class STextField : SElement { 6 | 7 | public string Text; 8 | public string TextOnSubmit = ""; 9 | 10 | public bool OverrideTab; 11 | 12 | public Action OnTextUpdate; 13 | public Action OnKey; 14 | public Action OnSubmit; 15 | 16 | public override bool IsInteractive { 17 | get { 18 | return true; 19 | } 20 | } 21 | 22 | public int CursorIndex { get; protected set; } 23 | public int SelectionIndex { get; protected set; } 24 | 25 | protected int? _MoveCursorIndex; 26 | protected int? _MoveSelectionIndex; 27 | 28 | public STextField() 29 | : this("") { } 30 | public STextField(string text) { 31 | Text = text; 32 | Background = Color.white; 33 | Foreground = Color.black; 34 | } 35 | 36 | public override void UpdateStyle() { 37 | // This will get called again once this element gets added to the root. 38 | if (Root == null) return; 39 | 40 | if (UpdateBounds) { 41 | Size.y = Backend.LineHeight; 42 | } 43 | 44 | base.UpdateStyle(); 45 | } 46 | 47 | public override void RenderBackground() { } 48 | public override void Render() { 49 | // Do not render background - background should be handled by Draw.TextField 50 | 51 | Draw.TextField(this, Vector2.zero, Size, ref Text); 52 | 53 | if (_MoveCursorIndex != null || _MoveSelectionIndex != null) { 54 | Backend.MoveTextFieldCursor(this, ref _MoveCursorIndex, ref _MoveSelectionIndex); 55 | } 56 | 57 | // Focusing should happen when the element has got a valid ID (after rendering the element) and after checking for it. 58 | if (_ScheduleFocus) { 59 | _ScheduleFocus = false; 60 | Backend.Focus(this); 61 | } 62 | } 63 | 64 | protected bool _ScheduleFocus; 65 | public override void Focus() { 66 | _ScheduleFocus = true; 67 | } 68 | 69 | public void MoveCursor(int cursor, int? selection = null) { 70 | _MoveCursorIndex = cursor; 71 | _MoveSelectionIndex = selection; 72 | } 73 | 74 | public void SetCursorIndex(int secret, int cursor, int select) { 75 | Backend.VerifySecret(secret); 76 | CursorIndex = cursor; 77 | SelectionIndex = select; 78 | } 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Elements/SWindowTitleBar.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace SGUI { 4 | public class SWindowTitleBar : SElement { 5 | 6 | public bool Dragging; 7 | 8 | public SWindowTitleBar() { 9 | ColorCount = 1; 10 | Background = Background * 2f; 11 | 12 | Children.Add(new SButton { 13 | 14 | }); 15 | } 16 | 17 | public override void UpdateStyle() { 18 | // This will get called again once this element gets added to the root. 19 | if (Root == null) return; 20 | 21 | Size = new Vector2( 22 | Parent.Size.x + ((SGroup) Parent).Border * 2f, 23 | Backend.LineHeight 24 | ); 25 | Position = Vector2.zero; 26 | 27 | base.UpdateStyle(); 28 | 29 | float x = Size.x; 30 | for (int i = 0; i < Children.Count; i++) { 31 | SElement child = Children[i]; 32 | x -= child.Size.x; 33 | child.Position.x = x; 34 | } 35 | } 36 | 37 | public override void RenderBackground() { 38 | // Backend renders background. 39 | } 40 | public override void Render() { 41 | // Handle title, buttons, dragging and other backend-specific window title bar magic. 42 | Draw.WindowTitleBar(this); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Modifiers/SInGameModifier.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | #if SGUI_EtG 6 | public class SInGameModifier : SModifier { 7 | 8 | public bool ChangeVisible = false; 9 | public bool ChangeEnabled = false; 10 | 11 | public override void Init() { 12 | ChangeVisible |= Elem.Visible; 13 | ChangeEnabled |= Elem.Enabled; 14 | } 15 | 16 | public override void Update() { 17 | if (ChangeVisible) { 18 | Elem.Visible = GameManager.Instance.IsPaused; 19 | } 20 | if (ChangeEnabled) { 21 | Elem.Enabled = GameManager.Instance.IsPaused; 22 | } 23 | } 24 | 25 | } 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/Modifiers/SRandomLabelModifier.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public class SRandomLabelModifier : SModifier { 6 | 7 | public override void Update() { 8 | if (Random.value > 0.1f) { 9 | return; 10 | } 11 | SLabel label = (SLabel) Elem; 12 | string orig = label.Text; 13 | StringBuilder repl = new StringBuilder(); 14 | while (orig.Length > 0) { 15 | int i = Random.Range(0, orig.Length); 16 | char c = orig[i]; 17 | repl.Append(c); 18 | orig = orig.Remove(i, 1); 19 | } 20 | label.Text = repl.ToString(); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/SAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace SGUI { 5 | public abstract class SAnimation : SModifier { 6 | 7 | public float TimeStart; 8 | public EStatus Status = EStatus.Uninitialized; 9 | 10 | public float Duration; 11 | 12 | public bool SpeedUnscaled = true; 13 | public bool AutoStart = true; 14 | public bool Loop = false; 15 | public bool Paused = false; 16 | 17 | public Func Easing = SEasings.SineEaseInOut; 18 | 19 | public SAnimation() 20 | : this(0.3f) { 21 | } 22 | 23 | public SAnimation(float duration) { 24 | Duration = duration; 25 | } 26 | 27 | public override void Init() { 28 | if (Status != EStatus.Uninitialized) { 29 | return; 30 | } 31 | 32 | OnInit(); 33 | 34 | if (AutoStart) { 35 | Start(); 36 | Animate(0f); 37 | } else { 38 | Status = EStatus.Finished; 39 | } 40 | } 41 | 42 | public virtual void OnInit() { 43 | } 44 | 45 | public override void Update() { 46 | if (Elem.Backend.RenderOnGUI && !Elem.Backend.IsOnGUIRepainting) { 47 | return; 48 | } 49 | 50 | if (Status != EStatus.Running || Paused) { 51 | return; 52 | } 53 | 54 | Loop: 55 | float t = ((SpeedUnscaled ? SGUIRoot.TimeUnscaled : SGUIRoot.Time) - TimeStart) / Duration; 56 | if (t >= 1f) { 57 | End(); 58 | if (!Loop) return; 59 | Start(); 60 | TimeStart += (t - 1f) * Duration; 61 | goto Loop; 62 | } 63 | 64 | Animate(Easing(t)); 65 | } 66 | 67 | public void Start() { 68 | OnStart(); 69 | 70 | TimeStart = (SpeedUnscaled ? SGUIRoot.TimeUnscaled : SGUIRoot.Time); 71 | Status = EStatus.Running; 72 | } 73 | 74 | public abstract void OnStart(); 75 | 76 | public abstract void Animate(float t); 77 | 78 | public void End() { 79 | Status = EStatus.Finished; 80 | OnEnd(); 81 | } 82 | 83 | public virtual void OnEnd() { 84 | Animate(1f); 85 | } 86 | 87 | public enum EStatus { 88 | Uninitialized, 89 | Running, 90 | Finished 91 | } 92 | 93 | } 94 | 95 | public abstract class SDAnimation : SAnimation { 96 | 97 | public Action DOnInit; 98 | public override void OnInit() { 99 | DOnInit.Invoke(this); 100 | } 101 | 102 | public Action DOnStart; 103 | public override void OnStart() { 104 | if (DOnStart != null) DOnStart(this); 105 | } 106 | 107 | public Action DOnAnimate; 108 | public override void Animate(float t) { 109 | if (DOnAnimate != null) DOnAnimate(this, t); 110 | } 111 | 112 | public override void OnEnd() { 113 | Animate(1f); 114 | } 115 | 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/SGUIExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace SGUI { 9 | #if !SGUI_SHARED_EXT 10 | public static class SGUIExtensions { 11 | 12 | public static T AtOr(this T[] a, int i, T or) { 13 | if (i < 0 || a.Length <= i) return or; 14 | return a[i]; 15 | } 16 | 17 | public static void AddRange(this IDictionary to, IDictionary from) { 18 | foreach (DictionaryEntry entry in from) { 19 | to.Add(entry.Key, entry.Value); 20 | } 21 | } 22 | 23 | public static void ForEach(this BindingList list, Action a) { 24 | for (int i = 0; i < list.Count; i++) { 25 | a(list[i]); 26 | } 27 | } 28 | public static void AddRange(this BindingList list, BindingList other) { 29 | for (int i = 0; i < other.Count; i++) { 30 | list.Add(other[i]); 31 | } 32 | } 33 | 34 | public static int IndexOf(this object[] array, object elem) { 35 | for (int i = 0; i < array.Length; i++) { 36 | if (array[i] == elem) { 37 | return i; 38 | } 39 | } 40 | return -1; 41 | } 42 | 43 | } 44 | #endif 45 | } 46 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/External/SGUI/src/SModifier.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable RECS0018 2 | using System; 3 | using System.ComponentModel; 4 | using UnityEngine; 5 | 6 | namespace SGUI { 7 | public class SModifier { 8 | 9 | public SElement Elem; 10 | 11 | public virtual void Init() { 12 | 13 | } 14 | 15 | public virtual void UpdateStyle() { 16 | 17 | } 18 | 19 | public virtual void Update() { 20 | 21 | } 22 | 23 | } 24 | 25 | public class SDModifier : SModifier { 26 | 27 | public Action OnInit; 28 | public override void Init() { 29 | if (OnInit != null) OnInit(Elem); 30 | } 31 | 32 | public Action OnUpdateStyle; 33 | public override void UpdateStyle() { 34 | if (OnUpdateStyle != null) OnUpdateStyle(Elem); 35 | } 36 | 37 | public Action OnUpdate; 38 | public override void Update() { 39 | if (OnUpdate != null) OnUpdate(Elem); 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/GUI/Backend.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.IO; 4 | using ModTheGungeon; 5 | using SGUI; 6 | using UnityEngine; 7 | 8 | namespace ModTheGungeon.GUI { 9 | public class GUI : Backend { 10 | public static Logger Logger = new Logger("GUI"); 11 | public static SGUIRoot GUIRoot; 12 | public static MenuController MenuController; 13 | public static NotificationController NotificationController; 14 | private static GameObject _GameObject; 15 | 16 | public override Version Version { get { return new Version(0, 1, 0); } } 17 | 18 | public override void PreGameManagerAlive() { 19 | Logger.Info("Initializing SGUI"); 20 | 21 | GUIRoot = SGUIRoot.Setup(); 22 | SGUIIMBackend.GetFont = (SGUIIMBackend backend) => { 23 | System.Console.WriteLine($"GETFONT INSTANCE: {CorePatches.MainMenuFoyerController.Instance}"); 24 | if (CorePatches.MainMenuFoyerController.Instance?.VersionLabel == null) return null; 25 | return FontCache.GungeonFont ?? (FontCache.GungeonFont = FontConverter.DFFontToUnityFont((dfFont)CorePatches.MainMenuFoyerController.Instance.VersionLabel.Font, 2)); 26 | }; 27 | 28 | _GameObject = new GameObject("GUI"); 29 | DontDestroyOnLoad(_GameObject); 30 | 31 | Logger.Info("Initializing menu controller"); 32 | MenuController = _GameObject.AddComponent(); 33 | DontDestroyOnLoad(MenuController); 34 | 35 | Logger.Info("Initializing notification controller"); 36 | NotificationController = _GameObject.AddComponent(); 37 | DontDestroyOnLoad(NotificationController); 38 | 39 | _Bullet = UnityUtil.LoadTexture2D(Path.Combine(Paths.ResourcesFolder, "bullet.png")); 40 | 41 | AppDomain.CurrentDomain.UnhandledException += (obj, e) => { 42 | NotificationController.Notify(new Notification( 43 | title: "An unhandled error has occured", 44 | content: "More information in the log." 45 | ) { 46 | BackgroundColor = UnityUtil.NewColorRGB(57, 7, 7) 47 | }); 48 | }; 49 | 50 | ModTheGungeon.ModLoader.LuaError += (info, method, e) => { 51 | NotificationController.Notify(new Notification( 52 | title: $"An error has occured while loading mod {info.Name}", 53 | content: $"The '{method}' method had raised an error. More information in the log." 54 | ) { 55 | BackgroundColor = UnityUtil.NewColorRGB(57, 7, 7) 56 | }); 57 | }; 58 | 59 | ModTheGungeon.ErrorLoadingMod += (filename, e) => { 60 | NotificationController.Notify(new Notification( 61 | title: $"An error has occured while loading '{filename}'", 62 | content: "More information in the log." 63 | ) { 64 | BackgroundColor = UnityUtil.NewColorRGB(57, 7, 7) 65 | }); 66 | }; 67 | 68 | ModTheGungeon.ErrorCreatingModsDirectory += (e) => { 69 | NotificationController.Notify(new Notification( 70 | title: $"An error has occured while trying to create the Mods directory", 71 | content: "More information in the log." 72 | ) { 73 | BackgroundColor = UnityUtil.NewColorRGB(57, 7, 7) 74 | }); 75 | }; 76 | 77 | ModTheGungeon.ModsReloaded += (manual) => { 78 | if (manual) { 79 | NotificationController.Notify(new Notification( 80 | title: $"Reloaded!", 81 | content: "All mods have been reloaded as a result of pressing the F5 key." 82 | )); 83 | } else { 84 | NotificationController.Notify(new Notification( 85 | title: $"Reloaded!", 86 | content: "All mods have been reloaded automatically as a result of at least one of them being modified." 87 | )); 88 | } 89 | }; 90 | } 91 | 92 | private int _TestID = 1; 93 | private Texture _Bullet; 94 | public void Update() { 95 | if (Input.GetKeyDown(KeyCode.F9)) { 96 | NotificationController.Notify(new Notification( 97 | _TestID % 2 == 0 ? _Bullet : null, 98 | $"Achivement Unlocked", 99 | "Unlocked achievement 'Biggest Wallet'\nCollect 300 casings in one run." 100 | ) { 101 | BackgroundColor = UnityUtil.NewColorRGB(238, 188, 29), 102 | TitleColor = UnityUtil.NewColorRGB(0, 0, 0), 103 | ContentColor = UnityUtil.NewColorRGB(55, 55, 55) 104 | }); 105 | _TestID += 1; 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/GUI/Font.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace ModTheGungeon.GUI { 5 | public static class FontCache { 6 | public static Font GungeonFont = null; 7 | } 8 | 9 | public static class FontConverter { 10 | public static Font DFFontToUnityFont(dfFont font, int scale = 1) { 11 | Font f = new Font(font.name); 12 | 13 | f.material = new Material(UnityEngine.GUI.skin.font.material); 14 | f.material.mainTexture = font.Texture; 15 | f.material.mainTexture.wrapMode = TextureWrapMode.Repeat; 16 | 17 | CharacterInfo[] chars = new CharacterInfo[font.Glyphs.Count]; 18 | 19 | for (int i = 0; i < chars.Length; i++) { 20 | CharacterInfo inf = new CharacterInfo(); 21 | dfFont.GlyphDefinition glyphDefinition = font.Glyphs[i]; 22 | dfAtlas.ItemInfo itemInfo = font.Atlas[font.Sprite]; 23 | 24 | inf.glyphWidth = glyphDefinition.width * scale; 25 | inf.glyphHeight = glyphDefinition.height * scale; 26 | inf.size = 0; // Must be 0 27 | 28 | inf.index = glyphDefinition.id; 29 | 30 | float left = itemInfo.region.x + glyphDefinition.x * f.material.mainTexture.texelSize.x; 31 | float right = left + glyphDefinition.width * f.material.mainTexture.texelSize.x; 32 | float top = itemInfo.region.yMax - glyphDefinition.y * f.material.mainTexture.texelSize.y; 33 | float bottom = top - glyphDefinition.height * f.material.mainTexture.texelSize.y; 34 | 35 | inf.uvTopLeft = new Vector2(left, top); 36 | inf.uvTopRight = new Vector2(right, top); 37 | inf.uvBottomLeft = new Vector2(left, bottom); 38 | inf.uvBottomRight = new Vector2(right, bottom); 39 | 40 | inf.advance = glyphDefinition.xadvance * scale; 41 | 42 | inf.minY = scale * -glyphDefinition.height / 2; 43 | inf.maxY = scale * glyphDefinition.height / 2; 44 | 45 | chars[i] = inf; 46 | } 47 | 48 | f.characterInfo = chars; 49 | 50 | return f; 51 | } 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Lua/Globals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace ModTheGungeon.Lua { 5 | public static class Globals { 6 | public static PlayerController PrimaryPlayer { get { return GameManager.Instance.PrimaryPlayer; } } 7 | public static PlayerController SecondaryPlayer { get { return GameManager.Instance.SecondaryPlayer; } } 8 | } 9 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Lua/LuaTool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using MicroLua; 4 | 5 | namespace ModTheGungeon.Lua { 6 | public static class LuaTool { 7 | public static bool IsType(object o) { 8 | return o is T; 9 | } 10 | 11 | public static T AssertType(object o, string name) { 12 | if (!(o is T)) { 13 | throw new LuaException($"Expected type {typeof(T).Name} for {name}, got {o.GetType().Name}"); 14 | } 15 | return (T)o; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Lua/Triggers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using MicroLua; 4 | 5 | namespace ModTheGungeon.Lua { 6 | public class TriggerContainer : IDisposable { 7 | public ModLoader.ModInfo Info; 8 | 9 | public int MainMenuLoadedFirstTimeRef = -1; 10 | public int UnloadedRef = -1; 11 | 12 | private Action _MainMenuLoadedFirstTime; 13 | 14 | public void InvokeUnloaded() { 15 | if (UnloadedRef == -1) return; 16 | 17 | ModTheGungeon.ModLoader.LuaState.EnterArea(); 18 | ModTheGungeon.ModLoader.LuaState.BeginProtCall(); 19 | ModTheGungeon.ModLoader.LuaState.PushLuaReference(UnloadedRef); 20 | ModTheGungeon.ModLoader.LuaState.ExecProtCallVoid(0, cleanup: true); 21 | ModTheGungeon.ModLoader.LuaState.LeaveAreaCleanup(); 22 | } 23 | 24 | public void InvokeMainMenuLoadedFirstTime() { 25 | if (MainMenuLoadedFirstTimeRef == -1) return; 26 | 27 | ModTheGungeon.ModLoader.LuaState.EnterArea(); 28 | ModTheGungeon.ModLoader.LuaState.BeginProtCall(); 29 | ModTheGungeon.ModLoader.LuaState.PushLuaReference(MainMenuLoadedFirstTimeRef); 30 | ModTheGungeon.ModLoader.LuaState.ExecProtCallVoid(0, cleanup: true); 31 | ModTheGungeon.ModLoader.LuaState.LeaveAreaCleanup(); 32 | } 33 | 34 | private void _Trigger(LuaState lua, string name, ref int func) { 35 | lua.GetField(name); 36 | if (lua.Type() != LuaType.Nil) { 37 | if (lua.Type() == LuaType.Function) { 38 | func = lua.MakeLuaReference(); 39 | } 40 | } 41 | lua.Pop(); 42 | } 43 | 44 | public TriggerContainer(int env_ref, ModLoader.ModInfo info) { 45 | var lua = ModTheGungeon.ModLoader.LuaState; 46 | 47 | Info = info; 48 | lua.PushLuaReference(env_ref); 49 | _Trigger(lua, "MainMenuLoadedFirstTime", ref MainMenuLoadedFirstTimeRef); 50 | _Trigger(lua, "Unloaded", ref UnloadedRef); 51 | lua.Pop(); 52 | } 53 | 54 | public void Dispose() { 55 | ModTheGungeon.ModLoader.LuaState.DeleteLuaReference(MainMenuLoadedFirstTimeRef); 56 | ModTheGungeon.ModLoader.LuaState.DeleteLuaReference(UnloadedRef); 57 | 58 | RemoveExternalHooks(); 59 | } 60 | 61 | public void RemoveExternalHooks() { 62 | if (_MainMenuLoadedFirstTime != null) EventHooks.MainMenuLoadedFirstTime -= _MainMenuLoadedFirstTime; 63 | 64 | _MainMenuLoadedFirstTime = null; 65 | } 66 | 67 | public void SetupExternalHooks() { 68 | if (MainMenuLoadedFirstTimeRef != -1 && _MainMenuLoadedFirstTime == null) { 69 | _MainMenuLoadedFirstTime = (main_menu) => { 70 | Info.RunLua(MainMenuLoadedFirstTimeRef, "Events.MainMenuLoadedFirstTime", new object[] { main_menu }); 71 | }; 72 | EventHooks.MainMenuLoadedFirstTime += _MainMenuLoadedFirstTime; 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Menu/Menu.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SGUI; 4 | using UnityEngine; 5 | 6 | namespace ModTheGungeon.GUI { 7 | public class MenuController : MonoBehaviour { 8 | internal Menu OpenMenu = null; 9 | private GameObject _GameObject = new GameObject("ModTheGungeon Menu Controller"); 10 | private Dictionary _Menus = new Dictionary(); 11 | 12 | public void AddMenu(KeyCode[] keys) where T : Menu { 13 | var menu = _Menus[keys] = _GameObject.AddComponent(); 14 | DontDestroyOnLoad(menu); 15 | menu.MenuController = this; 16 | menu.Keys = keys; 17 | menu.Window = menu.CreateWindow(); 18 | menu.Window.Visible = false; 19 | } 20 | 21 | public void Update() { 22 | foreach (var pair in _Menus) { 23 | for (int i = 0; i < pair.Key.Length; i++) { 24 | var key = pair.Key[i]; 25 | if (Input.GetKeyDown(key)) { 26 | if (OpenMenu == pair.Value) { 27 | OpenMenu.Hide(); 28 | OpenMenu = null; 29 | return; 30 | } 31 | if (OpenMenu != null) OpenMenu.Hide(); 32 | OpenMenu = pair.Value; 33 | OpenMenu.Show(); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | 40 | public abstract class Menu : MonoBehaviour { 41 | public SElement Window; 42 | public KeyCode[] Keys; 43 | internal MenuController MenuController; 44 | 45 | public abstract SElement CreateWindow(); 46 | public virtual void OnShow() {} 47 | public virtual void OnHide() {} 48 | 49 | public void Show() { 50 | if (MenuController.OpenMenu != null) MenuController.OpenMenu.Hide(); 51 | MenuController.OpenMenu = this; 52 | Window.Visible = true; 53 | OnShow(); 54 | } 55 | 56 | public void Hide() { 57 | if (MenuController.OpenMenu == this) MenuController.OpenMenu = null; 58 | Window.Visible = false; 59 | OnHide(); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModLoader/AssemblyNameMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace ModTheGungeon { 6 | internal class AssemblyNameMap { 7 | private Dictionary _AsmNameToPathMap = new Dictionary(); 8 | private Dictionary _PathToAsmNameMap = new Dictionary(); 9 | 10 | public void AddAssembly(string path) { 11 | var asmname = AssemblyName.GetAssemblyName(path).Name; 12 | _AsmNameToPathMap[asmname] = path; 13 | _PathToAsmNameMap[path] = asmname; 14 | } 15 | 16 | public string GetAssemblyName(string path) { 17 | return _PathToAsmNameMap[path]; 18 | } 19 | 20 | public string GetPath(string asmname) { 21 | return _AsmNameToPathMap[asmname]; 22 | } 23 | 24 | public bool TryGetAssemblyName(string path, out string result) { 25 | return _AsmNameToPathMap.TryGetValue(path, out result); 26 | } 27 | 28 | public bool TryGetPath(string asmname, out string result) { 29 | return _PathToAsmNameMap.TryGetValue(asmname, out result); 30 | } 31 | 32 | public bool ContainsPath(string path) { 33 | return _PathToAsmNameMap.ContainsKey(path); 34 | } 35 | 36 | public bool ContainsAssemblyName(string asmname) { 37 | return _AsmNameToPathMap.ContainsKey(asmname); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModLoader/Metadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Security.Cryptography; 5 | using YamlDotNet.Serialization; 6 | 7 | namespace ModTheGungeon { 8 | public partial class ModLoader { 9 | public partial class ModInfo { 10 | /// 11 | /// Mod metadata class (the YML file is parsed into this object) 12 | /// 13 | public class Metadata { 14 | public class Dependency { 15 | [YamlMember(Alias = "name")] 16 | public string Name { set; get; } = "Unknown"; 17 | 18 | [YamlMember(Alias = "version")] 19 | public Version Version { set; get; } = new Version(1, 0, 0); 20 | } 21 | [YamlMember(Alias = "name")] 22 | public string Name { set; get; } = "Unknown"; 23 | 24 | [YamlMember(Alias = "version")] 25 | public Version Version { set; get; } = new Version(1, 0, 0); 26 | 27 | [YamlMember(Alias = "description")] 28 | public string Description { set; get; } = ""; 29 | 30 | [YamlMember(Alias = "author")] 31 | public string Author { set; get; } = "Unknown"; 32 | 33 | [YamlMember(Alias = "url")] 34 | public string URL { set; get; } = ""; 35 | 36 | [YamlMember(Alias = "script")] 37 | public string Script { set; get; } = null; 38 | 39 | [YamlMember(Alias = "dependencies")] 40 | public List Dependencies { set; get; } = new List(); 41 | 42 | [YamlMember(Alias = "modpack_dir")] 43 | public string ModPackDir { set; get; } = null; 44 | 45 | /// 46 | /// Extra information for other backends. 47 | /// Deserialized and reparsed when needed. 48 | /// 49 | [YamlMember(Alias = "extra")] 50 | public Dictionary Extra { set; get; } = null; 51 | 52 | public bool HasScript { 53 | get { 54 | return Script != null; 55 | } 56 | } 57 | 58 | public bool IsModPack { 59 | get { 60 | return ModPackDir != null; 61 | } 62 | } 63 | 64 | private readonly Deserializer _ExtraDeserializer = new DeserializerBuilder().Build(); 65 | private readonly Serializer _ExtraSerializer = new SerializerBuilder().Build(); 66 | public T ExtraData(string id) { 67 | if (Extra == null) return default(T); 68 | 69 | object extra; 70 | if (!Extra.TryGetValue(id, out extra)) { 71 | return default(T); 72 | } 73 | 74 | // HACK 75 | string extra_ser = _ExtraSerializer.Serialize(extra); 76 | return _ExtraDeserializer.Deserialize(extra_ser); 77 | } 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModLoader/ModInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using ModTheGungeon.Lua; 5 | using MicroLua; 6 | 7 | namespace ModTheGungeon { 8 | public partial class ModLoader { 9 | public partial class ModInfo : IDisposable { 10 | public Logger Logger = new Logger("Unnamed Mod"); 11 | private string _NameOverride; 12 | 13 | public ModInfo Parent; 14 | 15 | public string Name { 16 | get { 17 | if (_NameOverride == null) return ModMetadata.Name; 18 | return _NameOverride; 19 | } 20 | internal set { 21 | _NameOverride = value; 22 | Logger.ID = value; 23 | } 24 | } 25 | public List EmbeddedMods { 26 | get; 27 | internal set; 28 | } = new List(); 29 | 30 | public int LuaEnvironmentRef; 31 | internal int RealPackageTableRef; 32 | 33 | public TriggerContainer Triggers; 34 | public HookManager Hooks; 35 | 36 | private Metadata _ModMetadata; 37 | public Metadata ModMetadata { 38 | get { 39 | return _ModMetadata; 40 | } 41 | internal set { 42 | _ModMetadata = value; 43 | if (_NameOverride == null) { 44 | Logger.ID = value.Name; 45 | } 46 | } 47 | } 48 | 49 | public string RealPath { 50 | get; 51 | internal set; 52 | } 53 | 54 | public string Path { 55 | get; 56 | internal set; 57 | } 58 | 59 | public string ScriptPath { 60 | get; 61 | internal set; 62 | } 63 | 64 | public bool HasScript { 65 | get { 66 | return ScriptPath != null; 67 | } 68 | } 69 | 70 | public bool HasAnyEmbeddedMods { 71 | get { 72 | return EmbeddedMods.Count > 0; 73 | } 74 | } 75 | 76 | public bool IsComplete { 77 | get { 78 | return RealPath != null && Path != null && ModMetadata != null; 79 | } 80 | } 81 | 82 | public void RunLua(int func_ref, string name = "[unknown]", object[] args = null) { 83 | var lua = ModTheGungeon.ModLoader.LuaState; 84 | 85 | lua.EnterArea(); 86 | 87 | try { 88 | lua.BeginProtCall(); 89 | lua.PushLuaReference(func_ref); 90 | lua.PushLuaReference(LuaEnvironmentRef); 91 | lua.SetEnvironment(); 92 | if (args != null) { 93 | for (int i = 0; i < args.Length; i++) { 94 | lua.PushCLR(args); 95 | } 96 | } 97 | lua.ExecProtCall(args?.Length ?? 0); 98 | } catch (Exception e) { 99 | ModTheGungeon.ModLoader.LuaError.Invoke(this, LuaEventMethod.Loaded, e); 100 | 101 | Logger.Error(e.ToString()); 102 | } finally { 103 | lua.LeaveAreaCleanup(); // I'm lazy 104 | } 105 | } 106 | 107 | public void Dispose() { 108 | ModTheGungeon.ModLoader.LuaState.DeleteLuaReference(LuaEnvironmentRef); 109 | ModTheGungeon.ModLoader.LuaState.DeleteLuaReference(RealPackageTableRef); 110 | Triggers?.Dispose(); 111 | Hooks?.Dispose(); 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModResources/LoadedResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.IO; 4 | using ModTheGungeon; 5 | using UnityEngine; 6 | using System.Collections.Generic; 7 | 8 | namespace ModTheGungeon { 9 | public class LoadedResource { 10 | public enum StorageType { 11 | Stream, 12 | Text, 13 | Binary 14 | } 15 | 16 | public StorageType Type { get; protected set; } 17 | public string Path { get; protected set; } 18 | public string ResourcePath { get; protected set; } 19 | 20 | public Stream Stream { get; protected set; } 21 | public string TextContent { get; protected set; } 22 | public byte[] BinaryContent { get; protected set; } 23 | 24 | private Texture2D _Texture2D; 25 | public Texture2D GetTexture2D() { 26 | if (_Texture2D != null) return _Texture2D; 27 | return _Texture2D = UnityUtil.LoadTexture2D(ReadBinary(), Path); 28 | } 29 | 30 | private Animation.Collection _AnimationCollection; 31 | public Animation.Collection GetAnimationCollection(ModLoader.ModInfo info) { 32 | if (_AnimationCollection != null) return _AnimationCollection; 33 | return _AnimationCollection = new Animation.Collection(info, ReadText(), System.IO.Path.GetDirectoryName(ResourcePath)); 34 | } 35 | 36 | private Animation _Animation; 37 | public Animation GetAnimation(ModLoader.ModInfo info) { 38 | if (_Animation != null) return _Animation; 39 | return _Animation = new Animation(info, ReadText(), System.IO.Path.GetDirectoryName(ResourcePath)); 40 | } 41 | 42 | public LoadedResource(string resource_path, string path, StorageType type = StorageType.Stream) { 43 | ResourcePath = resource_path; 44 | Path = path; 45 | Type = type; 46 | 47 | Stream = File.OpenRead(path); 48 | if (type == StorageType.Stream) return; 49 | if (type == StorageType.Text) ReadText(); 50 | else if (type == StorageType.Binary) ReadBinary(); 51 | } 52 | 53 | public string ReadText() { 54 | if (TextContent != null) return TextContent; 55 | return TextContent = new StreamReader(Stream).ReadToEnd(); 56 | } 57 | 58 | public byte[] ReadBinary() { 59 | if (BinaryContent != null) return BinaryContent; 60 | return BinaryContent = new BinaryReader(Stream).ReadAllBytes(); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModResources/ModInfoResources.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace ModTheGungeon { 5 | public partial class ModLoader { 6 | public partial class ModInfo { 7 | private ResourcePool _Resources; 8 | public ResourcePool Resources { 9 | get { 10 | if (_Resources != null) return _Resources; 11 | if (RealPath == null) { 12 | throw new InvalidOperationException($"Tried to access Resources without RealPath"); 13 | } 14 | return _Resources = new ResourcePool(RealPath); 15 | } 16 | } 17 | 18 | public bool FileExists(string relative_path) { 19 | var p = System.IO.Path.Combine(ResourcePool.BaseResourceDir, relative_path); 20 | return File.Exists(p); 21 | } 22 | 23 | public bool DirectoryExists(string relative_path) { 24 | var p = System.IO.Path.Combine(ResourcePool.BaseResourceDir, relative_path); 25 | return Directory.Exists(p); 26 | } 27 | 28 | public LoadedResource LoadResource(string relative_path) { 29 | try { 30 | return Resources.Load(relative_path); 31 | } catch (FileNotFoundException e) { 32 | throw new FileNotFoundException($"[{Logger.ID}] While loading resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 33 | } 34 | } 35 | 36 | public string LoadText(string relative_path) { 37 | try { 38 | return Resources.Load(relative_path).ReadText(); 39 | } catch (FileNotFoundException e) { 40 | throw new FileNotFoundException($"[{Logger.ID}] While loading text resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 41 | } 42 | } 43 | 44 | public byte[] LoadBytes(string relative_path) { 45 | try { 46 | return Resources.Load(relative_path).ReadBinary(); 47 | } catch (FileNotFoundException e) { 48 | throw new FileNotFoundException($"[{Logger.ID}] While loading bytes resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 49 | } 50 | } 51 | 52 | public UnityEngine.Texture2D LoadTexture(string relative_path) { 53 | try { 54 | return Resources.Load(relative_path).GetTexture2D(); 55 | } catch (FileNotFoundException e) { 56 | throw new FileNotFoundException($"[{Logger.ID}] While loading resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 57 | } 58 | } 59 | 60 | public Animation LoadAnimation(string relative_path) { 61 | try { 62 | return Resources.Load(relative_path).GetAnimation(this); 63 | } catch (FileNotFoundException e) { 64 | throw new FileNotFoundException($"[{Logger.ID}] While loading resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 65 | } 66 | } 67 | 68 | public Animation.Collection LoadCollection(string relative_path) { 69 | try { 70 | return Resources.Load(relative_path).GetAnimationCollection(this); 71 | } catch (FileNotFoundException e) { 72 | throw new FileNotFoundException($"[{Logger.ID}] While loading resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 73 | } 74 | } 75 | 76 | public void Unload(string relative_path) { 77 | try { 78 | Resources.Unload(relative_path); 79 | } catch (FileNotFoundException e) { 80 | throw new FileNotFoundException($"[{Logger.ID}] While unloading resource '{relative_path.NormalizePath()}': {e.Message}\n{e.StackTrace}"); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModResources/ResourcePool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace ModTheGungeon { 6 | public partial class ModLoader { 7 | public partial class ModInfo { 8 | public class ResourcePool { 9 | public static string BaseResourceDir { 10 | get { 11 | return "resources"; 12 | } 13 | } 14 | 15 | public string BaseDir { 16 | get; 17 | protected set; 18 | } 19 | 20 | public string Path { 21 | get; 22 | protected set; 23 | } 24 | 25 | public int ResourceCount { 26 | get { 27 | return _LoadedResources.Count; 28 | } 29 | } 30 | 31 | private Dictionary _LoadedResources = new Dictionary(); 32 | 33 | public ResourcePool(string base_dir) { 34 | BaseDir = base_dir; 35 | Path = System.IO.Path.Combine(BaseDir, BaseResourceDir); 36 | } 37 | 38 | public void Unload(string relative_path) { 39 | var normalized = relative_path.NormalizePath(); 40 | 41 | LoadedResource res; 42 | if (_LoadedResources.TryGetValue(normalized, out res)) { 43 | _LoadedResources[normalized].Stream.Close(); 44 | _LoadedResources.Remove(normalized); 45 | } 46 | } 47 | 48 | public LoadedResource Load(string relative_path) { 49 | var normalized = relative_path.NormalizePath(); 50 | var relative_to_resources_dir = System.IO.Path.Combine(BaseResourceDir, normalized); 51 | var final_path = System.IO.Path.Combine(BaseDir, relative_to_resources_dir); 52 | 53 | if (!File.Exists(final_path)) { 54 | throw new FileNotFoundException($"Resource '{normalized}' doesn't exist."); 55 | } 56 | 57 | var res = new LoadedResource( 58 | normalized, 59 | final_path 60 | ); 61 | _LoadedResources[normalized] = res; 62 | return res; 63 | } 64 | 65 | public string LoadText(string relative_path) { 66 | return Load(relative_path).ReadText(); 67 | } 68 | 69 | public byte[] LoadBinary(string relative_path) { 70 | return Load(relative_path).ReadBinary(); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModTheGungeon/API.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ModTheGungeon.API; 3 | 4 | namespace ModTheGungeon { 5 | public partial class ModTheGungeon { 6 | private void _InitAPIs() { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/ModTheGungeon/IDMaps.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | namespace ModTheGungeon { 7 | public partial class ModTheGungeon : Backend { 8 | public enum ItemType { 9 | Unknown, 10 | Item, 11 | Consumable, 12 | Syn//ergy 13 | } 14 | 15 | public enum EntityType { 16 | Unknown, 17 | Enemy, 18 | Friendly 19 | } 20 | 21 | public static IDPool Items; 22 | public static IDPool Entities; 23 | 24 | private IDPool _ReadIDMap(IList list, string path) where T : UnityEngine.Object { 25 | var pool = new IDPool(); 26 | 27 | using (var file = File.OpenRead(path)) { 28 | using (var reader = new StreamReader(file)) { 29 | var line_id = 0; 30 | 31 | while (!reader.EndOfStream) { 32 | line_id += 1; 33 | var line = reader.ReadLine().Trim(); 34 | if (line.StartsWithInvariant("#")) continue; 35 | if (line.Length == 0) continue; 36 | 37 | var split = line.Split(' '); 38 | if (split.Length < 3) { 39 | throw new Exception($"Failed parsing ID map file: not enough columns at line {line_id} (need at least 2, ID and the name)"); 40 | } 41 | var type_el_split = split[0].Split(','); 42 | var type = type_el_split[0]; 43 | var type_val = (TType)Enum.Parse(typeof(TType), type, true); 44 | 45 | string subtype = null; 46 | if (type_el_split.Length >= 2) { 47 | subtype = type_el_split[1]; 48 | } 49 | 50 | int id; 51 | if (!int.TryParse(split[1], out id)) throw new Exception($"Failed parsing ID map file: ID column at line {line_id} was not an integer"); 52 | 53 | try { 54 | pool[$"gungeon:{split[2]}"] = list[id]; 55 | pool.SetType($"gungeon:{split[2]}", type_val); 56 | } catch (Exception e) { 57 | throw new Exception($"Failed loading ID map file: Error while adding entry to ID pool ({e.Message})"); 58 | } 59 | } 60 | } 61 | } 62 | 63 | pool.LockNamespace("gungeon"); 64 | return pool; 65 | } 66 | 67 | private void _InitIDs() { 68 | var id_pool_base = Path.Combine(Paths.ResourcesFolder, "idmaps"); 69 | ModTheGungeon.Logger.Info("Loading item ID map"); 70 | Items = _ReadIDMap(PickupObjectDatabase.Instance.Objects, Path.Combine(id_pool_base, "items.txt")); 71 | 72 | ModTheGungeon.Logger.Info("Loading entity ID map"); 73 | Entities = new IDPool(); 74 | using (var file = File.OpenRead(Path.Combine(id_pool_base, "enemies.txt"))) { 75 | using (var reader = new StreamReader(file)) { 76 | var line_id = 0; 77 | 78 | while (!reader.EndOfStream) { 79 | line_id += 1; 80 | var line = reader.ReadLine().Trim(); 81 | if (line.StartsWithInvariant("#")) continue; 82 | if (line.Length == 0) continue; 83 | 84 | var split = line.Split(' '); 85 | if (split.Length < 3) { 86 | throw new Exception($"Failed parsing ID map file: not enough columns at line {line_id} (need at least 2, ID and the name)"); 87 | } 88 | var type_el_split = split[0].Split(','); 89 | var type = type_el_split[0]; 90 | var type_val = (EntityType)Enum.Parse(typeof(EntityType), type, true); 91 | 92 | string subtype = null; 93 | if (type_el_split.Length >= 2) { 94 | subtype = type_el_split[1]; 95 | } 96 | 97 | var prefab_name = split[1].Replace("%%%", " "); 98 | try { 99 | var prefab = EnemyDatabase.AssetBundle.LoadAsset(prefab_name); 100 | Entities[$"gungeon:{split[2]}"] = prefab.GetComponent(); 101 | Entities.SetType($"gungeon:{split[2]}", type_val); 102 | } catch (Exception e) { 103 | throw new Exception($"Failed loading ID map file: Error while adding entry to ID pool ({e.Message})"); 104 | } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Notifications/Animations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SGUI; 3 | using UnityEngine; 4 | 5 | namespace ModTheGungeon.GUI { 6 | public class SNopAnimation : SAnimation { 7 | public SNopAnimation(float duration) : base(duration) {} 8 | 9 | public override void OnInit() { 10 | base.OnInit(); 11 | } 12 | 13 | public override void OnStart() {} 14 | 15 | public override void Animate(float t) {} 16 | } 17 | 18 | public class SSlideInHorizontallyAnimation : SAnimation { 19 | public float HorizontalOffset; 20 | private float _XDiff; 21 | private float _XOrig; 22 | private float _XStart; 23 | 24 | public SSlideInHorizontallyAnimation(int x_offset, float duration) : base(duration) { 25 | HorizontalOffset = x_offset; 26 | } 27 | 28 | public override void OnInit() { 29 | base.OnInit(); 30 | 31 | var target = Elem.Position.x + HorizontalOffset; 32 | var diff = target - Elem.Position.x; 33 | 34 | _XDiff = diff; 35 | _XOrig = Elem.Position.x; 36 | 37 | _XStart = target; 38 | Elem.Position.x = _XStart; 39 | } 40 | 41 | public override void OnStart() {} 42 | 43 | public override void Animate(float t) { 44 | Elem.Position.x = _XStart - t * _XDiff; 45 | } 46 | 47 | public override void OnEnd() { 48 | Elem.Position.x = _XOrig; 49 | } 50 | } 51 | 52 | public class SNotificationDecayAnimation : SAnimation { 53 | 54 | public SNotificationDecayAnimation(NotificationController n) 55 | : this(0.3f, n) { 56 | } 57 | public SNotificationDecayAnimation(float duration, NotificationController n) 58 | : base(duration) { 59 | NotificationController = n; 60 | } 61 | 62 | protected float _OriginalH; 63 | protected float _OriginalY; 64 | protected float _YDiff; 65 | public NotificationController NotificationController; 66 | 67 | 68 | public override void OnInit() { 69 | AutoStart = false; 70 | Elem.UpdateBounds = false; 71 | } 72 | 73 | public override void OnStart() { 74 | Loop = false; 75 | 76 | ((NotificationSGroup)Elem).Decaying = true; 77 | 78 | _OriginalY = Elem.Position.y; 79 | var current = Elem.Position.y; 80 | float target = Screen.height + NotificationController.NotificationPadding; 81 | if (Elem.Previous != null) target = Elem.Previous.Position.y; 82 | 83 | _YDiff = target - current; 84 | 85 | Elem.Children.Clear(); 86 | Elem.Size.y = _OriginalH; 87 | } 88 | 89 | public override void Animate(float t) { 90 | Elem.Position.y = _OriginalY + _YDiff * t; 91 | if (Elem.Parent != null) { 92 | for (int i = 0; i < Elem.Parent.Children.Count; i++) { 93 | var child = Elem.Parent.Children[i]; 94 | if (child == Elem) continue; 95 | child.UpdateStyle(); 96 | } 97 | } 98 | } 99 | 100 | public override void OnEnd() { 101 | Elem.Remove(); 102 | base.OnEnd(); 103 | } 104 | 105 | } 106 | 107 | public class SNotificationAnimationSequence : SAnimationSequence { 108 | public SFadeOutAnimation FadeOut; 109 | public SNotificationDecayAnimation Shrink; 110 | public NotificationController NotificationController; 111 | 112 | public float IdleDuration; 113 | public float FadeOutDuration; 114 | public float DecayDuration; 115 | 116 | public SNotificationAnimationSequence(float durationIdle, float durationFadeOut, float durationDecay, NotificationController controller) { 117 | IdleDuration = durationIdle; 118 | FadeOutDuration = durationFadeOut; 119 | DecayDuration = durationDecay; 120 | NotificationController = controller; 121 | } 122 | 123 | public override void OnStart() { 124 | Sequence.Add(new SNopAnimation(IdleDuration)); 125 | 126 | if (FadeOut == null) { 127 | Sequence.Add(FadeOut = new SFadeOutAnimation(FadeOutDuration)); 128 | } 129 | 130 | if (Shrink == null) { 131 | Sequence.Add(Shrink = new SNotificationDecayAnimation(DecayDuration, NotificationController)); 132 | } 133 | 134 | base.OnStart(); 135 | } 136 | 137 | } 138 | 139 | public class STest : SAnimation { 140 | public override void Animate(float t) { 141 | var color = Elem.Foreground; 142 | color.a = t - 1f; 143 | Elem.Foreground = color; 144 | } 145 | 146 | public override void OnStart() { 147 | Duration = 100; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Notifications/Notification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SGUI; 3 | using UnityEngine; 4 | 5 | namespace ModTheGungeon.GUI { 6 | public class Notification { 7 | public Texture Image; 8 | public string Title; 9 | public string Content; 10 | public Color BackgroundColor = UnityUtil.NewColorRGB(0, 0, 0); 11 | public Color TitleColor = UnityUtil.NewColorRGB(255, 255, 255); 12 | public Color ContentColor = UnityUtil.NewColorRGB(200, 200, 200); 13 | internal float CurrentDecayTime; 14 | internal bool Decayed = false; 15 | 16 | public Notification(string title, string content) { 17 | Title = title; 18 | Content = content; 19 | } 20 | 21 | public Notification(Texture image, string title, string content) : this(title, content) { 22 | Image = image; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Notifications/NotificationController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using SGUI; 5 | 6 | namespace ModTheGungeon.GUI { 7 | internal class NotificationSGroup : SGroup { 8 | public bool Decaying = false; 9 | public bool Displayed = false; 10 | } 11 | 12 | public class NotificationController : MonoBehaviour { 13 | public float MaxNotificationDelay = 0.5f; 14 | public int NotificationSpaceWidth { get { return Screen.width / 4; } } 15 | public int NotificationHeight { get { return Screen.height / 8; } } 16 | public int NotificationPadding = 5; 17 | private float _CurrentNotificationDelay; 18 | private SGroup _NotificationGroup; 19 | 20 | public float IdleDuration = 2f; 21 | public float FadeoutDuration = 2f; 22 | public float DecayDuration = 1f; 23 | public int SlideOffset; 24 | public float SlideDuration = 1f; 25 | 26 | public void Awake() { 27 | SlideOffset = NotificationSpaceWidth; 28 | 29 | _CurrentNotificationDelay = MaxNotificationDelay; 30 | _NotificationGroup = new SGroup { 31 | Visible = true, 32 | Background = new Color(0, 0, 0, 0), 33 | 34 | OnUpdateStyle = (obj) => { 35 | var width = NotificationSpaceWidth; 36 | obj.Position = new Vector2(Screen.width - width, 0); 37 | obj.Size = new Vector2(width, Screen.height); 38 | }, 39 | 40 | Children = { } 41 | }; 42 | } 43 | 44 | private SGroup _CreateNotificationSGroup(Notification notif) { 45 | var sgroup = new NotificationSGroup { 46 | Visible = true, 47 | Background = notif.BackgroundColor, 48 | 49 | OnUpdateStyle = (obj) => { 50 | var group = (NotificationSGroup)obj; 51 | 52 | if (group.Decaying) return; 53 | 54 | if (obj.Previous == null && !group.Displayed) { 55 | group.Displayed = true; 56 | var seq = new SNotificationAnimationSequence( 57 | IdleDuration, 58 | FadeoutDuration, 59 | DecayDuration, 60 | this 61 | ); 62 | group.Modifiers.Add(seq); 63 | seq.Start(); 64 | } 65 | 66 | float ysize = ((SGroup)obj).AutoLayoutPadding; 67 | for (int i = 0; i < obj.Children.Count; i++) { 68 | var child = obj.Children[i]; 69 | if (child is SGroup) { 70 | child.UpdateStyle(); 71 | ysize += child.Size.y; 72 | } 73 | } 74 | 75 | float y; 76 | if (obj.Previous != null) y = obj.Previous.Position.y - NotificationPadding; 77 | else y = Screen.height; 78 | 79 | y -= obj.Size.y; 80 | 81 | obj.Size = new Vector2(NotificationSpaceWidth, ysize); 82 | obj.Position = new Vector2(obj.Position.x, y); 83 | }, 84 | 85 | Children = { } 86 | }; 87 | if (notif.Image != null) { 88 | sgroup.Children.Add(new SImage(notif.Image) { 89 | OnUpdateStyle = (obj) => { 90 | var image = (SImage)obj; 91 | image.Size = new Vector2(image.Texture.width, image.Texture.height); 92 | } 93 | }); 94 | } 95 | 96 | var inner_group = new SGroup { 97 | Background = new Color(0f, 0f, 0f, 0f), 98 | AutoLayout = (self) => self.AutoLayoutVertical, 99 | Children = { 100 | new SLabel(notif.Title) { Foreground = notif.TitleColor }, 101 | new SLabel(notif.Content) { Foreground = notif.ContentColor } 102 | }, 103 | OnUpdateStyle = (obj) => { 104 | float ysize = ((SGroup)obj).AutoLayoutPadding; 105 | for (int i = 0; i < obj.Children.Count; i++) { 106 | var child = obj.Children[i]; 107 | if (child is SLabel) { 108 | ysize += obj.Backend.MeasureText(((SLabel)child).Text, obj.Size.x).y; 109 | ysize += ((SGroup)obj).AutoLayoutPadding; 110 | } 111 | } 112 | 113 | if (notif.Image != null) { 114 | obj.Position = new Vector2(notif.Image.width, 0); 115 | obj.Size = new Vector2(obj.Parent.Size.x - notif.Image.width, ysize); 116 | } else { 117 | obj.Position = new Vector2(0, 0); 118 | obj.Size = new Vector2(obj.Parent.Size.x, ysize); 119 | } 120 | }, 121 | Size = new Vector2(NotificationSpaceWidth, NotificationHeight) 122 | }; 123 | 124 | sgroup.Children.Add(inner_group); 125 | inner_group.UpdateStyle(); 126 | sgroup.UpdateStyle(); 127 | 128 | sgroup.Modifiers.Add(new SSlideInHorizontallyAnimation( 129 | SlideOffset, 130 | SlideDuration 131 | )); 132 | 133 | return sgroup; 134 | } 135 | 136 | public void Notify(Notification notif) { 137 | var sgroup = _CreateNotificationSGroup(notif); 138 | _NotificationGroup.Children.Add(sgroup); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Patches/ModOptions.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using MonoMod; 6 | using ModTheGungeon.Tools; 7 | using UnityEngine; 8 | 9 | namespace ModTheGungeon.BasePatches { 10 | [MonoModPatch("global::PreOptionsMenuController")] 11 | public class PreOptionsMenuController : global::PreOptionsMenuController { 12 | public dfButton TabModTheGungeonSelector; 13 | private dfPanel m_panel; 14 | 15 | private extern void orig_Awake(); 16 | private void Awake() { 17 | orig_Awake(); 18 | TabModTheGungeonSelector = Instantiate(TabGameplaySelector); 19 | TabModTheGungeonSelector.Text = "MODS"; 20 | m_panel.AddControl(TabModTheGungeonSelector); 21 | 22 | TabModTheGungeonSelector.Position = new Vector3(TabModTheGungeonSelector.Position.x, TabGameplaySelector.Position.y - 42.75f, 0); 23 | TabControlsSelector.Position = new Vector3(TabControlsSelector.Position.x, TabModTheGungeonSelector.Position.y - 42.75f, 0); 24 | TabVideoSelector.Position = new Vector3(TabVideoSelector.Position.x, TabControlsSelector.Position.y - 42.75f, 0); 25 | TabAudioSelector.Position = new Vector3(TabAudioSelector.Position.x, TabVideoSelector.Position.y - 42.75f, 0); 26 | TabModTheGungeonSelector.Click += delegate (dfControl control, dfMouseEventArgs mouseEvent) { 27 | ToggleToPanel(((FullOptionsMenuController)FullOptionsMenu).TabModTheGungeon, false, false); 28 | }; 29 | } 30 | 31 | bool dumped = false; 32 | private extern void orig_Update(); 33 | private void Update() { 34 | orig_Update(); 35 | if (m_panel != null && dumped == false) { 36 | dumped = true; 37 | Console.WriteLine(ObjectDumper.Dump(m_panel, 10)); 38 | } 39 | } 40 | } 41 | 42 | [MonoModPatch("global::FullOptionsMenuController")] 43 | public class FullOptionsMenuController : global::FullOptionsMenuController { 44 | private dfControl m_lastSelectedBottomRowControl; 45 | 46 | public dfScrollPanel TabModTheGungeon; 47 | 48 | private extern void orig_Awake(); 49 | private void Awake() { 50 | orig_Awake(); 51 | TabModTheGungeon = Instantiate(TabControls); 52 | } 53 | 54 | public extern void orig_ToggleToPanel(dfScrollPanel targetPanel, bool doFocus = false); 55 | public void ToggleToPanel(dfScrollPanel targetPanel, bool doFocus = false) { 56 | TabModTheGungeon.IsVisible = (targetPanel == TabModTheGungeon); 57 | orig_ToggleToPanel(targetPanel, doFocus); 58 | } 59 | 60 | private void BottomOptionFocused(dfControl control, dfFocusEventArgs args) { 61 | m_lastSelectedBottomRowControl = control; 62 | if (TabAudio.IsVisible) { 63 | TabAudio.Controls[TabAudio.Controls.Count - 1].GetComponent().down = m_lastSelectedBottomRowControl; 64 | } else if (TabVideo.IsVisible) { 65 | TabVideo.Controls[TabVideo.Controls.Count - 1].GetComponent().down = m_lastSelectedBottomRowControl; 66 | } else if (TabControls.IsVisible) { 67 | TabControls.Controls[TabControls.Controls.Count - 2].GetComponent().down = m_lastSelectedBottomRowControl; 68 | } else if (TabGameplay.IsVisible) { 69 | TabGameplay.Controls[TabGameplay.Controls.Count - 1].GetComponent().down = m_lastSelectedBottomRowControl; 70 | } else if (TabModTheGungeon.IsVisible) { 71 | TabModTheGungeon.Controls[TabModTheGungeon.Controls.Count - 2].GetComponent().down = m_lastSelectedBottomRowControl; 72 | } else if (TabKeyboardBindings.IsVisible) { 73 | TabKeyboardBindings.Controls[TabKeyboardBindings.Controls.Count - 1].GetComponent().KeyButton.GetComponent().down = m_lastSelectedBottomRowControl; 74 | TabKeyboardBindings.Controls[TabKeyboardBindings.Controls.Count - 1].GetComponent().AltKeyButton.GetComponent().down = m_lastSelectedBottomRowControl; 75 | } 76 | } 77 | 78 | public void ToggleToModTheGungeon() { 79 | this.TabGameplay.IsVisible = false; 80 | this.TabCredits.IsVisible = true; 81 | this.TabCredits.Controls[0].Focus(true); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Patches/patch_MainMenuFoyerController.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using MonoMod; 6 | 7 | namespace ModTheGungeon.BasePatches { 8 | [MonoModPatch("global::MainMenuFoyerController")] 9 | public class MainMenuFoyerController : global::MainMenuFoyerController { 10 | public extern void AddLine(string s); 11 | 12 | public void Start() { 13 | var word = ModTheGungeon.ModLoader.LoadedMods.Count == 1 ? "mod" : "mods"; 14 | AddLine($"{ModTheGungeon.ModLoader.LoadedMods.Count} {word} loaded"); 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Patches/patch_dfButton.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using SGUI; 6 | using MonoMod; 7 | 8 | namespace ModTheGungeon.GUI.Patches { 9 | [MonoModPatch("global::dfButton")] 10 | public class dfButton : global::dfButton { 11 | protected extern void orig_OnKeyPress(dfKeyEventArgs args); 12 | protected override void OnKeyPress(dfKeyEventArgs args) { 13 | if (SGUIRoot.Main.Backend.LastKeyEventConsumed) return; 14 | 15 | orig_OnKeyPress(args); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Patches/patch_dfInputManager.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using SGUI; 6 | using MonoMod; 7 | 8 | namespace ModTheGungeon.GUI.Patches { 9 | [MonoModPatch("global::dfInputManager")] 10 | public class dfInputManager : global::dfInputManager { 11 | bool _ModTheGungeon_sgui_patched = false; 12 | 13 | public extern void orig_OnEnable(); 14 | public new void OnEnable() { 15 | orig_OnEnable(); 16 | 17 | if (_ModTheGungeon_sgui_patched) return; 18 | _ModTheGungeon_sgui_patched = true; 19 | 20 | GUI.Logger.Debug($"Patching dfInputManager adapter with SGUIDFInput"); 21 | Adapter = new SGUIDFInput(Adapter); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/Patches/patch_tk2dSpriteDefinition.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using MonoMod; 6 | 7 | namespace ModTheGungeon.BasePatches { 8 | // hacky stuff for passing the scale and region of a parsed definition 9 | 10 | [MonoModPatch("global::tk2dSpriteDefinition")] 11 | public class tk2dSpriteDefinition : global::tk2dSpriteDefinition { 12 | public int ModTheGungeonOffsetX { 13 | get { 14 | return (int)position0.x; 15 | } 16 | } 17 | 18 | public int ModTheGungeonOffsetY { 19 | get { 20 | return (int)position0.y; 21 | } 22 | } 23 | 24 | public int ModTheGungeonCropWidth { 25 | get { 26 | return regionW; 27 | } 28 | } 29 | 30 | public int ModTheGungeonCropHeight { 31 | get { 32 | return regionH; 33 | } 34 | } 35 | 36 | public int ModTheGungeonCropX { 37 | get { 38 | return regionX; 39 | } 40 | } 41 | 42 | public int ModTheGungeonCropY { 43 | get { 44 | return regionY; 45 | } 46 | } 47 | 48 | public float ModTheGungeonScaleW { 49 | get { 50 | var w = position3.x - ModTheGungeonOffsetX; 51 | return w * 16f / regionW; 52 | } 53 | } 54 | 55 | public float ModTheGungeonScaleH { 56 | get { 57 | var w = position3.y - ModTheGungeonOffsetY; 58 | return w * 16f / regionH; 59 | } 60 | } 61 | 62 | public float ModTheGungeonScaledWidth { 63 | get { 64 | return (position3.x - ModTheGungeonOffsetX) * 16f; 65 | } 66 | } 67 | 68 | public float ModTheGungeonScaledHeight { 69 | get { 70 | return (position3.y - ModTheGungeonOffsetY) * 16f; 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Base.mm/src/PrefabricTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace ModTheGungeon { 6 | public class PrefabricTest : MonoBehaviour { 7 | public class InnerObject { 8 | public int A; 9 | public string B; 10 | } 11 | 12 | public static void RunTest() { 13 | 14 | } 15 | 16 | public int A; 17 | public string B; 18 | public InnerObject C; 19 | public string[] StringAry; 20 | public InnerObject[] ObjectAry; 21 | public List StringList; 22 | public Dictionary ObjectDict; 23 | 24 | public void Test() { 25 | Console.WriteLine($"A: {A} B: {B} C: {C}"); 26 | if (C != null) Console.WriteLine($"INNER: A: {C.A} B: {C.B}"); 27 | if (StringAry != null) { 28 | Console.WriteLine($"STRINGARY NOT NULL, LENGTH {StringAry.Length}"); 29 | for (int i = 0; i < StringAry.Length; i++) { 30 | var ent = StringAry[i]; 31 | Console.WriteLine($"IDX {i}: VAL {ent}"); 32 | } 33 | } 34 | if (ObjectAry != null) { 35 | Console.WriteLine($"OBJECTARY NOT NULL, LENGTH {ObjectAry.Length}"); 36 | for (int i = 0; i < ObjectAry.Length; i++) { 37 | var ent = ObjectAry[i]; 38 | Console.WriteLine($"IDX {i}: A: {ent.A} B: {ent.B}"); 39 | } 40 | } 41 | if (StringList != null) { 42 | Console.WriteLine($"STRINGLIST NOT NULL, COUNT {StringList.Count}"); 43 | for (int i = 0; i < StringList.Count; i++) { 44 | var ent = StringList[i]; 45 | Console.WriteLine($"IDX {i}: VAL {ent}"); 46 | } 47 | } 48 | if (ObjectDict != null) { 49 | Console.WriteLine($"OBJECTDICT NOT NULL, COUNT {ObjectDict.Count}"); 50 | foreach (var ent in ObjectDict) { 51 | Console.WriteLine($"IDX {ent.Key}: A: {ent.Value.A} B: {ent.Value.B}"); 52 | } 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/Assembly-CSharp.Core.mm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {4473AD38-DAF1-449A-A850-4296D3368413} 7 | Library 8 | ModTheGungeon 9 | Assembly-CSharp.Core.mm 10 | v3.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | 21 | 22 | true 23 | bin\Release 24 | prompt 25 | 4 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ..\libs\UnityEngine.dll 51 | 52 | 53 | ..\libs\Assembly-CSharp.dll 54 | 55 | 56 | ..\libs\Assembly-CSharp-firstpass.dll 57 | 58 | 59 | ..\libs\UnityEngine.CoreModule.dll 60 | 61 | 62 | ..\libs\UnityEngine.UIModule.dll 63 | 64 | 65 | ..\libs\UnityEngine.ImageConversionModule.dll 66 | 67 | 68 | 69 | 70 | {8A17C958-5C33-4035-AF76-F94A3AA2DC4F} 71 | MonoMod 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Core/Backend.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace ModTheGungeon { 6 | public abstract class Backend : UnityEngine.MonoBehaviour { 7 | public struct Info { 8 | public string Name; 9 | public Version Version; 10 | public Type Type; 11 | public Backend Instance; 12 | public string StringVersion; 13 | } 14 | 15 | public abstract Version Version { 16 | get; 17 | } 18 | 19 | public virtual string StringVersion { 20 | get { 21 | return Version.ToString(); 22 | } 23 | } 24 | 25 | public static UnityEngine.GameObject GameObject { 26 | get; 27 | internal set; 28 | } 29 | 30 | public static List AllBackends = new List(); 31 | 32 | public static void AddBackendInfo(Info info) { 33 | AllBackends.Add(info); 34 | } 35 | 36 | public struct SearchResult { 37 | public enum Type { 38 | NoMatch, 39 | OnlyVersionMatches, 40 | OnlyNameMatches, 41 | PerfectMatch 42 | } 43 | 44 | private Type _Result; 45 | public Info? BestMatch; 46 | 47 | public bool NameMatched() { 48 | return _Result == Type.PerfectMatch || _Result == Type.OnlyNameMatches; 49 | } 50 | 51 | public bool VersionMatched() { 52 | return _Result == Type.PerfectMatch || _Result == Type.OnlyVersionMatches; 53 | } 54 | 55 | public bool FullyMatched() { 56 | return _Result == Type.PerfectMatch; 57 | } 58 | 59 | public bool NotMatched() { 60 | return _Result == Type.NoMatch; 61 | } 62 | 63 | public bool OnlyNameMatched() { 64 | return NameMatched() && !FullyMatched(); 65 | } 66 | 67 | public bool OnlyVersionMatched() { 68 | return VersionMatched() && !FullyMatched(); 69 | } 70 | 71 | public SearchResult(Type result, Info? best_match) { 72 | _Result = result; 73 | BestMatch = best_match; 74 | } 75 | } 76 | 77 | public static SearchResult SearchForBackend(string name, Version version = null) { 78 | Info? best_match = null; 79 | SearchResult.Type result = SearchResult.Type.NoMatch; 80 | 81 | for (int i = 0; i < AllBackends.Count; i++) { 82 | var backend = AllBackends[i]; 83 | 84 | if (result != SearchResult.Type.PerfectMatch && backend.Name == name && backend.Version == version) { 85 | Loader.Logger.Debug($"Perfect match for search (name={name},version={version}) found: {backend.Name} {backend.Version}"); 86 | best_match = backend; 87 | result = SearchResult.Type.PerfectMatch; 88 | break; // break early, since the perfect match has been found 89 | } else if (result != SearchResult.Type.OnlyNameMatches && backend.Name == name && backend.Version != version) { 90 | Loader.Logger.Debug($"Name match for search (name={name},version={version}) found: {backend.Name} {backend.Version}"); 91 | best_match = backend; 92 | result = SearchResult.Type.OnlyNameMatches; 93 | // continue on, in an attempt to find a perfect match 94 | } else if (result != SearchResult.Type.OnlyNameMatches && backend.Name != name && backend.Version == version) { 95 | Loader.Logger.Debug($"Version match for search (name={name},version={version}) found: {backend.Name} {backend.Version}"); 96 | best_match = backend; 97 | result = SearchResult.Type.OnlyVersionMatches; 98 | } 99 | } 100 | 101 | if (best_match == null) { 102 | Loader.Logger.Debug($"No match for search (name={name},version={version}) found"); 103 | } 104 | 105 | return new SearchResult(result, best_match); 106 | } 107 | 108 | public virtual void Loaded() { } 109 | public virtual void PreGameManagerAlive() { } 110 | public virtual void GameManagerAlive() { } 111 | public virtual void AllBackendsLoaded() { } 112 | public virtual void NoBackendsLoadedYet() { } 113 | 114 | public virtual void Reload() { } 115 | public virtual void ReloadAfterMods() { } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Core/Core.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using UnityEngine; 4 | 5 | namespace ModTheGungeon { 6 | public static class Loader { 7 | public static Logger Logger = new Logger("Loader"); 8 | } 9 | 10 | public class Coroutine { 11 | private class DummyBehaviour : MonoBehaviour {} 12 | private static GameObject _GameObject = new GameObject("ModTheGungeon Global Coroutines"); 13 | private static DummyBehavior _DummyBehaviour; 14 | 15 | static Coroutine() { 16 | _DummyBehaviour = _GameObject.AddComponent(); 17 | } 18 | 19 | public static void Start(IEnumerator coroutine) { 20 | _DummyBehaviour.StartCoroutine(coroutine); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Core/EventHooks.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace ModTheGungeon { 3 | public static class EventHooks { 4 | private static Logger _Logger = new Logger("EventHooks"); 5 | 6 | public static Action MainMenuLoadedFirstTime; 7 | public static void InvokeMainMenuLoadedFirstTime(MainMenuFoyerController menu) { 8 | _Logger.Debug(nameof(MainMenuLoadedFirstTime)); 9 | MainMenuLoadedFirstTime?.Invoke(menu); 10 | } 11 | 12 | public static Action GameStarted; 13 | public static void InvokeGameStarted() { 14 | _Logger.Debug(nameof(GameStarted)); 15 | GameStarted?.Invoke(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Core/Paths.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using UnityEngine; 4 | 5 | namespace ModTheGungeon { 6 | public static class Paths { 7 | private static string _GameFolder; 8 | public static string GameFolder { 9 | get { 10 | if (_GameFolder != null) return _GameFolder; 11 | return _GameFolder = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); 12 | } 13 | } 14 | 15 | private static string _ManagedFolder; 16 | public static string ManagedFolder { 17 | get { 18 | if (_ManagedFolder != null) return _ManagedFolder; 19 | return _ManagedFolder = Path.GetDirectoryName(typeof(ModTheGungeon.Paths).Assembly.Location); 20 | } 21 | } 22 | 23 | private static string _ResourcesFolder; 24 | public static string ResourcesFolder { 25 | get { 26 | if (_ResourcesFolder != null) return _ResourcesFolder; 27 | return _ResourcesFolder = Path.Combine(ManagedFolder, "ModTheGungeon/Resources"); 28 | } 29 | } 30 | 31 | private static string _ModsFolder; 32 | public static string ModsFolder { 33 | get { 34 | if (_ModsFolder != null) return _ModsFolder; 35 | return _ModsFolder = Path.Combine(GameFolder, "Mods"); 36 | } 37 | } 38 | 39 | private static string _CacheFolder; 40 | public static string CacheFolder { 41 | get { 42 | if (_CacheFolder != null) return _CacheFolder; 43 | return _CacheFolder = Path.Combine(GameFolder, ".ModTheGungeonCache"); 44 | } 45 | } 46 | 47 | private static string _ModsOrderFile; 48 | public static string ModsOrderFile { 49 | get { 50 | if (_ModsOrderFile != null) return _ModsOrderFile; 51 | return _ModsOrderFile = Path.Combine(ModsFolder, "order.txt"); 52 | } 53 | } 54 | 55 | private static string _ModsBlacklistFile; 56 | public static string ModsBlacklistFile { 57 | get { 58 | if (_ModsBlacklistFile != null) return _ModsBlacklistFile; 59 | return _ModsBlacklistFile = Path.Combine(ModsFolder, "blacklist.txt"); 60 | } 61 | } 62 | 63 | private static string _ModsCacheFolder; 64 | public static string ModsCacheFolder { 65 | get { 66 | if (_ModsCacheFolder != null) return _ModsCacheFolder; 67 | return _ModsCacheFolder = Path.Combine(GameFolder, ".ModRelinkCache"); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Core/UnityUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using UnityEngine; 4 | 5 | namespace ModTheGungeon { 6 | public static class UnityUtil { 7 | public static Texture2D LoadTexture2D(byte[] content, string name) { 8 | var tex = new Texture2D(0, 0); 9 | tex.name = name; 10 | tex.LoadImage(content); 11 | tex.filterMode = FilterMode.Point; 12 | return tex; 13 | } 14 | 15 | public static Texture2D LoadTexture2D(string path) { 16 | using (var file = File.OpenRead(path)) { 17 | return LoadTexture2D(new BinaryReader(file).ReadAllBytes(), path); 18 | } 19 | } 20 | 21 | public static Color NewColorRGB(int r, int g, int b) { 22 | return NewColorRGBA(r, g, b, 255); 23 | } 24 | 25 | public static Color NewColorRGBA(int r, int g, int b, int a) { 26 | return new Color(r / 255f, g / 255f, b / 255f, a / 255f); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Extensions/BinaryReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | 5 | public static class BinaryReaderExt { 6 | // http://stackoverflow.com/a/8613300 7 | public static byte[] ReadAllBytes(this BinaryReader reader) { 8 | const int bufferSize = 4096; 9 | using (var ms = new MemoryStream()) { 10 | byte[] buffer = new byte[bufferSize]; 11 | int count; 12 | while ((count = reader.Read(buffer, 0, buffer.Length)) != 0) ms.Write(buffer, 0, count); 13 | return ms.ToArray(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Extensions/String.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.IO; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | using System.Globalization; 7 | 8 | public static class StringExt { 9 | public static bool StartsWithInvariant(this string s, string v, bool ignore_case = false) { 10 | return s.StartsWith(v, StringComparison.InvariantCulture); 11 | } 12 | 13 | public static bool EndsWithInvariant(this string s, string v, bool ignore_case = false) { 14 | return s.EndsWith(v, StringComparison.InvariantCulture); 15 | } 16 | 17 | public static string ToPlatformPath(this string s) { 18 | return Application.platform == RuntimePlatform.WindowsPlayer ? s : s.Replace('\\', '/'); 19 | } 20 | 21 | public static string RemovePrefix(this string s, string prefix) { 22 | return s.EndsWithInvariant(prefix) ? s.Substring(prefix.Length) : s; 23 | } 24 | 25 | public static string RemoveSuffix(this string s, string suffix) { 26 | return s.EndsWithInvariant(suffix) ? s.Substring(0, s.Length - suffix.Length) : s; 27 | } 28 | 29 | public static string ToTitleCaseInvariant(this string s) { 30 | var text_info = CultureInfo.InvariantCulture.TextInfo; 31 | return text_info.ToTitleCase(s); 32 | } 33 | 34 | private static char[] _SeparatorSplitArray = { '\\', '/' }; 35 | public static string NormalizePath(this string path) { 36 | var split = path.Split(_SeparatorSplitArray, StringSplitOptions.RemoveEmptyEntries); 37 | var list = new List(); 38 | 39 | for (int i = 0; i < split.Length; i++) { 40 | var el = split[i]; 41 | 42 | if (el == "..") { 43 | if (list.Count > 0) list.RemoveAt(list.Count - 1); 44 | } else if (el != ".") { 45 | list.Add(el); 46 | } 47 | } 48 | 49 | return string.Join("/", list.ToArray()); 50 | } 51 | 52 | //used in IDPool.cs/VerifyID 53 | public static int Count(this string @in, char c) 54 | { 55 | int count = 0; 56 | for (int i = 0; i < @in.Length; i++) 57 | { 58 | if (@in[i] == c) count++; 59 | } 60 | return count; 61 | } 62 | 63 | public static string FirstFromSplit(this string source, char delimiter) { 64 | var i = source.IndexOf(delimiter); 65 | 66 | return i == -1 ? source : source.Substring(0, i); 67 | } 68 | 69 | public static string FirstFromSplit(this string source, string delimiter) { 70 | var i = source.IndexOf(delimiter, StringComparison.InvariantCulture); 71 | 72 | return i == -1 ? source : source.Substring(0, i); 73 | } 74 | 75 | public struct SplitPair { 76 | public string FirstElement; 77 | public string EverythingElse; // can be null! 78 | } 79 | 80 | public static SplitPair SplitIntoPair(this string source, string delimiter) { 81 | var i = source.IndexOf(delimiter, StringComparison.InvariantCulture); 82 | 83 | if (i == -1) return new SplitPair { FirstElement = source, EverythingElse = null }; 84 | 85 | return new SplitPair { FirstElement = source.Substring(0, i), EverythingElse = source.Substring(i + 0) }; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Patches/patch_GameManager.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using ModTheGungeon; 6 | using UnityEngine; 7 | using System.Reflection; 8 | using MonoMod; 9 | 10 | namespace ModTheGungeon.CorePatches { 11 | [MonoModPatch("global::GameManager")] 12 | internal class GameManager : global::GameManager { 13 | protected extern void orig_Awake(); 14 | private void Awake() { 15 | Loader.Logger.Info("GameManager is alive"); 16 | 17 | for (int i = 0; i < Backend.AllBackends.Count; i++) { 18 | var backend = Backend.AllBackends[i]; 19 | Loader.Logger.Info($"Running PreGameManagerAlive on backend {backend.Name} {backend.StringVersion}"); 20 | try { 21 | backend.Instance.PreGameManagerAlive(); 22 | } catch (Exception e) { 23 | Loader.Logger.Error($"Exception while running PreGameManagerAlive on backend {backend.Name}: [{e.GetType().Name}] {e.Message}"); 24 | foreach (var l in e.StackTrace.Split('\n')) Loader.Logger.ErrorIndent(l); 25 | } 26 | } 27 | 28 | for (int i = 0; i < Backend.AllBackends.Count; i++) { 29 | var backend = Backend.AllBackends[i]; 30 | Loader.Logger.Info($"Running GameManagerAlive on backend {backend.Name} {backend.StringVersion}"); 31 | try { 32 | backend.Instance.GameManagerAlive(); 33 | } catch (Exception e) { 34 | Loader.Logger.Error($"Exception while running GameManagerAlive on backend {backend.Name}: [{e.GetType().Name}] {e.Message}"); 35 | foreach (var l in e.StackTrace.Split('\n')) Loader.Logger.ErrorIndent(l); 36 | } 37 | } 38 | 39 | orig_Awake(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Assembly-CSharp.Core.mm/src/Patches/patch_MainMenuFoyerController.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using UnityEngine; 6 | using MonoMod; 7 | 8 | namespace ModTheGungeon.CorePatches { 9 | [MonoModPatch("global::MainMenuFoyerController")] 10 | public class MainMenuFoyerController : global::MainMenuFoyerController { 11 | public static MainMenuFoyerController Instance = null; 12 | 13 | private float _orig_height; 14 | 15 | private extern void orig_Awake(); 16 | protected void AddModVersions() { 17 | if (Instance == null) { 18 | Console.WriteLine($"SETTING INSTANCE TO {this}"); 19 | Instance = this; 20 | } 21 | orig_Awake(); 22 | 23 | _orig_height = VersionLabel.Height; 24 | 25 | VersionLabel.Text = $"Gungeon {VersionLabel.Text}"; 26 | VersionLabel.Color = new Color32(255, 255, 255, 255); 27 | VersionLabel.Shadow = true; 28 | VersionLabel.ShadowOffset = new Vector2(1, -1); 29 | VersionLabel.ShadowColor = new Color32(0, 0, 0, 255); 30 | 31 | for (int i = 0; i < ModTheGungeon.Backend.AllBackends.Count; i++) { 32 | var backend = ModTheGungeon.Backend.AllBackends[i]; 33 | AddLine($"{backend.Name} {backend.StringVersion}"); 34 | } 35 | } 36 | 37 | public extern void orig_InitializeMainMenu(); 38 | public new void InitializeMainMenu() { 39 | orig_InitializeMainMenu(); 40 | if (!_Notified) EventHooks.InvokeMainMenuLoadedFirstTime(this); 41 | _Notified = true; 42 | } 43 | 44 | private bool _Notified = false; 45 | protected void core_Awake() { 46 | AddModVersions(); 47 | } 48 | 49 | private void Awake() { 50 | core_Awake(); 51 | } 52 | 53 | public void AddLine(string line) { 54 | if (VersionLabel.Text.Length > 0) { 55 | VersionLabel.Text += $"\n{line}"; 56 | } else { 57 | VersionLabel.Text = line; 58 | } 59 | 60 | VersionLabel.Position = new UnityEngine.Vector3(VersionLabel.Position.x, _orig_height - VersionLabel.Height); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/Assembly-CSharp.TexMod.mm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {8EB10C26-9773-4FB6-93BA-CA0219701A78} 7 | Library 8 | TexMod 9 | Assembly-CSharp.TexMod.mm 10 | v3.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | true 24 | bin\Release 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | 31 | 32 | ..\libs\Assembly-CSharp.dll 33 | 34 | 35 | ..\libs\UnityEngine.dll 36 | 37 | 38 | ..\libs\UnityEngine.CoreModule.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {4473AD38-DAF1-449A-A850-4296D3368413} 55 | Assembly-CSharp.Core.mm 56 | 57 | 58 | {BF32DE1B-6276-4341-B212-F8862ADBBA7A} 59 | YamlDotNet 60 | 61 | 62 | {8A17C958-5C33-4035-AF76-F94A3AA2DC4F} 63 | MonoMod 64 | 65 | 66 | {34E81F62-F88C-44EF-96D9-DBBD2C46DF34} 67 | Assembly-CSharp.Base.mm 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("Assembly_CSharp.TexMod.mm")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/Patches/DF_Ident/patch_MainMenuFoyerController.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using MonoMod; 6 | 7 | namespace TexMod.Patches { 8 | [MonoModPatch("global::MainMenuFoyerController")] 9 | public class MainMenuFoyerController : ModTheGungeon.CorePatches.MainMenuFoyerController { 10 | private extern void orig_Awake(); 11 | 12 | private void IdentifyDFTitleCard() { 13 | TexMod.Logger.Debug($"DF Pre-ident: MainMenuFoyerController"); 14 | 15 | // pre-ident df sprites 16 | ((patch_dfTextureSprite)TitleCard).TexModInitDFFake( 17 | fake_collection_name: "TitleScreenCollection", 18 | fake_definition_name: "title_words_black_001" 19 | ); 20 | 21 | orig_Awake(); 22 | } 23 | 24 | private void Awake() { 25 | IdentifyDFTitleCard(); 26 | core_Awake(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/Patches/patch_GameObject.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using UnityEngine; 6 | 7 | public class patch_GameObject { 8 | extern public Component orig_AddComponent(Type componentType); 9 | public Component AddComponent(Type componentType) { 10 | var component = orig_AddComponent(componentType); 11 | if (component is tk2dBaseSprite) { 12 | ((patch_tk2dBaseSprite)component).TexModPatch(); 13 | } else if (component is tk2dSpriteAnimator) { 14 | ((patch_tk2dSpriteAnimator)component).TexModPatch(); 15 | } else if (component is tk2dSpriteCollectionData) { 16 | ((patch_tk2dSpriteCollectionData)component).TexModPatch(); 17 | } 18 | return component; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/Patches/patch_dfTextureSprite.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | // this patch makes it possible to provide a sort-of cross between tk2d and df 5 | // where texmod patch collections can also patch df sprites assuming they are 6 | // pre-identified by ModTheGungeon 7 | 8 | // TODO offsx and offsy not supported 9 | 10 | public class patch_dfTextureSprite : dfTextureSprite { 11 | private string _texmod_fake_collname; 12 | private string _texmod_fake_defname; 13 | 14 | private Texture _texmod_saved_texture; 15 | private float _texmod_saved_width; 16 | private float _texmod_saved_height; 17 | private Material _texmod_saved_material; 18 | private Rect _texmod_saved_croprect; 19 | private bool _texmod_saved_croptexture; 20 | 21 | private bool _texmod_init = false; 22 | 23 | public void TexModUnpatch() { 24 | Texture = _texmod_saved_texture; 25 | Material = _texmod_saved_material; 26 | //TexMod.TexMod.Logger.Debug($"relpos1 {RelativePosition}"); 27 | //RelativePosition -= _texmod_saved_translation; 28 | Width = _texmod_saved_width; 29 | Height = _texmod_saved_height; 30 | CropTexture = _texmod_saved_croptexture; 31 | CropRect = _texmod_saved_croprect; 32 | 33 | _texmod_init = false; 34 | } 35 | 36 | public new void Start() { 37 | TexModPatch(); 38 | } 39 | 40 | public void TexModPatch() { 41 | // TODO fix cropping and offsets here 42 | 43 | if (_texmod_init) return; 44 | if (_texmod_fake_collname == null || _texmod_fake_defname == null) return; 45 | _texmod_init = true; 46 | 47 | _texmod_saved_texture = Texture; 48 | _texmod_saved_material = Material; 49 | 50 | _texmod_saved_width = Width; 51 | _texmod_saved_height = Height; 52 | _texmod_saved_croprect = CropRect; 53 | _texmod_saved_croptexture = CropTexture; 54 | 55 | GUIManager.UIScale = 1f; 56 | 57 | TexMod.TexMod.AddPatchedObject(this); 58 | 59 | ModTheGungeon.Animation.Collection collection; 60 | TexMod.TexMod.Logger.Debug($"Looking for DF fake TexMod sprite collection ('{_texmod_fake_collname}')"); 61 | if (TexMod.TexMod.CollectionMap.TryGetValue(_texmod_fake_collname, out collection)) { 62 | TexMod.TexMod.Logger.Debug($"DF fake collection found, searching for definition '{_texmod_fake_defname}'"); 63 | var idx = collection.GetSpriteDefinitionIndex(_texmod_fake_defname); 64 | if (idx != null) { 65 | TexMod.TexMod.Logger.Debug($"DF fake definition found! Patching."); 66 | 67 | var def = (ModTheGungeon.BasePatches.tk2dSpriteDefinition)collection.CollectionData.spriteDefinitions[idx.Value]; 68 | Texture = def.material.mainTexture; 69 | Material = def.material; 70 | 71 | Width = def.ModTheGungeonCropWidth * def.ModTheGungeonScaleW; 72 | Height = def.ModTheGungeonCropHeight * def.ModTheGungeonScaleH; 73 | 74 | CropRect = new Rect( 75 | def.ModTheGungeonCropX, 76 | def.ModTheGungeonCropY, 77 | def.ModTheGungeonCropWidth, 78 | def.ModTheGungeonCropHeight 79 | ); 80 | CropTexture = true; 81 | } 82 | } else { 83 | TexMod.TexMod.Logger.Debug("Not found."); 84 | } 85 | } 86 | public void TexModInitDFFake(string fake_collection_name, string fake_definition_name) { 87 | _texmod_fake_defname = fake_definition_name; 88 | _texmod_fake_collname = fake_collection_name; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/Patches/patch_tk2dBaseSprite.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using System.Collections; 6 | using UnityEngine; 7 | using ModTheGungeon; 8 | 9 | public abstract class patch_tk2dBaseSprite : tk2dBaseSprite { 10 | private void Start() { 11 | if (!Animation.Collection.AllCollections.ContainsKey(Collection.spriteCollectionName)) 12 | { 13 | Animation.Collection.AllCollections.Add(Collection.spriteCollectionName, Collection); 14 | } 15 | TexModPatch(); 16 | } 17 | 18 | public void TexModUnpatch() { 19 | if (Collection != null) { 20 | ((patch_tk2dSpriteCollectionData)Collection).TexModUnpatch(); 21 | } 22 | if (spriteAnimator != null) ((patch_tk2dSpriteAnimator)spriteAnimator).TexModUnpatch(); 23 | 24 | Build(); 25 | UpdateMaterial(); 26 | UpdateCollider(); 27 | UpdateColors(); 28 | UpdateVertices(); 29 | } 30 | 31 | public void TexModPatch() { 32 | if (Collection != null) { 33 | ((patch_tk2dSpriteCollectionData)Collection).TexModPatch(); 34 | } 35 | if (spriteAnimator != null) ((patch_tk2dSpriteAnimator)spriteAnimator).TexModPatch(); 36 | 37 | Build(); 38 | UpdateMaterial(); 39 | UpdateCollider(); 40 | UpdateColors(); 41 | UpdateVertices(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/Patches/patch_tk2dSpriteAnimator.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using MonoMod; 6 | using TexMod; 7 | using System.Collections.Generic; 8 | using ModTheGungeon; 9 | 10 | abstract public class patch_tk2dSpriteAnimator : tk2dSpriteAnimator { 11 | private bool _texmod_init = false; 12 | 13 | private tk2dSpriteAnimator _texmod_saved_animator; 14 | private tk2dSpriteCollectionData _texmod_saved_collection; 15 | private tk2dSpriteDefinition[] _texmod_saved_definitions; 16 | private tk2dSpriteAnimationClip[] _texmod_saved_clips; 17 | private tk2dSpriteAnimationFrame[][] _texmod_saved_frames; 18 | private float _texmod_saved_clipfps; 19 | 20 | public string TexModName { 21 | get { 22 | return TexMod.TexMod.GenerateSpriteAnimationName(gameObject.GetComponent()); 23 | } 24 | } 25 | 26 | extern private void orig_Start(); 27 | private void Start() { 28 | orig_Start(); 29 | 30 | TexModPatch(); 31 | } 32 | 33 | public void Patch(Animation patch) { 34 | TexMod.TexMod.AnimationMap[TexModName] = patch; 35 | TexModPatch(); 36 | } 37 | 38 | public void Unpatch() { 39 | TexModUnpatch(); 40 | } 41 | 42 | public void TexModUnpatch() { 43 | if (!_texmod_init) return; 44 | 45 | _texmod_init = false; 46 | var collection = gameObject.GetComponent().Collection; 47 | 48 | Animation.CopyAnimator(_texmod_saved_animator, this); 49 | Animation.CopyCollection(_texmod_saved_collection, collection); 50 | 51 | Library.clips = _texmod_saved_clips; 52 | for (int i = 0; i < Library.clips.Length; i++) { 53 | Library.clips[i].frames = _texmod_saved_frames[i]; 54 | } 55 | 56 | collection.spriteDefinitions = _texmod_saved_definitions; 57 | ClipFps = _texmod_saved_clipfps; 58 | } 59 | 60 | public void TexModPatch() { 61 | if (_texmod_init) return; 62 | 63 | Animation anim; 64 | if (TexMod.TexMod.AnimationMap.TryGetValue(TexModName, out anim)) { 65 | _texmod_init = true; 66 | 67 | TexMod.TexMod.AddPatchedObject(this); 68 | 69 | var collection = gameObject.GetComponent().Collection; 70 | 71 | _texmod_saved_animator = new tk2dSpriteAnimator(); 72 | _texmod_saved_collection = new tk2dSpriteCollectionData(); 73 | _texmod_saved_definitions = (tk2dSpriteDefinition[])collection.spriteDefinitions.Clone(); 74 | _texmod_saved_clips = (tk2dSpriteAnimationClip[])Library.clips.Clone(); 75 | _texmod_saved_clipfps = ClipFps; 76 | 77 | _texmod_saved_frames = (tk2dSpriteAnimationFrame[][])Array.CreateInstance(typeof(tk2dSpriteAnimationFrame[]), Library.clips.Length); 78 | for (int i = 0; i < Library.clips.Length; i++) { 79 | _texmod_saved_frames[i] = (tk2dSpriteAnimationFrame[])Library.clips[i].frames.Clone(); 80 | } 81 | Animation.CopyAnimator(this, _texmod_saved_animator); 82 | Animation.CopyCollection(collection, _texmod_saved_collection); 83 | 84 | TexMod.TexMod.Logger.Debug($"Found patch animation '{TexModName}'"); 85 | 86 | anim.PatchAnimator(spriteAnimator); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/Patches/patch_tk2dSpriteCollectionData.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System; 5 | using ModTheGungeon; 6 | using MonoMod; 7 | 8 | [MonoModPatch("global::tk2dSpriteCollectionData")] 9 | public class patch_tk2dSpriteCollectionData : global::tk2dSpriteCollectionData { 10 | private bool _texmod_init = false; 11 | private tk2dSpriteCollectionData _texmod_saved_collection; 12 | 13 | private void Start() { 14 | TexModPatch(); 15 | } 16 | 17 | public void TexModUnpatch() { 18 | if (!_texmod_init) return; 19 | 20 | _texmod_init = false; 21 | Animation.CopyCollection(_texmod_saved_collection, this); 22 | } 23 | 24 | public void TexModPatch() { 25 | if (_texmod_init) return; 26 | 27 | Animation.Collection collection; 28 | if (TexMod.TexMod.CollectionMap.TryGetValue(name, out collection)) { 29 | _texmod_init = true; 30 | 31 | TexMod.TexMod.AddPatchedObject(this); 32 | 33 | _texmod_saved_collection = new tk2dSpriteCollectionData(); 34 | Animation.CopyCollection(this, _texmod_saved_collection); 35 | 36 | TexMod.TexMod.Logger.Debug($"Found patch collection '{name}', sprite defs: {spriteDefinitions.Length}"); 37 | collection.PatchCollection(this); 38 | TexMod.TexMod.Logger.Debug($"Sprite defs after patching: {spriteDefinitions.Length}"); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Assembly-CSharp.TexMod.mm/src/TexMod/TexModExtra.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using YamlDotNet.Serialization; 3 | 4 | namespace TexMod { 5 | public class TexModExtra { 6 | [YamlMember(Alias = "dir")] 7 | public string Dir { get; set; } = "texmod"; 8 | 9 | [YamlMember(Alias = "animations")] 10 | public string Animations { get; set; } = "animations"; 11 | 12 | [YamlMember(Alias = "collections")] 13 | public string Collections { get; set; } = "collections"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Plugins/Linux/32/liblua5.1.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Plugins/Linux/32/liblua5.1.so -------------------------------------------------------------------------------- /Plugins/Linux/64/liblua5.1.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Plugins/Linux/64/liblua5.1.so -------------------------------------------------------------------------------- /Plugins/MacOS/lua5.1.bundle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Plugins/MacOS/lua5.1.bundle -------------------------------------------------------------------------------- /Plugins/Windows/32/lua5.1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Plugins/Windows/32/lua5.1.dll -------------------------------------------------------------------------------- /Plugins/Windows/64/lua5.1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Plugins/Windows/64/lua5.1.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mod the Gungeon 2 | === 3 | 4 | A modding platform for [Enter the Gungeon](http://enterthegungeon.com) by [Dodgeroll Studios](http://dodgeroll.com), published by [Devolver Digital](http://devolverdigital.com/). 5 | 6 | ### For end users 7 | 8 | #### What does this add to the game? 9 | 10 | By itself, nothing except a title screen. This is a mod loader - intended to be a base for mods to run, not a mod by itself. 11 | 12 | #### How does this work? 13 | 14 | If you're interested in the actual details, you can check the "For developers" section below. To simplify it, you run the [installer](https://github.com/ModTheGungeon/Installer.Headless), which modifies the game to insert all of this code into it. Then, when you start the game, Mod the Gungeon is started "inside" of it, with the ability to access anything from the game. It'll then start loading mods and doing all of the things it needs to do. 15 | 16 | #### Who's working on this? 17 | 18 | You can check the members of the Mod the Gungeon GitHub organization [here](https://github.com/orgs/ModTheGungeon/people). Note that, while there are 5 people there, 2 have officially quit the project while others remain mostly dormant. In other words, at this moment I'm pretty much the only person working on Mod the Gungeon. 19 | 20 | #### Does this work for the latest update? Is this different from the version in the installer? 21 | 22 | Currently, the master branch (the branch you're seeing above) of this repository houses a version of Mod the Gungeon dubbed "Mod the Gungeon Reloaded". Mod the Gungeon Reloaded is a mod rewritten completely from scratch, with almost no code taken from the original Mod the Gungeon. The version that's currently available in the installer is an outdated version of the old Mod the Gungeon that was updated only to run on the latest Gungeon update (but it doesn't even have its new items as `give` command IDs). 23 | 24 | #### What are the differences between the "classic Mod the Gungeon" and Mod the Gungeon Reloaded? 25 | 26 | Mod the Gungeon has moved away from C# mods in favor of **Lua** mods. This, while slightly complicating the code, allows for a greater amount of control over mods by Mod the Gungeon and makes writing mods a lot easier. For example, I was able to implement the ability to reload mods without restarting the game, saving both the mod developers' and the end users' time. Mods are now also sandboxed, so that they can't just delete all of your files. 27 | 28 | #### How do I install this (Mod the Gungeon Reloaded)? 29 | 30 | Since it's a work in progress, there isn't even a beta release yet. If you think you'll be able to do it, you can try building this repository (use the `build.sh` script or the `build.bat` script **[NOTE: the build.bat script isn't finished yet]**; you'll need to have Visual Studio or Mono installed). Then you can select the resulting `MTG-DIST.zip` in the Advanced tab in the installer, install, and have fun. 31 | 32 | 33 | ### For developers 34 | 35 | #### Licensing 36 | The `LICENSE_MODTHEGUNGEON` file contains the licenses of the projects used by Mod the Gungeon. If an external project is used by Mod the Gungeon and its license is not in `LICENSE_MODTHEGUNGEON`, then it is an oversight and I ask you to report it on the issue tracker. 37 | 38 | #### Legality 39 | Dodgeroll Studios is fully aware of Mod the Gungeon's existence and goals. For the foreseeable future, there shouldn't be any worries about whether Mod the Gungeon would be forced to have its development stopped. 40 | 41 | #### Underlying technology 42 | * Enter the Gungeon is written in C# using the Unity Engine. 43 | * Mod the Gungeon is written in C#. 44 | * [MonoMod](https://github.com/0x0ade/MonoMod) - The ultimate CLR assembly patcher. 45 | * [A fork of Eluant](https://github.com/modthegungeon/Eluant) - CLR/Lua bindings with a focus on stability, memory conservatism and with the best error reporting out of all other Lua bindings for the CLR. 46 | * [YamlDotNet](https://github.com/aaubry/YamlDotNet) - The best YAML parser for the CLR. 47 | * [SGUI](https://github.com/ModTheGungeon/SGUI) - Scriptable GUI for Unity mods. 48 | 49 | #### What are mods written in? 50 | 51 | Lua. 52 | 53 | #### Tutorials 54 | 55 | Mod the Gungeon Reloaded is WIP, so no tutorials yet. Sorry! 56 | 57 | #### Resources 58 | 59 | * [Official WIP website](https://modthegungeon.zatherz.eu/) 60 | (for the time being, hosted on my private web server) 61 | * [**Very** WIP API reference](https://modthegungeon.zatherz.eu/gungeonapidocs/) 62 | (doesn't have Mod the Gungeon classes yet, the look and feel will change soon) 63 | * [Discord channel](https://discord.gg/ngkYDes) 64 | * [My barely-updated blog](https://zatherz.eu/blogs/) which contains some techniques and tools used by Mod the Gungeon 65 | -------------------------------------------------------------------------------- /Resources/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Resources/bullet.png -------------------------------------------------------------------------------- /Resources/logo.coll.yml: -------------------------------------------------------------------------------- 1 | # Mod the Gungeon title collection patch 2 | name: TitleScreenCollection 3 | spritesheet: logo.png 4 | 5 | definitions: 6 | title_words_black_001: 7 | scalew: 1.5 8 | scaleh: 1.5 9 | w: 437 10 | h: 163 11 | x: 0 12 | y: 0 13 | -------------------------------------------------------------------------------- /Resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/Resources/logo.png -------------------------------------------------------------------------------- /Resources/lua/env.lua: -------------------------------------------------------------------------------- 1 | -- this file is loaded by Mod the Gungeon 2 | -- and it's used to setup a base environment for mods 3 | -- editing this file has a high chance of breaking mods 4 | 5 | -- There's a MOD global available in here 6 | -- with the current mod's ModInfo 7 | 8 | local _MOD = MOD -- make it an upvalue 9 | local env = { 10 | Triggers = {}, 11 | Mod = MOD, 12 | Logger = MOD.Logger, 13 | Assemblies = {} 14 | } 15 | 16 | local gungeon = interop.assembly "Assembly-CSharp" 17 | local unity = interop.assembly "UnityEngine" 18 | 19 | env.Assemblies.Gungeon = gungeon; 20 | env.Assemblies.UnityEngine = unity; 21 | env.Assemblies.System = interop.assembly "System"; 22 | env.Assemblies.Mscorlib = interop.assembly "mscorlib"; 23 | 24 | local ns_mtg = interop.namespace(gungeon, 'ModTheGungeon') 25 | local function namespace(ass, name, tab) 26 | return setmetatable(tab, { 27 | __index = interop.namespace(ass, name) 28 | }) 29 | end 30 | 31 | local _GAME = namespace(gungeon, "-", { 32 | ModTheGungeon = namespace(gungeon, "ModTheGungeon", { 33 | GUI = interop.namespace(gungeon, 'ModTheGungeon.GUI'), 34 | Lua = interop.namespace(gungeon, 'ModTheGungeon.Lua'), 35 | Console = namespace(gungeon, "ModTheGungeon.Console", { 36 | Parser = interop.namespace(gungeon, 'ModTheGungeon.Console') 37 | }), 38 | TexMod = interop.namespace(gungeon, 'ModTheGungeon.TexMod') 39 | }) 40 | }) 41 | env._GAME = _GAME 42 | 43 | -- for k, v in pairs(luanet.namespace {'ModTheGungeon.Lua'}) do 44 | -- env[k] = v 45 | -- end 46 | 47 | local lua = interop.namespace(gungeon, 'ModTheGungeon.Lua') 48 | env = setmetatable(env, { 49 | __index = function(self, k) 50 | if k == "PrimaryPlayer" then 51 | return lua.Globals.PrimaryPlayer 52 | elseif k == "SecondaryPlayer" then 53 | return lua.Globals.SecondaryPlayer 54 | end 55 | end 56 | }) 57 | 58 | local gui = interop.namespace(gungeon, 'ModTheGungeon.GUI') 59 | local mtg = interop.namespace(gungeon, 'ModTheGungeon') 60 | 61 | function env.Color(r, g, b, a) 62 | if a == nil then 63 | return mtg.UnityUtil.NewColorRGB(r, g, b) 64 | else 65 | return mtg.UnityUtil.NewColorRGBA(r, g, b, a) 66 | end 67 | end 68 | 69 | function env.Notify(data) 70 | if type(data) ~= "table" then 71 | error("Notification data must be a table") 72 | end 73 | 74 | if data.title == nil or data.content == nil then 75 | error("Notification must have a title and content") 76 | end 77 | local notif = gui.Notification(data.title, data.content) 78 | 79 | if data.image then 80 | notif.Image = data.image 81 | end 82 | if data.background_color then 83 | notif.BackgroundColor = data.background_color 84 | end 85 | if data.title_color then 86 | notif.TitleColor = data.title_color 87 | end 88 | if data.content_color then 89 | notif.ContentColor = data.content_color 90 | end 91 | 92 | gui.GUI.NotificationController:Notify(notif) 93 | end 94 | 95 | function env.Hook(method, func) 96 | _MOD.Hooks:Add(method, func) 97 | end 98 | 99 | require("sandbox")(env) 100 | 101 | return env; -------------------------------------------------------------------------------- /Resources/lua/sandbox.lua: -------------------------------------------------------------------------------- 1 | local sep = package.config:sub(1,1) 2 | local function searchpath (mod,path) 3 | mod = mod:gsub('%.',sep) 4 | for m in path:gmatch('[^;]+') do 5 | local nm = m:gsub('?',mod) 6 | local f = io.open(nm,'r') 7 | if f then f:close(); return nm end 8 | end 9 | end 10 | -- https://github.com/stevedonovan/Penlight/blob/master/lua/pl/compat.lua 11 | -- penlight is licensed under the MIT license 12 | -- https://github.com/stevedonovan/Penlight/blob/master/LICENSE.md 13 | 14 | return function(env) 15 | local function include(name) 16 | env[name] = _G[name] 17 | end 18 | 19 | env._G = env 20 | 21 | include "assert" 22 | include "error" 23 | include "pairs" 24 | include "ipairs" 25 | include "next" 26 | include "pcall" 27 | 28 | env.print = function(...) 29 | local args = {...} 30 | local len = select('#', ...) 31 | local s = "" 32 | 33 | for x = 1, len do 34 | s = s .. tostring(args[x]) 35 | if x ~= len then 36 | s = s .. "\t" 37 | end 38 | end 39 | 40 | env.Logger:Info(s) 41 | end 42 | 43 | include "select" 44 | include "tonumber" 45 | include "tostring" 46 | include "type" 47 | include "unpack" 48 | include "_VERSION" 49 | env._MTG = true 50 | include "xpcall" 51 | 52 | env.coroutine = { 53 | create = coroutine.create, 54 | resume = coroutine.resume, 55 | running = coroutine.running, 56 | status = coroutine.status, 57 | wrap = coroutine.wrap, 58 | yield = coroutine.yield 59 | } 60 | 61 | env.string = { 62 | byte = string.byte, 63 | char = string.char, 64 | dump = string.dump, 65 | find = string.find, 66 | format = string.format, 67 | gmatch = string.gmatch, 68 | gsub = string.gsub, 69 | len = string.len, 70 | lower = string.lower, 71 | match = string.match, 72 | rep = string.rep, 73 | reverse = string.reverse, 74 | sub = string.sub, 75 | upper = string.upper 76 | } 77 | 78 | env.table = { 79 | insert = table.insert, 80 | maxn = table.maxn, 81 | remove = table.remove, 82 | sort = table.sort 83 | } 84 | 85 | local system = interop.namespace(interop.assembly('mscorlib'), 'System') 86 | local rng = system.Random() 87 | 88 | env.math = { 89 | abs = math.abs, 90 | acos = math.acos, 91 | asin = math.asin, 92 | atan = math.atan, 93 | atan2 = math.atan2, 94 | ceil = math.ceil, 95 | cos = math.cos, 96 | cosh = math.cosh, 97 | deg = math.deg, 98 | exp = math.exp, 99 | floor = math.floor, 100 | fmod = math.fmod, 101 | frexp = math.frexp, 102 | huge = math.huge, 103 | ldexp = math.ldexp, 104 | log = math.log, 105 | log10 = math.log10, 106 | max = math.max, 107 | min = math.min, 108 | modf = math.modf, 109 | pi = math.pi, 110 | pow = math.pow, 111 | rad = math.rad, 112 | sin = math.sin, 113 | sinh = math.sinh, 114 | sqrt = math.sqrt, 115 | tan = math.tan, 116 | tanh = math.tanh, 117 | 118 | random = function(a, b) 119 | if a == nil and b == nil then 120 | return rng:NextDouble() 121 | elseif b == nil then 122 | return rng:Next(1, a + 1) 123 | else 124 | return rng:Next(a, b + 1) 125 | end 126 | end, 127 | randomseed = function(seed) 128 | rng = system.Random(seed) 129 | end 130 | } 131 | 132 | env.os = { 133 | clock = os.clock, 134 | date = os.date, 135 | difftime = os.difftime, 136 | time = os.time, 137 | } 138 | 139 | env.interop = { 140 | -- assembly = clr.assembly, 141 | type = interop.type, 142 | namespace = interop.namespace, 143 | --metatype = clr.metatype, 144 | --statictype = clr.statictype, 145 | --unrestricted = clr.unrestricted 146 | } 147 | 148 | local _require = require 149 | 150 | 151 | function env.require(name) 152 | -- local formatted_name = name:gsub("[%./\\]+", "/") -- replace all series of dots or slashes with a single slash 153 | -- if #formatted_name > 0 then 154 | -- if formatted_name[1] == "/" then 155 | -- formatted_name = formatted_name:sub(2) 156 | -- end 157 | -- if formatted_name[#formatted_name] == "/" then 158 | -- formatted_name = formatted_name:sub(1, #formatted_name - 1) 159 | -- end 160 | -- end 161 | local path, err = searchpath(name, env.package.path) 162 | if err then error(err) end 163 | 164 | if env.package.loaded[path] then return env.package.loaded[path] end 165 | 166 | local f = loadfile(path, "t", env) 167 | 168 | env.package.loaded[path] = f() 169 | return env.package.loaded[path] 170 | end 171 | end 172 | -------------------------------------------------------------------------------- /Resources/prefabric_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Import Test", 3 | "version": 1, 4 | "transform": { 5 | "type": { 6 | "assembly": "UnityEngine", 7 | "name": "UnityEngine.Transform" 8 | }, 9 | "data": {} 10 | }, 11 | "components": [ 12 | { 13 | "id": "Test 1", 14 | "type": { 15 | "assembly": "Assembly-CSharp", 16 | "name": "ModTheGungeon.PrefabricTest" 17 | }, 18 | "data": { 19 | "A": 1, 20 | "B": "Hello", 21 | "C": { 22 | "type": { 23 | "assembly": "Assembly-CSharp", 24 | "name": "ModTheGungeon.PrefabricTest+InnerObject" 25 | }, 26 | "data": { 27 | "A": 42, 28 | "B": "Hello" 29 | } 30 | }, 31 | "StringAry": { 32 | "array_type": { 33 | "assembly": "mscorlib", 34 | "name": "System.String" 35 | }, 36 | "entries": [ 37 | "A", 38 | "B", 39 | "C", 40 | "Hello" 41 | ] 42 | }, 43 | "ObjectAry": { 44 | "array_type": { 45 | "assembly": "Assembly-CSharp", 46 | "name": "ModTheGungeon.PrefabricTest+InnerObject" 47 | }, 48 | "entries": [ 49 | { 50 | "type": { 51 | "assembly": ".", 52 | "name": "." 53 | }, 54 | "data": { 55 | "A": 42, 56 | "B": "Bye" 57 | } 58 | }, 59 | { 60 | "type": { 61 | "assembly": ".", 62 | "name": "." 63 | }, 64 | "data": { 65 | "A": 999, 66 | "B": "XXX" 67 | } 68 | } 69 | ] 70 | }, 71 | "ObjectDict": { 72 | "collection_type": { 73 | "assembly": "mscorlib", 74 | "name": "System.Collections.Generic.Dictionary`2", 75 | "generic_params": [ 76 | { 77 | "assembly": "mscorlib", 78 | "name": "System.String" 79 | }, 80 | { 81 | "assembly": "Assembly-CSharp", 82 | "name": "ModTheGungeon.PrefabricTest+InnerObject" 83 | } 84 | ], 85 | "element_types": [ 86 | { 87 | "assembly": "mscorlib", 88 | "name": "System.String" 89 | }, 90 | { 91 | "assembly": "Assembly-CSharp", 92 | "name": "ModTheGungeon.PrefabricTest+InnerObject" 93 | } 94 | ] 95 | }, 96 | "elements": [ 97 | [ 98 | "A", 99 | { 100 | "type": { 101 | "assembly": "Assembly-CSharp", 102 | "name": "ModTheGungeon.PrefabricTest+InnerObject" 103 | }, 104 | "data": { 105 | "A": 42, 106 | "B": "Hello" 107 | } 108 | } 109 | ], 110 | [ 111 | "Test", 112 | { 113 | "type": { 114 | "assembly": "Assembly-CSharp", 115 | "name": "ModTheGungeon.PrefabricTest+InnerObject" 116 | }, 117 | "data": { 118 | "A": 24, 119 | "B": "olleH" 120 | } 121 | } 122 | ] 123 | ] 124 | }, 125 | "StringList": { 126 | "collection_type": { 127 | "assembly": "mscorlib", 128 | "name": "System.Collections.Generic.List`1", 129 | "generic_params": [ 130 | { 131 | "assembly": "mscorlib", 132 | "name": "System.String" 133 | } 134 | ], 135 | "element_types": [ 136 | { 137 | "assembly": "mscorlib", 138 | "name": "System.String" 139 | } 140 | ] 141 | }, 142 | "elements": [ 143 | [ "Element 1" ], 144 | [ "Element 2" ], 145 | [ "Element 3" ] 146 | ] 147 | } 148 | } 149 | } 150 | ] 151 | } 152 | -------------------------------------------------------------------------------- /UnityEngine.Base.mm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("UnityEngine")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /UnityEngine.Base.mm/UnityEngine.CoreModule.Base.mm.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {BCD03ACB-E715-4A3D-A4C2-C5717A5D41E4} 7 | Library 8 | ModTheGungeon 9 | UnityEngine.CoreModule.Base.mm 10 | v3.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | true 24 | bin\Release 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | 31 | 32 | ..\libs\UnityEngine.dll 33 | 34 | 35 | ..\libs\UnityEngine.CoreModule.dll 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | {8A17C958-5C33-4035-AF76-F94A3AA2DC4F} 50 | MonoMod 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /UnityEngine.Base.mm/src/Extensions/Texture2DExt.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace ModTheGungeon 4 | { 5 | public static class Texture2DExt 6 | { 7 | public static bool IsReadable(this Texture2D texture) 8 | { 9 | #if DEBUG 10 | try 11 | { 12 | texture.GetPixels(); 13 | return true; 14 | } 15 | catch 16 | { 17 | return false; 18 | } 19 | #else 20 | return texture.GetRawTextureData().Length != 0; // spams log 21 | #endif 22 | } 23 | 24 | public static Texture2D GetRW(this Texture2D texture) 25 | { 26 | if (texture == null) 27 | { 28 | return null; 29 | } 30 | if (texture.IsReadable()) 31 | { 32 | return texture; 33 | } 34 | return texture.Copy(); 35 | } 36 | 37 | public static Texture2D Copy(this Texture2D texture, TextureFormat? format = TextureFormat.ARGB32) 38 | { 39 | if (texture == null) 40 | { 41 | return null; 42 | } 43 | RenderTexture copyRT = RenderTexture.GetTemporary( 44 | texture.width, texture.height, 0, 45 | RenderTextureFormat.Default, RenderTextureReadWrite.Default 46 | ); 47 | 48 | Graphics.Blit(texture, copyRT); 49 | 50 | RenderTexture previousRT = RenderTexture.active; 51 | RenderTexture.active = copyRT; 52 | 53 | Texture2D copy = new Texture2D(texture.width, texture.height, format != null ? format.Value : texture.format, 1 < texture.mipmapCount); 54 | copy.name = texture.name; 55 | copy.ReadPixels(new Rect(0, 0, copyRT.width, copyRT.height), 0, 0); 56 | copy.Apply(true, false); 57 | 58 | RenderTexture.active = previousRT; 59 | RenderTexture.ReleaseTemporary(copyRT); 60 | 61 | return copy; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /UnityEngine.Base.mm/src/Patches/patch_Resources.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 0626 2 | #pragma warning disable 0649 3 | 4 | using System.Diagnostics; 5 | using MonoMod; 6 | 7 | namespace UnityEngine { 8 | [MonoModPatch("UnityEngine.Resources")] 9 | internal sealed class Resources { 10 | // TODO 11 | 12 | [MonoModOriginal] 13 | public static extern Object Ooad(string path, System.Type systemTypeInstance); 14 | [MonoModOriginalName("Ooad")] 15 | public static Object Load(string path, System.Type type) { 16 | return Ooad(path, type); 17 | } 18 | 19 | [MonoModOriginal] 20 | public static extern ResourceRequest OoadAsync(string path, System.Type type); 21 | [MonoModOriginalName("OoadAsync")] 22 | public static ResourceRequest LoadAsync(string path, System.Type type) { 23 | return OoadAsync(path, type); 24 | } 25 | 26 | [MonoModOriginal] 27 | public static extern Object[] OoadAll(string path, System.Type systemTypeInstance); 28 | [MonoModOriginalName("OoadAll")] 29 | public static Object[] LoadAll(string path, System.Type type) { 30 | return OoadAll(path, type); 31 | } 32 | 33 | [MonoModOriginal] 34 | public static extern Object OetBuiltinResource(System.Type type, string path); 35 | [MonoModOriginalName("OetBuiltinResource")] 36 | public static Object GetBuiltinResource(System.Type type, string path) { 37 | return OetBuiltinResource(type, path); 38 | } 39 | 40 | [MonoModOriginal] 41 | public static extern void OnloadAsset(Object assetToUnload); 42 | [MonoModOriginalName("OnloadAsset")] 43 | public static void UnloadAsset(Object asset) { 44 | OnloadAsset(asset); 45 | } 46 | 47 | [MonoModOriginal] 48 | public static extern AsyncOperation OnloadUnusedAssets(); 49 | [MonoModOriginalName("OnloadUnusedAssets")] 50 | public static AsyncOperation UnloadUnusedAssets() { 51 | return OnloadUnusedAssets(); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /UnityEngine.Core.mm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("UnityEngine.Core.mm")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /UnityEngine.Core.mm/UnityEngine.CoreModule.Core.mm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {85EEF778-D1A0-4DFD-8B6C-AF6BE334DB92} 7 | Library 8 | ModTheGungeon 9 | UnityEngine.CoreModule.Core.mm 10 | v3.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | true 24 | bin\Release 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | 31 | 32 | ..\libs\UnityEngine.dll 33 | 34 | 35 | ..\libs\UnityEngine.CoreModule.dll 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {8A17C958-5C33-4035-AF76-F94A3AA2DC4F} 49 | MonoMod 50 | 51 | 52 | {1C734127-AC83-4ECB-ABCA-32B98DFE49C7} 53 | Logger 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /UnityEngine.Core.mm/src/Patches/patch_Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MonoMod; 3 | 4 | namespace UnityEngine.Patches { 5 | /// 6 | /// Patches the UnityEngine logger to use ModTheGungeon's logger 7 | /// 8 | [MonoModPatch("UnityEngine.Logger")] 9 | public class Logger { 10 | public static ModTheGungeon.Logger GungeonLogger = new ModTheGungeon.Logger("Gungeon"); 11 | 12 | /// 13 | /// Converts a UnityEngine.LogType to an ModTheGungeon.Logger.LogLevel 14 | /// 15 | /// The ModTheGungeon LogLevel 16 | /// The Unity LogType 17 | private ModTheGungeon.Logger.LogLevel _LogTypeToLogLevel(LogType type) { 18 | switch(type) { 19 | case LogType.Log: return ModTheGungeon.Logger.LogLevel.Info; 20 | case LogType.Assert: return ModTheGungeon.Logger.LogLevel.Error; 21 | case LogType.Error: return ModTheGungeon.Logger.LogLevel.Error; 22 | case LogType.Exception: return ModTheGungeon.Logger.LogLevel.Error; 23 | case LogType.Warning: return ModTheGungeon.Logger.LogLevel.Warn; 24 | default: return ModTheGungeon.Logger.LogLevel.Debug; 25 | } 26 | } 27 | 28 | private string _FormatMessage(object message, string tag = null, Object context = null) { 29 | if (tag != null && context != null) return $"[tag: {tag}, context: {context}] {message}"; 30 | if (tag != null && context == null) return $"[context: {context}] {message}"; 31 | if (tag == null && context != null) return $"[tag: {tag}] {message}"; 32 | return message.ToString(); 33 | } 34 | 35 | public bool IsLogTypeAllowed(LogType logType) { 36 | return GungeonLogger.LogLevelEnabled(_LogTypeToLogLevel(logType)); 37 | } 38 | 39 | public void Log(string tag, object message, Object context) { 40 | GungeonLogger.Info(_FormatMessage(message, tag: tag, context: context)); 41 | } 42 | 43 | public void Log(string tag, object message) { 44 | GungeonLogger.Info(_FormatMessage(message, tag: tag)); 45 | } 46 | 47 | public void Log(object message) { 48 | GungeonLogger.Info(_FormatMessage(message)); 49 | } 50 | 51 | public void Log(LogType logType, string tag, object message, Object context) { 52 | GungeonLogger.Log(_LogTypeToLogLevel(logType), _FormatMessage(message, tag: tag, context: context)); 53 | } 54 | 55 | public void Log(LogType logType, string tag, object message) { 56 | GungeonLogger.Log(_LogTypeToLogLevel(logType), _FormatMessage(message, tag: tag)); 57 | } 58 | 59 | public void Log(LogType logType, object message, Object context) { 60 | GungeonLogger.Log(_LogTypeToLogLevel(logType), _FormatMessage(message, context: context)); 61 | } 62 | 63 | public void Log(LogType logType, object message) { 64 | GungeonLogger.Log(_LogTypeToLogLevel(logType), _FormatMessage(message)); 65 | } 66 | 67 | public void LogError(string tag, object message, Object context) { 68 | GungeonLogger.Error(_FormatMessage(message, tag: tag, context: context)); 69 | } 70 | 71 | public void LogError(string tag, object message) { 72 | GungeonLogger.Error(_FormatMessage(message, tag: tag)); 73 | } 74 | 75 | public void LogException(Exception exception) { 76 | GungeonLogger.Error(_FormatMessage(exception)); 77 | } 78 | 79 | public void LogException(Exception exception, Object context) { 80 | GungeonLogger.Error(_FormatMessage(exception, context: context)); 81 | } 82 | 83 | public void LogWarning(string tag, object message) { 84 | GungeonLogger.Warn(_FormatMessage(message, tag: tag)); 85 | } 86 | 87 | public void LogWarning(string tag, object message, Object context) { 88 | GungeonLogger.Warn(_FormatMessage(message, tag: tag, context: context)); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /build-files: -------------------------------------------------------------------------------- 1 | # external 2 | libs/Ionic.Zip.dll 3 | libs/YamlDotNet/YamlDotNet/bin/{TARGET-UNSIGNED}/YamlDotNet.dll 4 | libs/MonoMod/bin/{TARGET}/MonoMod.exe 5 | libs/MonoMod/packages/Mono.Cecil.0.10.0-beta5/lib/net35/Mono.Cecil.dll 6 | libs/MonoMod/packages/Mono.Cecil.0.10.0-beta5/lib/net35/Mono.Cecil.Mdb.dll 7 | libs/MonoMod/packages/Mono.Cecil.0.10.0-beta5/lib/net35/Mono.Cecil.Pdb.dll 8 | 9 | # in-house but technically external 10 | #libs/Eluant/Eluant/bin/{TARGET}/Eluant.dll 11 | libs/Logger/bin/{TARGET}/Logger.dll 12 | libs/MicroLua/MicroLua/bin/{TARGET}/MicroLua.dll 13 | libs/Prefabric/Prefabric/bin/{TARGET}/Prefabric.dll 14 | libs/Prefabric/Prefabric/bin/{TARGET}/Newtonsoft.Json.dll 15 | libs/Prefabric/Prefabric/bin/{TARGET}/System.Xml.Linq.dll 16 | 17 | # internal [Assembly-CSharp] 18 | Assembly-CSharp.Core.mm/bin/{TARGET}/Assembly-CSharp.Core.mm.dll 19 | Assembly-CSharp.Base.mm/bin/{TARGET}/Assembly-CSharp.Base.mm.dll 20 | Assembly-CSharp.TexMod.mm/bin/{TARGET}/Assembly-CSharp.TexMod.mm.dll 21 | 22 | # internal [UnityEngine] 23 | UnityEngine.Core.mm/bin/{TARGET}/UnityEngine.CoreModule.Core.mm.dll 24 | UnityEngine.Base.mm/bin/{TARGET}/UnityEngine.CoreModule.Base.mm.dll 25 | 26 | # licenses 27 | LICENSE_MODTHEGUNGEON 28 | LICENSE_MONO 29 | 30 | # resources 31 | Resources 32 | 33 | # for the installer 34 | metadata.yml 35 | 36 | # plugins 37 | Plugins 38 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal EnableDelayedExpansion 3 | 4 | :: Requirements 5 | if not exist "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ( 6 | echo ERROR: Microsoft.NET framework 3.5 not found. Make sure you have Virtual Studio installed. 7 | goto _exit 8 | ) 9 | set msbuild="C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" 10 | 11 | set sevenz=7z 12 | if exist "C:\Program Files\7-Zip\7z.exe" ( 13 | set sevenz="C:\Program Files\7-Zip\7z.exe" 14 | goto prep 15 | ) 16 | 17 | if exist "C:\Program Files(x86)\7-Zip\7z.exe" ( 18 | set sevenz="C:\Program Files (x86)\7-Zip\7z.exe" 19 | goto prep 20 | ) 21 | 22 | where 7z >nul 2>nul 23 | if not %errorlevel%==0 ( 24 | echo ERROR: 7zip was not found. Make sure that you have it installed and in the PATH. 25 | goto _exit 26 | ) 27 | 28 | 29 | :prep 30 | set target=Debug 31 | set target_unsigned=Debug 32 | if %1.==release. goto _if_setrelease 33 | goto _ifj_setrelease 34 | :_if_setrelease 35 | set target=Release 36 | set target_unsigned=Release-Unsigned 37 | :_ifj_setrelease 38 | 39 | :: Prepare the build directory 40 | set build_base=build 41 | set build_mtg=MTG-DIST 42 | set "build=%build_base%\%build_mtg%" 43 | set "build_zip=%build_base%\%build_mtg%.zip" 44 | 45 | if exist "%build_base%" rmdir /q /s "%build_base%" 46 | mkdir "%build_base%" 2>nul 47 | mkdir "%build%" 2>nul 48 | 49 | :: Build 50 | where xbuild >nul 2>nul 51 | if %errorlevel%==0 ( 52 | ::call xbuild 53 | rem 54 | ) else ( 55 | call %msbuild% 56 | ) 57 | 58 | for /f "tokens=*" %%L in (build-files) do ( 59 | set "line=%%L" 60 | setlocal enabledelayedexpansion 61 | echo !line! 62 | set str=!line:{TARGET}=%target%! 63 | echo !str! 64 | set "line=!line:/=\!" 65 | endlocal 66 | ) 67 | 68 | rem for /f "tokens=*" %%L in (build-files) do ( 69 | rem set "line=%%L" 70 | rem set "line=!line:/=\!" 71 | rem if not "!line:~0,1!"=="#" ( 72 | rem set "file_ex=!line:{TARGET}=%target%!" 73 | rem set "file=!file_ex:{TARGET-UNSIGNED}=%target_unsigned%!" 74 | rem for %%f in (!file!) do set target=%%~nxf 75 | rem rem 76 | 77 | rem echo !line! 78 | rem set "file_ex=!line:{TARGET}=A!" 79 | rem echo !file_ex! 80 | rem call echo %%line%% 81 | rem echo Copying '!file!' to '%build%/!target!' 82 | 83 | rem for %%i in (!file!) do ( 84 | rem if exist %%~si\nul ( 85 | rem robocopy "!file!" "%build%/!target!" /s /e 86 | rem ) else ( 87 | rem copy "!file!" "%build%/!target!" 88 | rem ) 89 | rem ) 90 | rem ) 91 | rem ) 92 | 93 | :: Zipping it all up 94 | pushd "%build%" 95 | %sevenz% a MTG-DIST.zip * 96 | popd 97 | move "%build%\MTG-DIST.zip" "%build_zip%" 98 | 99 | :: The End 100 | :_exit 101 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | TARGET="Debug" 5 | TARGET_UNSIGNED="$TARGET" 6 | if [ "$1" = "release" ]; then 7 | TARGET="Release" 8 | TARGET_UNSIGNED="Release-Unsigned" 9 | fi 10 | 11 | BUILD_BASE="build" 12 | BUILD_MTG="MTG-DIST" 13 | 14 | BUILD="$BUILD_BASE/$BUILD_MTG" 15 | BUILD_ZIP="$BUILD_BASE/$BUILD_MTG.zip" 16 | 17 | rm -rf $BUILD_BASE 18 | mkdir -p $BUILD 19 | 20 | xbuild /p:Configuration=$TARGET 21 | 22 | deps=() 23 | 24 | while read line; do 25 | if [[ "$line" == "#"* ]]; then continue; fi 26 | deps+=("$(echo "$line" | sed -e "s/{TARGET}/$TARGET/" -e "s/{TARGET-UNSIGNED}/$TARGET_UNSIGNED/")") 27 | done < build-files 28 | 29 | echo "${deps[@]}" 30 | 31 | for d in ${deps[@]}; do 32 | cp -r "$d" "$BUILD" 33 | done 34 | 35 | zip_name="$(mktemp -u -p "." .build-XXXXXXXXX.zip)" 36 | pushd $BUILD 37 | zip -r "$zip_name" * 38 | popd 39 | mv "$BUILD/$zip_name" "$BUILD_ZIP" 40 | -------------------------------------------------------------------------------- /libs/Assembly-CSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/Assembly-CSharp.dll -------------------------------------------------------------------------------- /libs/Ionic.Zip.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/Ionic.Zip.dll -------------------------------------------------------------------------------- /libs/Mono.Cecil.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/Mono.Cecil.dll -------------------------------------------------------------------------------- /libs/UnityEngine.CoreModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.CoreModule.dll -------------------------------------------------------------------------------- /libs/UnityEngine.IMGUIModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.IMGUIModule.dll -------------------------------------------------------------------------------- /libs/UnityEngine.ImageConversionModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.ImageConversionModule.dll -------------------------------------------------------------------------------- /libs/UnityEngine.InputModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.InputModule.dll -------------------------------------------------------------------------------- /libs/UnityEngine.TextRenderingModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.TextRenderingModule.dll -------------------------------------------------------------------------------- /libs/UnityEngine.UIModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.UIModule.dll -------------------------------------------------------------------------------- /libs/UnityEngine.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ModTheGungeon/ETGMod.Reloaded/050a319bec9185d9ab5b9205ed172f0711be35c9/libs/UnityEngine.dll -------------------------------------------------------------------------------- /metadata.yml: -------------------------------------------------------------------------------- 1 | name: ModTheGungeon 2 | install_in_managed: 3 | - LICENSE_MODTHEGUNGEON 4 | - LICENSE_MONO 5 | 6 | ordered_targets: 7 | - UnityEngine.CoreModule 8 | - Assembly-CSharp 9 | 10 | #relink_map: 11 | # Assembly-CSharp: 12 | # UnityEngine.Core.mm: UnityEngine.dll 13 | # UnityEngine.Base.mm: UnityEngine.dll 14 | 15 | --------------------------------------------------------------------------------