├── ModdingTools
├── steam_appid.txt
├── hueh.ico
├── Resources
│ ├── ok.png
│ ├── cook.png
│ ├── dye.png
│ ├── hat.png
│ ├── play.png
│ ├── save.png
│ ├── about.png
│ ├── badge.png
│ ├── close.png
│ ├── compile.png
│ ├── console.png
│ ├── delete.png
│ ├── delete1.png
│ ├── folder.png
│ ├── generic.png
│ ├── heeh_1b.png
│ ├── heeh_2.png
│ ├── heeh_3.png
│ ├── loading.gif
│ ├── msg.app.png
│ ├── msg.exc.png
│ ├── noimage.png
│ ├── refresh.png
│ ├── remix.png
│ ├── steam.png
│ ├── steam1.png
│ ├── sticker.png
│ ├── tools.png
│ ├── weapon.png
│ ├── compile4.gif
│ ├── compncook.png
│ ├── console1.png
│ ├── deathwish.png
│ ├── icon_004.png
│ ├── icon_043.png
│ ├── icon_044.png
│ ├── icon_073.png
│ ├── icon_164.png
│ ├── minimize.png
│ ├── msg.error.png
│ ├── msg.info.png
│ ├── msg.warn.png
│ ├── uploaded.png
│ ├── loading_text.png
│ ├── msg.question.png
│ ├── noimage_wide.png
│ ├── settings-icon.png
│ └── editorcrashedhueh4.png
├── steam_api64.dll
├── Steamworks.NET.dll
├── Logging
│ ├── ILogger.cs
│ ├── Handlers
│ │ ├── DebuggerLogger.cs
│ │ └── CommandLineLogger.cs
│ └── Logger.cs
├── BuildData.cs
├── Engine
│ ├── APNG
│ │ ├── Chunks
│ │ │ ├── IDATChunk.cs
│ │ │ ├── IENDChunk.cs
│ │ │ ├── OtherChunk.cs
│ │ │ ├── acTLChunk.cs
│ │ │ ├── IHDRChunk.cs
│ │ │ ├── fdATChunk.cs
│ │ │ ├── fcTLChunk.cs
│ │ │ └── Chunk.cs
│ │ ├── Helper.cs
│ │ ├── Frame.cs
│ │ └── CrcHelper.cs
│ ├── EditorProcessStateWatchdog.cs
│ ├── UpdateChecker.cs
│ ├── Meme.cs
│ ├── NamedPipe.cs
│ ├── SteamWorkshopStorage.cs
│ ├── ScriptWatcher.cs
│ ├── UModelFacade.cs
│ └── GameFinder.cs
├── Steam
│ ├── AbstractModUploader.AbstractMethods.cs
│ ├── AbstractModUploader.HelperMethods.cs
│ ├── AbstractModUploader.cs
│ └── SteamApiCallback.cs
├── GUI
│ ├── ThemeConstants.cs
│ ├── GUIWorker.cs
│ ├── CategorySpacer.cs
│ ├── ProcessRunner.cs
│ ├── ArgEditorItem.cs
│ ├── ARItem.cs
│ ├── GUIProcessRunner.cs
│ ├── BorderPanel.cs
│ ├── ConfigList.cs
│ ├── HuehProgressBar.cs
│ ├── ARList.cs
│ ├── GUIWorker.Designer.cs
│ ├── ConfigItem.cs
│ └── ContentBrowser.cs
├── packages.config
├── Headless
│ ├── ConsoleProcessRunner.cs
│ └── CommandLineOptions.cs
├── Windows
│ ├── ChangelogWindow.cs
│ ├── AboutWindow.cs
│ ├── Tools
│ │ ├── Benchmark.cs
│ │ └── Benchmark.Designer.cs
│ ├── ArgEditor.cs
│ ├── ConfigWindow.cs
│ ├── Validators
│ │ └── ModdingValidators.cs
│ ├── MapChooser.cs
│ ├── WorkshopLocker.cs
│ ├── ArrayInputWindow.cs
│ └── ArgEditor.Designer.cs
├── Properties
│ ├── AssemblyInfo.cs
│ └── Settings.settings
├── app.config
└── Modding
│ └── ModDirectorySource.cs
├── Create-Release-Files.bat
├── ModdingTools.Cli
├── app.config
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── ModdingTools.Cli.csproj
├── ModdingTools.Updater
├── app.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ └── Resources.Designer.cs
├── ModdingTools.Updater.csproj
├── CUFormEx.cs
├── Program.cs
├── MainWindow.cs
└── OMMHelper.cs
├── HeadlessModeCheatsheet.md
├── Create-Release-Files.ps1
├── README.md
├── OpenModManager.sln
├── .gitattributes
└── .gitignore
/ModdingTools/steam_appid.txt:
--------------------------------------------------------------------------------
1 | 734880
--------------------------------------------------------------------------------
/ModdingTools/hueh.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/hueh.ico
--------------------------------------------------------------------------------
/ModdingTools/Resources/ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/ok.png
--------------------------------------------------------------------------------
/ModdingTools/steam_api64.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/steam_api64.dll
--------------------------------------------------------------------------------
/ModdingTools/Resources/cook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/cook.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/dye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/dye.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/hat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/hat.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/play.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/save.png
--------------------------------------------------------------------------------
/ModdingTools/Steamworks.NET.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Steamworks.NET.dll
--------------------------------------------------------------------------------
/ModdingTools/Resources/about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/about.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/badge.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/close.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/compile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/compile.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/console.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/console.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/delete.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/delete1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/delete1.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/folder.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/generic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/generic.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/heeh_1b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/heeh_1b.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/heeh_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/heeh_2.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/heeh_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/heeh_3.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/loading.gif
--------------------------------------------------------------------------------
/ModdingTools/Resources/msg.app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/msg.app.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/msg.exc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/msg.exc.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/noimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/noimage.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/refresh.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/remix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/remix.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/steam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/steam.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/steam1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/steam1.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/sticker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/sticker.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/tools.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/weapon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/weapon.png
--------------------------------------------------------------------------------
/Create-Release-Files.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | Powershell.exe -executionpolicy remotesigned -File Create-Release-Files.ps1
3 | pause
--------------------------------------------------------------------------------
/ModdingTools/Resources/compile4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/compile4.gif
--------------------------------------------------------------------------------
/ModdingTools/Resources/compncook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/compncook.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/console1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/console1.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/deathwish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/deathwish.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/icon_004.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/icon_004.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/icon_043.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/icon_043.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/icon_044.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/icon_044.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/icon_073.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/icon_073.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/icon_164.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/icon_164.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/minimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/minimize.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/msg.error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/msg.error.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/msg.info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/msg.info.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/msg.warn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/msg.warn.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/uploaded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/uploaded.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/loading_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/loading_text.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/msg.question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/msg.question.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/noimage_wide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/noimage_wide.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/settings-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/settings-icon.png
--------------------------------------------------------------------------------
/ModdingTools/Resources/editorcrashedhueh4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcu8/OpenModManager/HEAD/ModdingTools/Resources/editorcrashedhueh4.png
--------------------------------------------------------------------------------
/ModdingTools.Cli/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ModdingTools/Logging/ILogger.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Shared;
2 |
3 | namespace ModdingTools.Logging
4 | {
5 | interface ILogger
6 | {
7 | void Init();
8 | void Append(string text, string sender, LogLevel level);
9 | void Unregister();
10 | LogLevel VerbosityLevel();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ModdingTools.Cli/Program.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Headless;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace ModdingTools.Cli
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | ProgramHeadless.MainHeadless(args);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ModdingTools/BuildData.cs:
--------------------------------------------------------------------------------
1 | namespace ModdingTools
2 | {
3 | class BuildData
4 | {
5 | public const string UpdateUrl = "https://hat.ovh/omm_version.txt";
6 | public const string ReleasesPage = "https://github.com/mcu8/OpenModManager/releases/latest";
7 | public const string ChangeLogUrl = "https://hat.ovh/omm_changelog.php";
8 | public const long CurrentVersion = 159;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/IDATChunk.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace LibAPNG
4 | {
5 | public class IDATChunk : Chunk
6 | {
7 | public IDATChunk(byte[] bytes)
8 | : base(bytes)
9 | {
10 | }
11 |
12 | public IDATChunk(MemoryStream ms)
13 | : base(ms)
14 | {
15 | }
16 |
17 | public IDATChunk(Chunk chunk)
18 | : base(chunk)
19 | {
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/IENDChunk.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace LibAPNG
4 | {
5 | public class IENDChunk : Chunk
6 | {
7 | public IENDChunk(byte[] bytes)
8 | : base(bytes)
9 | {
10 | }
11 |
12 | public IENDChunk(MemoryStream ms)
13 | : base(ms)
14 | {
15 | }
16 |
17 | public IENDChunk(Chunk chunk)
18 | : base(chunk)
19 | {
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/ModdingTools/Steam/AbstractModUploader.AbstractMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Web.UI;
6 | using System.Windows.Forms;
7 |
8 | namespace ModdingTools.Steam
9 | {
10 | public abstract partial class AbstractModUploader
11 | {
12 | protected abstract void SetStatusText(string text);
13 | protected abstract void SetProgress(int value);
14 | protected abstract void SetState();
15 | protected abstract Form GetParentForm();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/OtherChunk.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace LibAPNG
4 | {
5 | public class OtherChunk : Chunk
6 | {
7 | public OtherChunk(byte[] bytes)
8 | : base(bytes)
9 | {
10 | }
11 |
12 | public OtherChunk(MemoryStream ms)
13 | : base(ms)
14 | {
15 | }
16 |
17 | public OtherChunk(Chunk chunk)
18 | : base(chunk)
19 | {
20 | }
21 |
22 | protected override void ParseData(MemoryStream ms)
23 | {
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/ModdingTools/GUI/ThemeConstants.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace ModdingTools.GUI
4 | {
5 | public class ThemeConstants
6 | {
7 | public static readonly Color BackgroundColor = Color.FromArgb(36, 36, 36);
8 | public static readonly Color ForegroundColor = Color.White;
9 | public static readonly Color BorderColor = Color.FromArgb(64, 64, 128);
10 | public static readonly Color TitleBarBackground = Color.Black;
11 | public static readonly Color TitleBarForeground = Color.White;
12 | public static readonly Color TileUnselected = Color.FromArgb(64, 64, 64);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ModdingTools/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/HeadlessModeCheatsheet.md:
--------------------------------------------------------------------------------
1 | # Cook mod
2 | ```
3 | ModdingTools.Cli.exe --cookmod --mod=mod_folder_name_here
4 | ```
5 |
6 | Example: `ModdingTools.Cli.exe --cookmod --mod=mcu8_maps_SpaceshipEx`
7 |
8 | # Compile mod
9 | ```
10 | ModdingTools.Cli.exe --compilemod --mod=mod_folder_name_here
11 | ```
12 |
13 | Example: `ModdingTools.Cli.exe --compilemod --mod=mcu8_maps_SpaceshipEx`
14 |
15 | # Mod list
16 | ```
17 | ModdingTools.Cli.exe --modlist
18 | ```
19 |
20 | # Launch editor
21 | ```
22 | ModdingTools.Cli.exe --editor
23 | ```
24 |
25 | # Test map
26 | ```
27 | ModdingTools.Cli.exe --testmap=map_name_here
28 | ```
29 | Example: `ModdingTools.Cli.exe --testmap=hatintimeentry`
--------------------------------------------------------------------------------
/ModdingTools/Logging/Handlers/DebuggerLogger.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Shared;
2 | using System.Diagnostics;
3 |
4 | namespace ModdingTools.Logging.Handlers
5 | {
6 | public class DebuggerLogger : ILogger
7 | {
8 |
9 | public void Append(string text, string sender, LogLevel level)
10 | {
11 | string tag = "[" + Logger.GetLoggerDate() + "][" + Logger.GetLevelText(level) + "][" + sender + "]";
12 | Debug.WriteLine(tag + text);
13 | }
14 |
15 | public void Init()
16 | {
17 | }
18 |
19 | public void Unregister()
20 | {
21 | }
22 |
23 | public LogLevel VerbosityLevel()
24 | {
25 | return LogLevel.Verbose;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/acTLChunk.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace LibAPNG
4 | {
5 | public class acTLChunk : Chunk
6 | {
7 | public acTLChunk(byte[] bytes)
8 | : base(bytes)
9 | {
10 | }
11 |
12 | public acTLChunk(MemoryStream ms)
13 | : base(ms)
14 | {
15 | }
16 |
17 | public acTLChunk(Chunk chunk)
18 | : base(chunk)
19 | {
20 | }
21 |
22 | public uint NumFrames { get; private set; }
23 |
24 | public uint NumPlays { get; private set; }
25 |
26 | protected override void ParseData(MemoryStream ms)
27 | {
28 | NumFrames = Helper.ConvertEndian(ms.ReadUInt32());
29 | NumPlays = Helper.ConvertEndian(ms.ReadUInt32());
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/ModdingTools/Headless/ConsoleProcessRunner.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Shared;
2 | using ModdingTools.Engine;
3 | using ModdingTools.Logging;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 |
9 | namespace ModdingTools.Headless
10 | {
11 | public class ConsoleProcessRunner : AbstractProcessRunner
12 | {
13 | public override void FinishAppRun()
14 | {
15 | }
16 |
17 | public override void Log(string msg, LogLevel level)
18 | {
19 | Logger.Log(level, msg);
20 | }
21 |
22 | public override void PostAppRun()
23 | {
24 | }
25 |
26 | public override void PreAppRun(bool cleanConsole, string taskName)
27 | {
28 | Logger.PrintBoxed($"Starting task: {taskName}...", ConsoleColor.White);
29 | }
30 |
31 | public override void PreRunWithoutWait()
32 | {
33 | }
34 |
35 | public override void SetText(string value)
36 | {
37 | Console.Title = value??"";
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ModdingTools.Updater.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ModdingTools/Headless/CommandLineOptions.cs:
--------------------------------------------------------------------------------
1 | using CommandLine;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace ModdingTools.Headless
8 | {
9 | class CommandLineOptions
10 | {
11 | [Option(Group = "task", HelpText = "Compile scripts")]
12 | public bool CompileMod { get; set; }
13 |
14 | [Option(Group = "task", HelpText = "Cook mod")]
15 | public bool CookMod { get; set; }
16 |
17 | [Option(Group = "task", HelpText = "Print mod list")]
18 | public bool ModList { get; set; }
19 |
20 | [Option(Group = "task", HelpText = "Launch editor")]
21 | public bool Editor { get; set; }
22 |
23 | [Option("testmap", HelpText = "Test map", Group = "task")]
24 | public string TestMap { get; set; }
25 |
26 | [Option("testmapall", HelpText = "Test map (all mods)", Group = "task")]
27 | public string TestMapAll { get; set; }
28 |
29 | [Option("mod", HelpText = "Mod folder name")]
30 | public string ModName { get; set; }
31 |
32 | [Option("nologo", HelpText = "Hide banner", Default = false)]
33 | public bool NoLogo { get; set; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/EditorProcessStateWatchdog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Windows.Forms;
8 |
9 | namespace ModdingTools.Engine
10 | {
11 | internal class EditorProcessStateWatchdog
12 | {
13 | public bool IsEditorRunning { get; private set; }
14 |
15 | public event EventHandler EditorStateChanged;
16 |
17 | public EditorProcessStateWatchdog() {
18 | var th = new Thread(ThreadWorker);
19 | th.IsBackground = true;
20 | th.Start();
21 | }
22 |
23 | private void ThreadWorker()
24 | {
25 | while (true)
26 | {
27 | try
28 | {
29 | var x = Process.GetProcessesByName("HatinTimeEditor");
30 | var isRunning = x != null && x.Length > 0;
31 | if (isRunning != IsEditorRunning)
32 | {
33 | IsEditorRunning = isRunning;
34 | // trigger state change
35 | EditorStateChanged?.Invoke(this, EventArgs.Empty);
36 | }
37 | }
38 | catch (Exception) { } // nah
39 | Thread.Sleep(5000);
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/IHDRChunk.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace LibAPNG
5 | {
6 | public class IHDRChunk : Chunk
7 | {
8 | public IHDRChunk(byte[] chunkBytes)
9 | : base(chunkBytes)
10 | {
11 | }
12 |
13 | public IHDRChunk(MemoryStream ms)
14 | : base(ms)
15 | {
16 | }
17 |
18 | public IHDRChunk(Chunk chunk)
19 | : base(chunk)
20 | {
21 | }
22 |
23 | public int Width { get; private set; }
24 |
25 | public int Height { get; private set; }
26 |
27 | public byte BitDepth { get; private set; }
28 |
29 | public byte ColorType { get; private set; }
30 |
31 | public byte CompressionMethod { get; private set; }
32 |
33 | public byte FilterMethod { get; private set; }
34 |
35 | public byte InterlaceMethod { get; private set; }
36 |
37 | protected override void ParseData(MemoryStream ms)
38 | {
39 | Width = Helper.ConvertEndian(ms.ReadInt32());
40 | Height = Helper.ConvertEndian(ms.ReadInt32());
41 | BitDepth = Convert.ToByte(ms.ReadByte());
42 | ColorType = Convert.ToByte(ms.ReadByte());
43 | CompressionMethod = Convert.ToByte(ms.ReadByte());
44 | FilterMethod = Convert.ToByte(ms.ReadByte());
45 | InterlaceMethod = Convert.ToByte(ms.ReadByte());
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/ModdingTools/Windows/ChangelogWindow.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Windows;
2 | using ModdingTools.Engine;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Data;
7 | using System.Diagnostics;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 |
13 | namespace ModdingTools.Windows
14 | {
15 | public partial class ChangelogWindow : CUWindow
16 | {
17 | public ChangelogWindow(bool changelogOnly = false)
18 | {
19 | InitializeComponent();
20 | webBrowser1.ScriptErrorsSuppressed = true;
21 | webBrowser1.DocumentText = "
";
22 | webBrowser1.Navigate(BuildData.ChangeLogUrl + "?ver=" + BuildData.CurrentVersion);
23 | if (changelogOnly)
24 | {
25 | this.IsResizable = true;
26 | this.IsCloseButtonEnabled = true;
27 | this.ControlBoxVisible = true;
28 | tableLayoutPanel1.Visible = false;
29 | label2.Visible = false;
30 | webBrowser1.Dock = DockStyle.Fill;
31 | this.Text = "CHANGELOG";
32 | }
33 | }
34 |
35 | private void cuButton1_Click(object sender, EventArgs e)
36 | {
37 | this.DialogResult = DialogResult.Yes;
38 | }
39 |
40 | private void cuButton2_Click_1(object sender, EventArgs e)
41 | {
42 | this.DialogResult = DialogResult.No;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ModdingTools/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OpenModManager")]
9 | [assembly: AssemblyDescription("Funni modding tool for A Hat in Time")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("m_cu8/m_cube")]
12 | [assembly: AssemblyProduct("OpenModManager")]
13 | [assembly: AssemblyCopyright("https://github.com/mcu8/OpenModManager")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("0569be64-ba84-4c53-9296-ee830f5a002f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OpenModManager Updater")]
9 | [assembly: AssemblyDescription("Updater for OpenModManager")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("m_cu8/m_cube")]
12 | [assembly: AssemblyProduct("OpenModManager")]
13 | [assembly: AssemblyCopyright("https://github.com/mcu8/OpenModManager")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("25aaae0c-404d-4877-af19-f6245eb17f0e")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ModdingTools.Cli/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OpenModManager (Console Interface)")]
9 | [assembly: AssemblyDescription("Funni modding tool for A Hat in Time")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("m_cu8/m_cube")]
12 | [assembly: AssemblyProduct("OpenModManager")]
13 | [assembly: AssemblyCopyright("https://github.com/mcu8/OpenModManager")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("0569be64-ba84-4c53-9296-ee830f5a002f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Create-Release-Files.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 |
3 | $scriptpath = $MyInvocation.MyCommand.Path
4 | $dir = Split-Path $scriptpath
5 | Write-host "My directory is $dir"
6 |
7 | $devenv = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.com"
8 |
9 | $outputDir = Join-Path -Path $dir -Child "Release"
10 | $tmpDir = Join-Path -Path $outputDir -Child ".tmp"
11 |
12 | Remove-Item -Path $outputDir\*.* -Force -Recurse
13 | New-Item -Path $tmpDir -ItemType Directory -ErrorAction Ignore
14 | Remove-Item -Path $tmpDir\* -Force -Recurse
15 |
16 | $ommFiles = Join-Path -Path $dir -Child "ModdingTools.Cli\bin\Debug"
17 | $ommUpdaterFiles = Join-Path -Path $dir -Child "ModdingTools.Updater\bin\Debug"
18 |
19 | Remove-Item -Force $ommFiles\*
20 | Remove-Item -Force $ommUpdaterFiles\*
21 |
22 | $csproj = Join-Path -Path $dir -Child "OpenModManager.sln"
23 | & $devenv "$csproj" /build Debug
24 |
25 | Write-Host $ommFiles
26 | Copy-Item -Path $ommFiles\* -Recurse -Destination $tmpDir
27 |
28 | Write-Host $ommUpdaterFiles
29 | Copy-Item -Path $ommUpdaterFiles\* -Recurse -Destination $tmpDir
30 |
31 | Move-Item -Path $tmpDir\ModdingTools.Updater.exe -Destination $tmpDir\ModdingTools.Updater.New.exe
32 | Move-Item -Path $tmpDir\ModdingTools.Updater.pdb -Destination $tmpDir\ModdingTools.Updater.New.pdb
33 |
34 | Compress-Archive -Path $tmpDir\* -DestinationPath $outputDir\OpenModManager-bin.zip
35 | Remove-Item -Path $tmpDir -Recurse -Force
36 |
37 | $sha256 = Get-FileHash $outputDir\OpenModManager-bin.zip -Algorithm SHA256 | Select-Object -ExpandProperty Hash
38 | [IO.File]::WriteAllText("$outputDir\OpenModManager-bin.zip.sha256", ("$sha256".ToLower() + " OpenModManager-bin.zip") -join "`n")
39 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/fdATChunk.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace LibAPNG
4 | {
5 | internal class fdATChunk : Chunk
6 | {
7 | public fdATChunk(byte[] bytes)
8 | : base(bytes)
9 | {
10 | }
11 |
12 | public fdATChunk(MemoryStream ms)
13 | : base(ms)
14 | {
15 | }
16 |
17 | public fdATChunk(Chunk chunk)
18 | : base(chunk)
19 | {
20 | }
21 |
22 | public uint SequenceNumber { get; private set; }
23 |
24 | public byte[] FrameData { get; private set; }
25 |
26 | protected override void ParseData(MemoryStream ms)
27 | {
28 | SequenceNumber = Helper.ConvertEndian(ms.ReadUInt32());
29 | FrameData = ms.ReadBytes((int)Length - 4);
30 | }
31 |
32 | public IDATChunk ToIDATChunk()
33 | {
34 | uint newCrc;
35 | using (var msCrc = new MemoryStream())
36 | {
37 | msCrc.WriteBytes(new[] {(byte)'I', (byte)'D', (byte)'A', (byte)'T'});
38 | msCrc.WriteBytes(FrameData);
39 |
40 | newCrc = CrcHelper.Calculate(msCrc.ToArray());
41 | }
42 |
43 | using (var ms = new MemoryStream())
44 | {
45 | ms.WriteUInt32(Helper.ConvertEndian(Length - 4));
46 | ms.WriteBytes(new[] {(byte)'I', (byte)'D', (byte)'A', (byte)'T'});
47 | ms.WriteBytes(FrameData);
48 | ms.WriteUInt32(Helper.ConvertEndian(newCrc));
49 | ms.Position = 0;
50 |
51 | return new IDATChunk(ms);
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/ModdingTools/Windows/AboutWindow.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Windows;
2 | using ModdingTools.Engine;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Data;
7 | using System.Diagnostics;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 |
13 | namespace ModdingTools.Windows
14 | {
15 | public partial class AboutWindow : CUWindow
16 | {
17 | public AboutWindow()
18 | {
19 | InitializeComponent();
20 | label3.Text = $"App build number: {BuildData.CurrentVersion}";
21 | }
22 |
23 | private void cuButton2_Click(object sender, EventArgs e)
24 | {
25 | Utils.StartInDefaultBrowser("https://hat.ovh");
26 | }
27 |
28 | private void cuButton3_Click(object sender, EventArgs e)
29 | {
30 | Utils.StartInDefaultBrowser("https://github.com/mcu8/OpenModManager");
31 | }
32 |
33 | private void cuButton1_Click(object sender, EventArgs e)
34 | {
35 | this.Close();
36 | }
37 |
38 | private void cuButton4_Click(object sender, EventArgs e)
39 | {
40 | Utils.StartInDefaultBrowser("https://bsky.app/profile/m-cu.be");
41 | }
42 |
43 | private void cuButton5_Click(object sender, EventArgs e)
44 | {
45 | Process.Start("steam://openurl/https://steamcommunity.com/id/m_cu8/myworkshopfiles/?appid=253230");
46 | }
47 |
48 | private void cuButton6_Click(object sender, EventArgs e)
49 | {
50 | new ChangelogWindow(true).ShowDialog(this);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/UpdateChecker.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Settings;
2 | using System;
3 | using System.Diagnostics;
4 | using System.Net;
5 | using System.Threading.Tasks;
6 |
7 | namespace ModdingTools.Engine
8 | {
9 |
10 | public class UpdateChecker
11 | {
12 | static readonly bool TestMode = false;
13 |
14 | private Action OnUpdateAvaiable;
15 | private string UpdateUrl;
16 | private long BuildNumber;
17 |
18 | public UpdateChecker(long buildNumber, string updateUrl, Action onUpdateAvaiable)
19 | {
20 | BuildNumber = buildNumber;
21 | UpdateUrl = updateUrl;
22 | OnUpdateAvaiable = onUpdateAvaiable;
23 | }
24 |
25 | public void CheckForUpdatesAsync()
26 | {
27 | if (!OMMSettings.Instance.UpdateCheck)
28 | {
29 | Debug.WriteLine("Updates disabled");
30 | return;
31 | }
32 | Task.Factory.StartNew(() =>
33 | {
34 | try
35 | {
36 | using (var wc = new WebClient())
37 | {
38 | var remoteVersion = long.Parse(wc.DownloadString(UpdateUrl).Trim());
39 | if (remoteVersion > BuildNumber || TestMode)
40 | {
41 | OnUpdateAvaiable?.Invoke();
42 | }
43 | }
44 | }
45 | catch (Exception e)
46 | {
47 | Debug.WriteLine("!!" + e.Message);
48 | Debug.WriteLine("!!" + e.StackTrace);
49 | }
50 | });
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/Meme.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Settings;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Media;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace ModdingTools.Engine
13 | {
14 | // Don't ask...
15 | class Meme
16 | {
17 | static SoundPlayer pl;
18 | static bool IsPlaying = false;
19 |
20 | public static void PlayElevatorMusic()
21 | {
22 | if (IsPlaying) return; // prevent the ear-rape
23 | if (!OMMSettings.Instance.Memes) return;
24 | var ph = Path.Combine(Program.GetAppRoot(), @"lol.wav");
25 | if (!File.Exists(ph)) return;
26 | Debug.WriteLine("MemeStart()");
27 | IsPlaying = false;
28 | Task.Factory.StartNew(() =>
29 | {
30 | if (pl != null)
31 | {
32 | pl.Stop();
33 | pl.Dispose();
34 | pl = null;
35 | }
36 |
37 | pl = new SoundPlayer(ph);
38 | pl.PlayLooping(); // loop the music
39 | IsPlaying = true;
40 | while (IsPlaying)
41 | {
42 | Thread.Sleep(100);
43 | }
44 | pl.Stop();
45 | IsPlaying = false;
46 | });
47 | }
48 |
49 | public static void StopElevatorMusic()
50 | {
51 | if (!OMMSettings.Instance.Memes) return;
52 | Debug.WriteLine("MemeStop()");
53 | IsPlaying = false;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/GUIWorker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using ModdingTools.Windows;
10 |
11 | namespace ModdingTools.GUI
12 | {
13 | public partial class GUIWorker : UserControl
14 | {
15 | public GUIWorker()
16 | {
17 | this.DoubleBuffered = true;
18 | InitializeComponent();
19 | }
20 |
21 | public void SetStatus(string text)
22 | {
23 | SetStatus(text, Color.Empty);
24 | }
25 |
26 | public void SetProgress(int value, string text = null)
27 | {
28 | if (text == null) text = $"{value}%";
29 | huehProgressBar1.Value = value;
30 | huehProgressBar1.Text = text;
31 | }
32 |
33 | public void SetStatus(string text, Color color)
34 | {
35 | if (this.InvokeRequired)
36 | {
37 | this.Invoke(new MethodInvoker(() => SetStatus(text, color)));
38 | return;
39 | }
40 |
41 | SetTextOrHideOnNull(color, text);
42 | }
43 |
44 | public void SetTextOrHideOnNull(string text = null)
45 | {
46 | SetTextOrHideOnNull(Color.Empty, text);
47 | }
48 |
49 | public void SetTextOrHideOnNull(Color color, string text = null)
50 | {
51 | if (text == null)
52 | {
53 | MainWindow.Instance.SetCard(MainWindow.CardControllerTabs.Mods);
54 | MainWindow.Instance.ToggleSearchBar(true);
55 | }
56 | else
57 | {
58 | cuGradientTextBox1.Insert(text, color);
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/Tools/Benchmark.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Windows;
2 | using ModdingTools.GUI;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Data;
7 | using System.Diagnostics;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using System.Windows.Forms;
14 |
15 | namespace ModdingTools.Windows.Tools
16 | {
17 | public partial class Benchmark : CUWindow
18 | {
19 | public Benchmark()
20 | {
21 | InitializeComponent();
22 | }
23 |
24 | bool closing = false;
25 |
26 | Stopwatch sw = new Stopwatch();
27 | public void Start()
28 | {
29 | sw.Start();
30 |
31 | Task.Factory.StartNew(() =>
32 | {
33 | while(sw.IsRunning)
34 | {
35 | if (closing) return;
36 | try
37 | {
38 | this.Invoke(new MethodInvoker(() =>
39 | {
40 | label1.Text = sw.Elapsed.ToString(@"hh\:mm\:ss\.fff");
41 | }));
42 | }
43 | catch (Exception)
44 | {
45 | break;
46 | }
47 | Thread.Sleep(10);
48 | }
49 | this.Invoke(new MethodInvoker(() =>
50 | {
51 | label1.ForeColor = Color.Green;
52 | }));
53 | });
54 | }
55 |
56 | public void Stop()
57 | {
58 | sw.Stop();
59 | }
60 |
61 | private void Benchmark_FormClosing(object sender, FormClosingEventArgs e)
62 | {
63 | closing = true;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/CategorySpacer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using ModdingTools.Engine;
10 |
11 | namespace ModdingTools.GUI
12 | {
13 | public partial class CategorySpacer : UserControl
14 | {
15 |
16 | public delegate void OnToggle(CategorySpacer sender, bool state);
17 | public OnToggle Toggle = null;
18 |
19 | public delegate void OnHeaderClick(CategorySpacer sender);
20 | public OnHeaderClick HeaderClick = null;
21 |
22 | public CategorySpacer(string title, string subtitle)
23 | {
24 | InitializeComponent();
25 | this.panel1.BackColor = ThemeConstants.BorderColor;
26 | this.label2.Text = title;
27 | this.label1.Text = subtitle;
28 | }
29 |
30 | public bool SelectionMode { get; set; }
31 |
32 | private bool _ToggleState;
33 | public bool ToggleState
34 | {
35 | get
36 | {
37 | return _ToggleState;
38 | }
39 | set
40 | {
41 | _ToggleState = value;
42 | CUButtonBorderless1.Image = (value) ? Properties.Resources.icon_044 : Properties.Resources.icon_043;
43 | Toggle?.Invoke(this, value);
44 | }
45 | }
46 |
47 | private void CUButtonBorderless1_Click(object sender, EventArgs e)
48 | {
49 | ToggleState = !ToggleState;
50 | }
51 |
52 | private void label1_Click(object sender, EventArgs e)
53 | {
54 | Utils.OpenInExplorer(label1.Text);
55 | }
56 |
57 | private void label2_Click(object sender, EventArgs e)
58 | {
59 | HeaderClick?.Invoke(this);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Open Mod Manager
2 | **For *A Hat in Time***
3 |
4 | 
5 |
6 | ---
7 |
8 | ### What is this? Flying boat?
9 |
10 | Nope — it's the **Mod Manager**, fully rewritten from scratch with new features:
11 |
12 | - Resizable window
13 | - Embedded console
14 | - "Mafia Punch™" button (for killing the editor when it stops responding)
15 | - Batch-building multiple mods at once
16 | - Fully dark-themed interface
17 | - Improved Asset Replacements editor
18 | - Mod configuration editor
19 | - Clipbook generator (from GIFs)
20 | - Asset exporter (supports `SoundNodeWave` and `Texture2D`)
21 | - Custom workshop uploader with advanced features
22 | - Search bar
23 | - Script watcher (automatically compiles scripts when modified — disabled by default)
24 | - Mod list context menu
25 | - Customizable command line arguments
26 | - Headless mode
27 | - VS Code integration
28 | - ...and more!
29 |
30 | You can find a ready-to-run version on the [Releases](https://github.com/mcu8/OpenModManager/releases/latest) page.
31 |
32 | ---
33 |
34 | ### Now with Steam Workshop Upload Support!
35 |
36 | Supports mod uploading via the **Steamworks API** (no more `Int32` issue)!
37 | ⚠️ Works only with the **Steam version** of the game and **64-bit operating systems** (since the game is 64-bit anyway).
38 | 🛠 Requires [.NET Framework v4.8](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net48).
39 |
40 | ---
41 |
42 | ### Installation
43 |
44 | 1. Download the latest release from the [Releases](https://github.com/mcu8/OpenModManager/releases/latest) page.
45 | 2. Extract it to any folder.
46 | 3. Run the `ModdingTools.exe` executable.
47 |
48 | ---
49 |
50 | ### Building from Source
51 |
52 | 1. Clone the repository.
53 | 2. Open the solution in **Visual Studio 2022** or newer.
54 |
55 | ---
56 |
57 | ### Disclaimer
58 |
59 | This is an unofficial tool and is not affiliated with **Gears for Breakfast**.
60 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/ProcessRunner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using System.Diagnostics;
4 | using System.Runtime.InteropServices;
5 | using System.Threading.Tasks;
6 | using static ModdingTools.Engine.ProcessFactory;
7 | using System.Collections.Generic;
8 | using ModdingTools.Engine;
9 | using ModdingTools.Windows;
10 | using System.Text.RegularExpressions;
11 | using System.IO;
12 | using System.Threading;
13 | using System.Windows.Input;
14 | using System.Drawing;
15 | using CUFramework.Shared;
16 | using CUFramework.Controls;
17 |
18 | namespace ModdingTools.GUI
19 | {
20 | public partial class ProcessRunner : UserControl
21 | {
22 | public GUIProcessRunner Runner { get; private set; }
23 |
24 | public ProcessRunner()
25 | {
26 | InitializeComponent();
27 | Runner = new GUIProcessRunner(this);
28 |
29 | SetText(null);
30 | mButton3.Visible = false;
31 | }
32 |
33 | public void SetText(string value)
34 | {
35 | if (this.InvokeRequired)
36 | {
37 | this.Invoke(new MethodInvoker(() => SetText(value)));
38 | }
39 | else
40 | {
41 | if (MainWindow.Instance != null)
42 | {
43 | MainWindow.Instance.GuiWorker.SetStatus(value);
44 | }
45 |
46 | if (value == null) Text = "";
47 | else Text = value;
48 | }
49 | }
50 |
51 | public void Log(string msg, LogLevel level)
52 | {
53 | if (level >= LogLevel.Info)
54 | {
55 | MainWindow.Instance.GuiWorker.SetStatus(msg, CUConsoleControl.GetLevelColor(level));
56 | }
57 | consoleControl1.Log(msg, level);
58 | }
59 |
60 | private void mButton3_Click(object sender, EventArgs e)
61 | {
62 | Runner.KillAllWorkers();
63 | }
64 |
65 | private void mButton1_Click(object sender, EventArgs e)
66 | {
67 | consoleControl1.Clear();
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/ModdingTools/Logging/Handlers/CommandLineLogger.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Shared;
2 | using System;
3 | using System.IO;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace ModdingTools.Logging.Handlers
7 | {
8 | public class CommandLineLogger : ILogger
9 | {
10 | public void Init()
11 | {
12 | try
13 | {
14 | Console.Title = "OMM";
15 | } catch (IOException)
16 | {
17 | // just ignore for now
18 | }
19 | }
20 |
21 | public static void PrintBanner()
22 | {
23 | Logger.PrintBoxed(Properties.Resources.Banner + "\n\n" + "[Command Line mode]\nApp build number: " + BuildData.CurrentVersion, ConsoleColor.Yellow);
24 |
25 | Console.WriteLine("");
26 | Console.WriteLine("");
27 | }
28 |
29 | public void Append(string text, string sender, LogLevel level)
30 | {
31 | string tag = "[" + Logger.GetLoggerDate() + " " + Logger.GetLevelText(level) + "] ";
32 |
33 | switch (level)
34 | {
35 | case LogLevel.Success:
36 | Console.ForegroundColor = ConsoleColor.Green;
37 | break;
38 | case LogLevel.Error:
39 | Console.ForegroundColor = ConsoleColor.Red;
40 | break;
41 | case LogLevel.Warn:
42 | Console.ForegroundColor = ConsoleColor.Yellow;
43 | break;
44 | case LogLevel.Info:
45 | Console.ForegroundColor = ConsoleColor.White;
46 | break;
47 | case LogLevel.Verbose:
48 | Console.ForegroundColor = ConsoleColor.Gray;
49 | break;
50 | }
51 |
52 | Console.WriteLine(tag + text);
53 | Console.ResetColor();
54 | }
55 |
56 | public void Unregister()
57 | {
58 | }
59 |
60 | public LogLevel VerbosityLevel()
61 | {
62 | return LogLevel.Info;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/ArgEditorItem.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs.Validators;
2 | using ModdingTools.Settings;
3 | using ModdingTools.Windows;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 | using System.Windows.Input;
13 |
14 | namespace ModdingTools.GUI
15 | {
16 | public partial class ArgEditorItem : UserControl
17 | {
18 | private OMMSettings.ArgsDefaultsKeys MyKey;
19 | public ArgEditorItem(OMMSettings.ArgsDefaultsKeys key)
20 | {
21 | MyKey = key;
22 | InitializeComponent();
23 | RefreshData();
24 | }
25 |
26 | private void RefreshData()
27 | {
28 | label5.Text = OMMSettings.Instance.GetArgumentsFor(MyKey);
29 | label6.Text = OMMSettings.Instance.GetLocalizedArgKeyName(MyKey);
30 | if (label5.Text != OMMSettings.ArgsDefaults[MyKey])
31 | {
32 | this.label6.Image = global::ModdingTools.Properties.Resources.delete;
33 | }
34 | else
35 | {
36 | this.label6.Image = global::ModdingTools.Properties.Resources.ok;
37 | }
38 | }
39 |
40 | public ArgEditorItem()
41 | {
42 | InitializeComponent();
43 | }
44 |
45 | private void mButtonBorderless1_Click(object sender, EventArgs e)
46 | {
47 | OMMSettings.Instance.ResetArguments(MyKey);
48 | OMMSettings.Instance.Save();
49 | RefreshData();
50 | }
51 |
52 | private void label5_Click(object sender, EventArgs e)
53 | {
54 | var iw = CUInputWindow.Ask(this, $"Editing arguments for action: {MyKey}", "", new NonEmptyValidator(), label5.Text, true);
55 | if (iw != null && iw != label5.Text)
56 | {
57 | OMMSettings.Instance.ChangeArgument(MyKey, iw);
58 | OMMSettings.Instance.Save();
59 | RefreshData();
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ModdingTools/Steam/AbstractModUploader.HelperMethods.cs:
--------------------------------------------------------------------------------
1 | using Steamworks;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace ModdingTools.Steam
8 | {
9 | public abstract partial class AbstractModUploader
10 | {
11 | private static string TranslateStatus(EItemUpdateStatus s)
12 | {
13 | switch (s)
14 | {
15 | case EItemUpdateStatus.k_EItemUpdateStatusInvalid:
16 | return "...";
17 | case EItemUpdateStatus.k_EItemUpdateStatusCommittingChanges:
18 | return "Committing changes...";
19 | case EItemUpdateStatus.k_EItemUpdateStatusPreparingConfig:
20 | return "Preparing config...";
21 | case EItemUpdateStatus.k_EItemUpdateStatusPreparingContent:
22 | return "Preparing content...";
23 | case EItemUpdateStatus.k_EItemUpdateStatusUploadingContent:
24 | return "Uploading content...";
25 | case EItemUpdateStatus.k_EItemUpdateStatusUploadingPreviewFile:
26 | return "Uploading preview file...";
27 | default:
28 | return s.ToString();
29 | }
30 | }
31 | private static string BytesToString(ulong byteCount)
32 | {
33 | try
34 | {
35 | string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; //Longs run out around EB
36 | if (byteCount == 0)
37 | return "0" + suf[0];
38 | long bytes = Math.Abs((long)byteCount);
39 | int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
40 | double num = Math.Round(bytes / Math.Pow(1024, place), 1);
41 | return (Math.Sign((long)byteCount) * num).ToString() + suf[place];
42 | }
43 | catch (Exception e)
44 | {
45 | // normally, that shouldn't happen... but nah
46 | return byteCount + "B";
47 | }
48 | }
49 |
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/ARItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using ModdingTools.Windows;
10 | using ModdingTools.Windows.Validators;
11 |
12 | namespace ModdingTools.GUI
13 | {
14 | public partial class ARItem : UserControl
15 | {
16 | public ARItem(string target, string replacement)
17 | {
18 | InitializeComponent();
19 | label4.Text = target;
20 | label3.Text = replacement;
21 | }
22 |
23 | public string Target => label4.Text;
24 | public string Replacement => label3.Text;
25 |
26 | private void CUButtonBorderless1_Click(object sender, EventArgs e)
27 | {
28 | if (this.Parent is FlowLayoutPanel)
29 | {
30 | CallUpdateEvent();
31 | this.Parent.Controls.Remove(this);
32 | }
33 | }
34 |
35 | private void label4_Click(object sender, EventArgs e)
36 | {
37 | var a = CUInputWindow.Ask(this, "AR Editor", "Please, enter the original asset name", new ARValidator(), label4.Text);
38 | if (a != null)
39 | {
40 | if (label4.Text != a)
41 | {
42 | label4.Text = a;
43 | CallUpdateEvent();
44 | }
45 | }
46 | }
47 |
48 | private void label3_Click(object sender, EventArgs e)
49 | {
50 | var a = CUInputWindow.Ask(this, "AR Editor", "Please, enter the replacement asset name", new ARValidator(), label3.Text);
51 | if (a != null)
52 | {
53 | if (label3.Text != a)
54 | {
55 | label3.Text = a;
56 | CallUpdateEvent();
57 | }
58 | }
59 | }
60 |
61 | private void CallUpdateEvent()
62 | {
63 | if (this.Parent.Parent is ARList)
64 | ((ARList)this.Parent.Parent).CallOnUpdateEvent();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Helper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace LibAPNG
4 | {
5 | internal class Helper
6 | {
7 | ///
8 | /// Convert big-endian to little-endian or reserve
9 | ///
10 | internal static byte[] ConvertEndian(byte[] i)
11 | {
12 | if (i.Length % 2 != 0)
13 | throw new Exception("byte array length must multiply of 2");
14 |
15 | Array.Reverse(i);
16 |
17 | return i;
18 | }
19 |
20 | ///
21 | /// Convert big-endian to little-endian or reserve
22 | ///
23 | internal static int ConvertEndian(int i)
24 | {
25 | return BitConverter.ToInt32(ConvertEndian(BitConverter.GetBytes(i)), 0);
26 | }
27 |
28 | ///
29 | /// Convert big-endian to little-endian or reserve
30 | ///
31 | internal static uint ConvertEndian(uint i)
32 | {
33 | return BitConverter.ToUInt32(ConvertEndian(BitConverter.GetBytes(i)), 0);
34 | }
35 |
36 | ///
37 | /// Convert big-endian to little-endian or reserve
38 | ///
39 | internal static Int16 ConvertEndian(Int16 i)
40 | {
41 | return BitConverter.ToInt16(ConvertEndian(BitConverter.GetBytes(i)), 0);
42 | }
43 |
44 | ///
45 | /// Convert big-endian to little-endian or reserve
46 | ///
47 | internal static UInt16 ConvertEndian(UInt16 i)
48 | {
49 | return BitConverter.ToUInt16(ConvertEndian(BitConverter.GetBytes(i)), 0);
50 | }
51 |
52 | ///
53 | /// Compare two byte array
54 | ///
55 | public static bool IsBytesEqual(byte[] byte1, byte[] byte2)
56 | {
57 | if (byte1.Length != byte2.Length)
58 | return false;
59 |
60 | for (int i = 0; i < byte1.Length; i++)
61 | {
62 | if (byte1[i] != byte2[i])
63 | return false;
64 | }
65 | return true;
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/ModdingTools/GUI/GUIProcessRunner.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Shared;
2 | using ModdingTools.Engine;
3 | using ModdingTools.Windows;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Web.UI;
9 | using System.Windows.Forms;
10 |
11 | namespace ModdingTools.GUI
12 | {
13 | public class GUIProcessRunner : AbstractProcessRunner
14 | {
15 | ProcessRunner Parent;
16 | public GUIProcessRunner(ProcessRunner parent)
17 | {
18 | this.Parent = parent;
19 | }
20 |
21 | public override void FinishAppRun()
22 | {
23 | Parent.Invoke(new MethodInvoker(() =>
24 | {
25 | MainWindow.Instance.ToggleConsole(false);
26 | }));
27 | }
28 |
29 | public override void Log(string msg, LogLevel level)
30 | {
31 | Parent.Log(msg, level);
32 | }
33 |
34 | public override void PostAppRun()
35 | {
36 | if (runningProcesses.Count == 0)
37 | Parent.Invoke(new MethodInvoker(() =>
38 | {
39 | Parent.mButton3.Visible = false;
40 | }));
41 | }
42 |
43 | public override void PreAppRun(bool cleanConsole, string taskName)
44 | {
45 | Parent.Invoke(new MethodInvoker(() =>
46 | {
47 | if (cleanConsole) Parent.consoleControl1.Clear();
48 | Parent.consoleControl1.Log(taskName, LogLevel.Verbose);
49 | MainWindow.Instance.CallWorker();
50 | Parent.mButton3.Visible = true;
51 | }));
52 | }
53 |
54 | public override void PreRunWithoutWait()
55 | {
56 | Parent.Invoke(new MethodInvoker(() =>
57 | {
58 | Program.Benchmark = new Windows.Tools.Benchmark();
59 | Program.Benchmark.StartPosition = FormStartPosition.CenterScreen;
60 | Program.Benchmark.TopMost = true;
61 | Program.Benchmark.Show();
62 | }));
63 | }
64 |
65 | public override void SetText(string value)
66 | {
67 | Parent.SetText(value);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/ArgEditor.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Windows;
2 | using ModdingTools.GUI;
3 | using ModdingTools.Settings;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 | using static ModdingTools.Settings.OMMSettings;
13 |
14 | namespace ModdingTools.Windows
15 | {
16 | public partial class ArgEditor : CUWindow
17 | {
18 | private static int BarOffset = 30;
19 |
20 | public ArgEditor()
21 | {
22 | InitializeComponent();
23 | Init();
24 | UpdateWidths();
25 | }
26 |
27 | public void Init()
28 | {
29 | this.flowLayoutPanel1.SuspendLayout();
30 |
31 | this.flowLayoutPanel1.Controls.Clear();
32 | foreach (ArgsDefaultsKeys item in Enum.GetValues(typeof(OMMSettings.ArgsDefaultsKeys)))
33 | {
34 | var e = new ArgEditorItem(item);
35 | e.Padding = new Padding(0);
36 | e.Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
37 | this.flowLayoutPanel1.Controls.Add(e);
38 | }
39 | this.flowLayoutPanel1.ResumeLayout();
40 | }
41 |
42 | private void UpdateWidths(bool useHack = true)
43 | {
44 | flowLayoutPanel1.SuspendLayout();
45 | foreach (var a in flowLayoutPanel1.Controls)
46 | {
47 | if (a is ArgEditorItem)
48 | {
49 | ((Control)a).Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
50 | }
51 | }
52 | flowLayoutPanel1.ResumeLayout();
53 |
54 | if (useHack)
55 | {
56 | this.flowLayoutPanel1.Width -= 1;
57 | this.flowLayoutPanel1.Width += 1; // little hack to force-update the layout
58 | }
59 | }
60 |
61 | private void flowLayoutPanel1_SizeChanged(object sender, EventArgs e)
62 | {
63 |
64 | }
65 |
66 | private void ArgEditor_SizeChanged(object sender, EventArgs e)
67 | {
68 | UpdateWidths(false);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ModdingTools/Steam/AbstractModUploader.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs;
2 | using ModdingTools.Engine;
3 | using ModdingTools.Modding;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Windows.Forms;
10 |
11 | namespace ModdingTools.Steam
12 | {
13 | // time to rewrite that mess...
14 |
15 | // Remember: you can use only one isntance of uploader at once!!!
16 | public abstract partial class AbstractModUploader
17 | {
18 | public bool IsUploaderRunning { get; protected set; } = false;
19 |
20 | // return true if success, otherwise false
21 | public bool UpdateOrUploadMod(ModObject mod, string changelog, string[] tags, bool keepUnCooked, bool keepScripts, int visibility, string description)
22 | {
23 | if (IsUploaderRunning)
24 | {
25 | GetParentForm().Invoke(new MethodInvoker(() => {
26 | CUMessageBox.Show(GetParentForm(), "Only one uploader instance can run at once!");
27 | }));
28 | return false;
29 | }
30 | }
31 |
32 | private void PrepareUploadFolder(ModObject mod, bool keepScripts, bool keepUncookedContent)
33 | {
34 | var tmpDir = Path.Combine(Program.GetAppRoot(), "uploader_tmp");
35 | if (Directory.Exists(tmpDir))
36 | Directory.Delete(tmpDir, true);
37 | Directory.CreateDirectory(tmpDir);
38 |
39 | Utils.DirectoryCopy(mod.RootPath, tmpDir, true);
40 |
41 | if (!keepScripts)
42 | {
43 | if (Directory.Exists(Path.Combine(tmpDir, "CompiledScripts")))
44 | Directory.Delete(Path.Combine(tmpDir, "CompiledScripts"), true);
45 | if (Directory.Exists(Path.Combine(tmpDir, "Classes")))
46 | Directory.Delete(Path.Combine(tmpDir, "Classes"), true);
47 | }
48 |
49 | if (!keepUncookedContent)
50 | {
51 | if (Directory.Exists(Path.Combine(tmpDir, "Maps")))
52 | Directory.Delete(Path.Combine(tmpDir, "Maps"), true);
53 | if (Directory.Exists(Path.Combine(tmpDir, "Content")))
54 | Directory.Delete(Path.Combine(tmpDir, "Content"), true);
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/OpenModManager.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33122.133
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModdingTools", "ModdingTools\ModdingTools.csproj", "{0569BE64-BA84-4C53-9296-EE830F5A002F}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModdingTools.Cli", "ModdingTools.Cli\ModdingTools.Cli.csproj", "{23733746-7020-4E5B-958F-E3AA34E9E60F}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModdingTools.Updater", "ModdingTools.Updater\ModdingTools.Updater.csproj", "{25AAAE0C-404D-4877-AF19-F6245EB17F0E}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8DC7A4E-EEAB-4932-8AE6-3281C6BC6A69}"
13 | ProjectSection(SolutionItems) = preProject
14 | Create-Release-Files.bat = Create-Release-Files.bat
15 | Create-Release-Files.ps1 = Create-Release-Files.ps1
16 | EndProjectSection
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Release|Any CPU = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {0569BE64-BA84-4C53-9296-EE830F5A002F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {0569BE64-BA84-4C53-9296-EE830F5A002F}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {0569BE64-BA84-4C53-9296-EE830F5A002F}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {0569BE64-BA84-4C53-9296-EE830F5A002F}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {23733746-7020-4E5B-958F-E3AA34E9E60F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {23733746-7020-4E5B-958F-E3AA34E9E60F}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {23733746-7020-4E5B-958F-E3AA34E9E60F}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {23733746-7020-4E5B-958F-E3AA34E9E60F}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {25AAAE0C-404D-4877-AF19-F6245EB17F0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {25AAAE0C-404D-4877-AF19-F6245EB17F0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {25AAAE0C-404D-4877-AF19-F6245EB17F0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {25AAAE0C-404D-4877-AF19-F6245EB17F0E}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {323CAB77-0883-4EDD-BC2C-6F905872FD93}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/BorderPanel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace ModdingTools.GUI
9 | {
10 | class BorderPanel : Panel
11 | {
12 | public BorderPanel() {
13 |
14 | this.Resize += (o, e) =>
15 | {
16 | this.Invalidate();
17 | };
18 | this.BackColor = ThemeConstants.BackgroundColor;
19 | this.ForeColor = ThemeConstants.ForegroundColor;
20 | this.Padding = new Padding(0,0,0,0);
21 |
22 | this.Paint += BaseWindow_Paint;
23 | this.BorderStyle = BorderStyle.None;
24 | }
25 |
26 | public static void EatControl(Control c)
27 | {
28 | var f = new BorderPanel();
29 | var parentC = c.Parent;
30 | var loc = c.Location;
31 | var size = c.Size;
32 | var index = c.TabIndex;
33 | var dock = c.Dock;
34 | var anchor = c.Anchor;
35 |
36 | c.Width -= 5;
37 | c.Height -= 4;
38 |
39 | if (c is TextBox)
40 | {
41 | ((TextBox)c).BorderStyle = BorderStyle.None;
42 | }
43 |
44 | c.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
45 | c.Location = new Point(2, 2);
46 |
47 | parentC.Controls.Remove(c);
48 | f.BorderStyle = BorderStyle.None;
49 | f.Location = loc;
50 | f.Size = size;
51 | f.TabIndex = index;
52 | f.Dock = dock;
53 | f.Anchor = anchor;
54 | f.Controls.Add(c);
55 |
56 | parentC.Controls.Add(f);
57 | }
58 |
59 | private void BaseWindow_Paint(object sender, PaintEventArgs e)
60 | {
61 | DrawBorder(e);
62 | }
63 |
64 | private int _border = 2;
65 | public int BorderThickness
66 | {
67 | get => _border;
68 | set
69 | {
70 | _border = value;
71 | Refresh();
72 | }
73 | }
74 |
75 | public void DrawBorder(PaintEventArgs e)
76 | {
77 | var pen = new Pen(ThemeConstants.BorderColor);
78 | pen.Width = _border;
79 |
80 | var rect = new Rectangle(new Point(0, 0), new Size(this.Width - 2, this.Height - 2));
81 | e.Graphics.DrawRectangle(pen, rect);
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/ModdingTools/Steam/SteamApiCallback.cs:
--------------------------------------------------------------------------------
1 | using Steamworks;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 |
9 | // let's rewrite that shit...
10 | namespace ModdingTools.Steam.SteamApiCallback
11 | {
12 | public class SteamCallbackEventArgs : EventArgs
13 | {
14 | public T CallbackResult { get; set; }
15 | public bool IOFailed { get; protected set; }
16 |
17 | public SteamCallbackEventArgs(T CallbackResult, bool IOFailed)
18 | {
19 | this.IOFailed = IOFailed;
20 | this.CallbackResult = CallbackResult;
21 | }
22 | }
23 |
24 | public abstract class SteamCallback
25 | {
26 | protected static CallResult CallResult;
27 |
28 | // it's static, cuz we only can run one callback at once...
29 | protected static bool IsRunning = false;
30 |
31 | public event EventHandler> OnCallbackFinished;
32 |
33 | public SteamCallback()
34 | {
35 | CallResult = CallResult.Create(OnItemCreated);
36 | }
37 |
38 | protected abstract SteamAPICall_t CreateCall();
39 |
40 | public void Run()
41 | {
42 | if (IsRunning)
43 | {
44 | throw new Exception("Another callback is already running!");
45 | }
46 | IsRunning = true;
47 | CallResult.Set(CreateCall());
48 | SteamAPI.RunCallbacks();
49 | }
50 |
51 | public Task RunAsync()
52 | {
53 | return Task.Factory.StartNew(() => Run());
54 | }
55 |
56 | protected void OnCallFinished()
57 | {
58 | IsRunning = false;
59 | }
60 |
61 | protected void OnItemCreated(T callBack, bool bIOFailure)
62 | {
63 | OnCallFinished();
64 | OnCallbackFinished?.Invoke(this, new SteamCallbackEventArgs(callBack, bIOFailure));
65 | }
66 | }
67 |
68 | public class SteamCreateItemCallback : SteamCallback
69 | {
70 | private AppId_t AppId;
71 | private EWorkshopFileType EWorkshopFileType;
72 |
73 | public SteamCreateItemCallback(uint appId, EWorkshopFileType eWorkshopFileType = EWorkshopFileType.k_EWorkshopFileTypeCommunity)
74 | {
75 | AppId = new AppId_t(appId);
76 | EWorkshopFileType = eWorkshopFileType;
77 | }
78 |
79 | protected override SteamAPICall_t CreateCall()
80 | {
81 | return SteamUGC.CreateItem(AppId, EWorkshopFileType);
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ModdingTools/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | False
7 |
8 |
9 | False
10 |
11 |
12 | False
13 |
14 |
15 | True
16 |
17 |
18 | True
19 |
20 |
21 | False
22 |
23 |
24 |
25 |
26 |
27 | 0
28 |
29 |
30 | 8192
31 |
32 |
33 | False
34 |
35 |
36 | False
37 |
38 |
39 | False
40 |
41 |
42 | 0
43 |
44 |
45 |
46 |
47 |
48 | False
49 |
50 |
51 | False
52 |
53 |
54 | False
55 |
56 |
57 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/NamedPipe.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.SafeHandles;
2 | using System;
3 | using System.Diagnostics;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace ModdingTools.Engine
7 | {
8 | // adapted from UnrealFrontend, for handling cooking&compiling output
9 | public class NamedPipe : IDisposable
10 | {
11 | [StructLayout(LayoutKind.Sequential)]
12 | public class Overlapped
13 | {
14 | }
15 |
16 | public const int INVALID_HANDLE_VALUE = -1;
17 |
18 | public const uint PIPE_ACCESS_INBOUND = 1u;
19 |
20 | public const uint PIPE_TYPE_BYTE = 0u;
21 |
22 | public const uint PIPE_READMODE_BYTE = 0u;
23 |
24 | private const uint BUFFER_SIZE = 1024u;
25 |
26 | private SafePipeHandle PipeHandle;
27 |
28 | [DllImport("kernel32", SetLastError = true)]
29 | public static extern SafePipeHandle CreateNamedPipe(string lpName, uint dwOpenMode, uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize, uint nDefaultTimeOut, IntPtr pipeSecurityDescriptor);
30 |
31 | [DllImport("kernel32", SetLastError = true)]
32 | public static extern bool ConnectNamedPipe(SafePipeHandle hHandle, Overlapped lpOverlapped);
33 |
34 | [DllImport("kernel32", SetLastError = true)]
35 | public static extern bool DisconnectNamedPipe(SafePipeHandle hHandle);
36 |
37 | [DllImport("kernel32", SetLastError = true)]
38 | public static extern bool ReadFile(SafePipeHandle hHandle, byte[] lpBuffer, uint nNumberOfBytesToRead, byte[] lpNumberOfBytesRead, uint lpOverlapped);
39 |
40 | public void Disconnect()
41 | {
42 | DisconnectNamedPipe(PipeHandle);
43 | }
44 |
45 | public void Dispose()
46 | {
47 | Dispose(disposing: true);
48 | GC.SuppressFinalize(this);
49 | }
50 |
51 | protected virtual void Dispose(bool disposing)
52 | {
53 | if (disposing)
54 | {
55 | PipeHandle.Dispose();
56 | }
57 | }
58 |
59 | public bool Connect(Process ClientProcess)
60 | {
61 | try
62 | {
63 | string lpName = "\\\\.\\pipe\\" + ClientProcess.Id + "cout";
64 | PipeHandle = CreateNamedPipe(lpName, 1u, 0u, 1u, 1024u, 1024u, 1000u, IntPtr.Zero);
65 | if (PipeHandle.IsInvalid)
66 | {
67 | return false;
68 | }
69 | ConnectNamedPipe(PipeHandle, null);
70 | }
71 | catch (Exception)
72 | {
73 | return false;
74 | }
75 | return true;
76 | }
77 |
78 | public string Read()
79 | {
80 | byte[] array = new byte[1025];
81 | byte[] array2 = new byte[4];
82 | string text = "";
83 | ReadFile(PipeHandle, array, 1024u, array2, 0u);
84 | int num = array2[0] + (array2[1] << 8) + (array2[2] << 16) + (array2[3] << 24);
85 | for (int i = 0; i < num; i += 2)
86 | {
87 | int num2 = array[i] + (array[i + 1] << 8);
88 | text += (char)num2;
89 | }
90 | return text;
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/ModdingTools.Cli/ModdingTools.Cli.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {23733746-7020-4E5B-958F-E3AA34E9E60F}
8 | Exe
9 | ModdingTools.Cli
10 | ModdingTools.Cli
11 | v4.8
12 | 512
13 | true
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | false
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {0569be64-ba84-4c53-9296-ee830f5a002f}
53 | ModdingTools
54 | False
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/fcTLChunk.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace LibAPNG
4 | {
5 | public enum DisposeOps
6 | {
7 | APNGDisposeOpNone = 0,
8 | APNGDisposeOpBackground = 1,
9 | APNGDisposeOpPrevious = 2,
10 | }
11 |
12 | public enum BlendOps
13 | {
14 | APNGBlendOpSource = 0,
15 | APNGBlendOpOver = 1,
16 | }
17 |
18 | public class fcTLChunk : Chunk
19 | {
20 | public fcTLChunk(byte[] bytes)
21 | : base(bytes)
22 | {
23 | }
24 |
25 | public fcTLChunk(MemoryStream ms)
26 | : base(ms)
27 | {
28 | }
29 |
30 | public fcTLChunk(Chunk chunk)
31 | : base(chunk)
32 | {
33 | }
34 |
35 | ///
36 | /// Sequence number of the animation chunk, starting from 0
37 | ///
38 | public uint SequenceNumber { get; private set; }
39 |
40 | ///
41 | /// Width of the following frame
42 | ///
43 | public uint Width { get; private set; }
44 |
45 | ///
46 | /// Height of the following frame
47 | ///
48 | public uint Height { get; private set; }
49 |
50 | ///
51 | /// X position at which to render the following frame
52 | ///
53 | public uint XOffset { get; private set; }
54 |
55 | ///
56 | /// Y position at which to render the following frame
57 | ///
58 | public uint YOffset { get; private set; }
59 |
60 | ///
61 | /// Frame delay fraction numerator
62 | ///
63 | public ushort DelayNum { get; private set; }
64 |
65 | ///
66 | /// Frame delay fraction denominator
67 | ///
68 | public ushort DelayDen { get; private set; }
69 |
70 | ///
71 | /// Type of frame area disposal to be done after rendering this frame
72 | ///
73 | public DisposeOps DisposeOp { get; private set; }
74 |
75 | ///
76 | /// Type of frame area rendering for this frame
77 | ///
78 | public BlendOps BlendOp { get; private set; }
79 |
80 | protected override void ParseData(MemoryStream ms)
81 | {
82 | SequenceNumber = Helper.ConvertEndian(ms.ReadUInt32());
83 | Width = Helper.ConvertEndian(ms.ReadUInt32());
84 | Height = Helper.ConvertEndian(ms.ReadUInt32());
85 | XOffset = Helper.ConvertEndian(ms.ReadUInt32());
86 | YOffset = Helper.ConvertEndian(ms.ReadUInt32());
87 | DelayNum = Helper.ConvertEndian(ms.ReadUInt16());
88 | DelayDen = Helper.ConvertEndian(ms.ReadUInt16());
89 | DisposeOp = (DisposeOps)ms.ReadByte();
90 | BlendOp = (BlendOps)ms.ReadByte();
91 | }
92 | }
93 | }
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Frame.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace LibAPNG
5 | {
6 | ///
7 | /// Describe a single frame.
8 | ///
9 | public class Frame
10 | {
11 | public static byte[] Signature = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
12 |
13 | private List idatChunks = new List();
14 | private List otherChunks = new List();
15 |
16 | ///
17 | /// Gets or Sets the acTL chunk
18 | ///
19 | public IHDRChunk IHDRChunk { get; set; }
20 |
21 | ///
22 | /// Gets or Sets the fcTL chunk
23 | ///
24 | public fcTLChunk fcTLChunk { get; set; }
25 |
26 | ///
27 | /// Gets or Sets the IEND chunk
28 | ///
29 | public IENDChunk IENDChunk { get; set; }
30 |
31 | ///
32 | /// Gets or Sets the other chunks
33 | ///
34 | public List OtherChunks
35 | {
36 | get { return otherChunks; }
37 | set { otherChunks = value; }
38 | }
39 |
40 | ///
41 | /// Gets or Sets the IDAT chunks
42 | ///
43 | public List IDATChunks
44 | {
45 | get { return idatChunks; }
46 | set { idatChunks = value; }
47 | }
48 |
49 | ///
50 | /// Add an Chunk to end end of existing list.
51 | ///
52 | public void AddOtherChunk(OtherChunk chunk)
53 | {
54 | otherChunks.Add(chunk);
55 | }
56 |
57 | ///
58 | /// Add an IDAT Chunk to end end of existing list.
59 | ///
60 | public void AddIDATChunk(IDATChunk chunk)
61 | {
62 | idatChunks.Add(chunk);
63 | }
64 |
65 | ///
66 | /// Gets the frame as PNG FileStream.
67 | ///
68 | public MemoryStream GetStream()
69 | {
70 | var ihdrChunk = new IHDRChunk(IHDRChunk);
71 | if (fcTLChunk != null)
72 | {
73 | // Fix frame size with fcTL data.
74 | ihdrChunk.ModifyChunkData(0, Helper.ConvertEndian(fcTLChunk.Width));
75 | ihdrChunk.ModifyChunkData(4, Helper.ConvertEndian(fcTLChunk.Height));
76 | }
77 |
78 | // Write image data
79 | var ms = new MemoryStream();
80 |
81 | ms.WriteBytes(Signature);
82 | ms.WriteBytes(ihdrChunk.RawData);
83 | otherChunks.ForEach(o => ms.WriteBytes(o.RawData));
84 | idatChunks.ForEach(i => ms.WriteBytes(i.RawData));
85 | ms.WriteBytes(IENDChunk.RawData);
86 |
87 | ms.Flush();
88 | ms.Position = 0;
89 | return ms;
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/ModdingTools/GUI/ConfigList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using ModdingTools.Windows;
10 | using ModdingTools.Modding;
11 |
12 | namespace ModdingTools.GUI
13 | {
14 | public partial class ConfigList : UserControl
15 | {
16 | private static int BarOffset = 10;
17 | private ModObject ModObj;
18 |
19 | public ConfigList()
20 | {
21 | InitializeComponent();
22 | }
23 |
24 | public void Fill(ModObject o)
25 | {
26 | ModObj = o;
27 |
28 | this.flowLayoutPanel1.SuspendLayout();
29 |
30 | this.flowLayoutPanel1.Controls.Clear();
31 | foreach (var item in o.Config)
32 | {
33 | var e = new ConfigItem(item, o);
34 | e.Padding = new Padding(0);
35 | e.Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
36 | this.flowLayoutPanel1.Controls.Add(e);
37 | }
38 | this.flowLayoutPanel1.ResumeLayout();
39 |
40 | UpdateWidths();
41 | }
42 |
43 | public void Append(ModObject.ModConfigItem conf, ModObject o)
44 | {
45 | this.flowLayoutPanel1.SuspendLayout();
46 |
47 | var e = new ConfigItem(conf, o);
48 | e.Padding = new Padding(0);
49 | e.Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
50 | this.flowLayoutPanel1.Controls.Add(e);
51 |
52 | this.flowLayoutPanel1.ResumeLayout();
53 |
54 | UpdateWidths();
55 | }
56 |
57 | private void UpdateWidths(bool useHack = true)
58 | {
59 | flowLayoutPanel1.SuspendLayout();
60 | foreach (var a in flowLayoutPanel1.Controls)
61 | {
62 | if (a is ConfigItem)
63 | {
64 | ((Control)a).Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
65 | }
66 | }
67 | flowLayoutPanel1.ResumeLayout();
68 |
69 | if (useHack)
70 | {
71 | this.flowLayoutPanel1.Width -= 1;
72 | this.flowLayoutPanel1.Width += 1; // little hack to force-update the layout
73 | }
74 | }
75 |
76 | private void mButtonBorderless1_Click(object sender, EventArgs e)
77 | {
78 | var cfg = new ModObject.ModConfigItem();
79 | ModObj.Config.Add(cfg);
80 | Append(cfg, ModObj);
81 | CallOnUpdateEvent();
82 | }
83 |
84 | private void flowLayoutPanel1_SizeChanged(object sender, EventArgs e)
85 | {
86 | UpdateWidths(false);
87 | }
88 |
89 | public event EventHandler OnUpdate;
90 | public virtual void CallOnUpdateEvent()
91 | {
92 | OnUpdate?.Invoke(this, new EventArgs());
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ModdingTools.Updater.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModdingTools.Updater.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ModdingTools/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | False
13 |
14 |
15 | False
16 |
17 |
18 | False
19 |
20 |
21 | True
22 |
23 |
24 | True
25 |
26 |
27 | False
28 |
29 |
30 |
31 |
32 |
33 | 0
34 |
35 |
36 | 8192
37 |
38 |
39 | False
40 |
41 |
42 | False
43 |
44 |
45 | False
46 |
47 |
48 | 0
49 |
50 |
51 |
52 |
53 |
54 | False
55 |
56 |
57 | False
58 |
59 |
60 | False
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/SteamWorkshopStorage.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Modding;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 |
8 | namespace ModdingTools.Engine
9 | {
10 | public class SteamWorkshopStorage
11 | {
12 | Dictionary SteamWorkshopData;
13 | private string FileName;
14 |
15 | public SteamWorkshopStorage(string fileName)
16 | {
17 | SteamWorkshopData = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
18 | this.FileName = fileName;
19 | Reload();
20 | }
21 |
22 | public long GetIdForMod(ModObject mod)
23 | {
24 | var dirname = mod.GetDirectoryName();
25 | if (SteamWorkshopData.ContainsKey(dirname))
26 | return SteamWorkshopData[dirname];
27 | return 0;
28 | }
29 |
30 | public void SetIdForMod(ModObject mod, long value)
31 | {
32 | var dirname = mod.GetDirectoryName();
33 | if (SteamWorkshopData.ContainsKey(dirname))
34 | SteamWorkshopData[dirname] = value;
35 | else
36 | SteamWorkshopData.Add(dirname, value);
37 | Save();
38 | }
39 |
40 | // New parser for the SteamWorkshop.ini file, maybe that will avoid parser mistakes... hopefully :huehpain:
41 | private void Reload()
42 | {
43 | SteamWorkshopData.Clear();
44 |
45 | if (!File.Exists(FileName)) return; // just do nothing if it doesn't exists
46 |
47 | var data = File.ReadAllLines(FileName);
48 |
49 | var nextLineShouldHaveValue = false;
50 | var cachedPrevLineName = "";
51 | foreach (var line in data)
52 | {
53 | var sanitized = line.Trim();
54 | if (sanitized.StartsWith("#") || sanitized.StartsWith("//") || string.IsNullOrEmpty(sanitized)) continue; // skip comments and empty lines
55 |
56 | if (sanitized.StartsWith("[") && sanitized.EndsWith("]"))
57 | {
58 | cachedPrevLineName = sanitized.TrimStart('[').TrimEnd(']');
59 | nextLineShouldHaveValue = true;
60 | }
61 | else if (nextLineShouldHaveValue && sanitized.Split('=')[0].Trim().StartsWith("WorkshopId"))
62 | {
63 | SteamWorkshopData.Add(cachedPrevLineName, long.Parse(sanitized.Split('=')[1].Trim()));
64 | nextLineShouldHaveValue = false;
65 | cachedPrevLineName = "";
66 | }
67 | }
68 | }
69 |
70 | public void Save()
71 | {
72 | var b = new StringBuilder();
73 | foreach (var e in SteamWorkshopData)
74 | {
75 | if (e.Value <= 0) continue; // skip empty values
76 | b.AppendLine($"[{e.Key}]");
77 | b.AppendLine($"WorkshopId={e.Value}");
78 | b.AppendLine("");
79 | }
80 | File.WriteAllText(FileName, b.ToString());
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/HuehProgressBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Drawing.Drawing2D;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Windows.Forms;
9 |
10 | namespace ModdingTools.GUI
11 | {
12 | public class HuehProgressBar : System.Windows.Forms.Control
13 | {
14 | Timer Timer;
15 | Image i1, i2, i3;
16 | const float scale = 0.4f;
17 |
18 | private int _oldValue = -1;
19 | private string _oldText = null;
20 | public int Value { get; set; } = 0;
21 | public new string Text { get; set; } = "...";
22 | public HuehProgressBar()
23 | {
24 | this.DoubleBuffered = true;
25 |
26 | i1 = ResizeImage(Properties.Resources.heeh_1b, scale);
27 | i2 = ResizeImage(Properties.Resources.heeh_2, scale);
28 | i3 = ResizeImage(Properties.Resources.heeh_3, scale);
29 |
30 | this.Paint += Form1_Paint;
31 |
32 | this.Timer = new Timer();
33 | Timer.Interval = 10;
34 | Timer.Tick += Timer_Tick;
35 | Timer.Start();
36 | }
37 |
38 | public static Image ResizeImage(Image image, float sc)
39 | {
40 | var new_width = image.Width * sc;
41 | var new_height = image.Height * sc;
42 | Bitmap new_image = new Bitmap((int)new_width, (int)new_height);
43 | Graphics g = Graphics.FromImage((Image)new_image);
44 | g.InterpolationMode = InterpolationMode.High;
45 | g.DrawImage(image, 0, 0, new_width, new_height);
46 | return new_image;
47 | }
48 |
49 | private void Form1_Paint(object sender, PaintEventArgs e)
50 | {
51 | var startPos = this.Height - i3.Height * 1;
52 | var clipOff = 20;
53 |
54 | var drawBrush = new SolidBrush(this.ForeColor);
55 | var drawFont = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit);
56 | var drawFormat = new StringFormat();
57 | drawFormat.Alignment = StringAlignment.Far;
58 |
59 | int posX = this.Width - (int)(i1.Width * 1.2f); //this.Width / 2 - i3.Width / 2;
60 |
61 | float progress = (this.Height - i3.Height - i1.Height) * (Math.Min((float)Value, 100f) / 100f);
62 | e.Graphics.SmoothingMode = SmoothingMode.None;
63 | e.Graphics.DrawImage(i2, new Rectangle(posX, startPos - (int)progress, i3.Width, (int)progress + clipOff));
64 | e.Graphics.DrawImage(i3, posX, startPos);
65 |
66 | var y = startPos - (i1.Height) - progress + clipOff;
67 | e.Graphics.DrawImage(i1, posX, y);
68 |
69 | e.Graphics.DrawString(Text, drawFont, drawBrush, posX - clipOff, y + clipOff / 2, drawFormat);
70 | drawFont.Dispose();
71 | }
72 |
73 | private void Timer_Tick(object sender, EventArgs e)
74 | {
75 | if (_oldText != Text || _oldValue != Value)
76 | {
77 | _oldText = Text;
78 | _oldValue = Value;
79 | this.Refresh();
80 | }
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/Tools/Benchmark.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ModdingTools.Windows.Tools
2 | {
3 | partial class Benchmark
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Benchmark));
32 | this.label1 = new System.Windows.Forms.Label();
33 | this.SuspendLayout();
34 | //
35 | // label1
36 | //
37 | this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 27.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
38 | this.label1.Location = new System.Drawing.Point(4, 44);
39 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
40 | this.label1.Name = "label1";
41 | this.label1.Size = new System.Drawing.Size(393, 127);
42 | this.label1.TabIndex = 1;
43 | this.label1.Text = "00:00:00";
44 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
45 | //
46 | // Benchmark
47 | //
48 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
49 | this.ClientSize = new System.Drawing.Size(400, 181);
50 | this.Controls.Add(this.label1);
51 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
52 | this.IsMaximizeButtonEnabled = false;
53 | this.IsMinimizeButtonEnabled = false;
54 | this.IsResizable = false;
55 | this.Location = new System.Drawing.Point(0, 0);
56 | this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
57 | this.MaximumSize = new System.Drawing.Size(2560, 1268);
58 | this.MinimumSize = new System.Drawing.Size(400, 123);
59 | this.Name = "Benchmark";
60 | this.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2);
61 | this.Text = "EDITOR TAS SPEEDRUN ANY%";
62 | this.TitlebarColor = System.Drawing.Color.Black;
63 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Benchmark_FormClosing);
64 | this.Controls.SetChildIndex(this.label1, 0);
65 | this.ResumeLayout(false);
66 |
67 | }
68 |
69 | #endregion
70 |
71 | private System.Windows.Forms.Label label1;
72 | }
73 | }
--------------------------------------------------------------------------------
/ModdingTools/Modding/ModDirectorySource.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Logging;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 |
9 | namespace ModdingTools.Modding
10 | {
11 | public class ModDirectorySource
12 | {
13 | public string Root { get; private set; }
14 | public string Name { get; private set; }
15 |
16 | public bool IsReadOnly { get; private set; }
17 | public bool Enabled { get; set; }
18 | public bool AutoLoad { get; set; }
19 |
20 | public ModObject FindModByScriptPath(string scriptPath)
21 | {
22 | var path = Path.GetFullPath(scriptPath).ToLower();
23 | var mods = GetMods();
24 | Logger.Log(CUFramework.Shared.LogLevel.Verbose, path);
25 | foreach (var mod in mods)
26 | {
27 | var x = Path.GetFullPath(mod.GetClassesDir()).ToLower();
28 | Logger.Log(CUFramework.Shared.LogLevel.Verbose, x);
29 |
30 | // idk I'm skeptical about this method... but for testing it should be enough
31 | if (path.StartsWith(x))
32 | return mod;
33 | }
34 | return null;
35 | }
36 |
37 | public ModObject[] GetMods(string modName = null)
38 | {
39 | List mods = new List();
40 | if (!AutoLoad)
41 | return mods.ToArray();
42 |
43 | if (!Directory.Exists(Root))
44 | return mods.ToArray();
45 |
46 | var paths = Directory.GetDirectories(Root);
47 | foreach (var path in paths)
48 | {
49 | if (modName != null)
50 | {
51 | if (!modName.Equals(Path.GetFileName(path), StringComparison.InvariantCultureIgnoreCase))
52 | {
53 | continue;
54 | }
55 | }
56 |
57 | var modIniPath = Path.Combine(path, "modinfo.ini");
58 | if (File.Exists(modIniPath))
59 | {
60 | try
61 | {
62 | var mod = new ModObject(path, this);
63 | mods.Add(mod);
64 | }
65 | catch (Exception ex)
66 | {
67 | CUFramework.Dialogs.CUMessageBox.Show($"Mod parser failed while reading mod {path}!\n" + ex.Message + "\n" + ex.ToString());
68 | Debug.WriteLine(":sealnyon: Oopsie woopsie!\n" + ex.Message + "\n" + ex.ToString());
69 | }
70 | }
71 | }
72 | return mods.ToArray();
73 | }
74 |
75 | public ModDirectorySource(string name, string path, bool autoLoad, bool defaultEnabled = true, bool isReadOnly = false)
76 | {
77 | this.Name = name;
78 | this.Root = path;
79 | this.AutoLoad = autoLoad;
80 |
81 | if (!Directory.Exists(path) && !isReadOnly)
82 | {
83 | Directory.CreateDirectory(path);
84 | }
85 |
86 | this.Enabled = defaultEnabled;
87 | this.IsReadOnly = isReadOnly;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/Chunks/Chunk.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 |
5 | namespace LibAPNG
6 | {
7 | public class Chunk
8 | {
9 | internal Chunk()
10 | {
11 | Length = 0;
12 | ChunkType = String.Empty;
13 | ChunkData = null;
14 | Crc = 0;
15 | }
16 |
17 | internal Chunk(byte[] bytes)
18 | {
19 | var ms = new MemoryStream(bytes);
20 | Length = Helper.ConvertEndian(ms.ReadUInt32());
21 | ChunkType = Encoding.ASCII.GetString(ms.ReadBytes(4));
22 | ChunkData = ms.ReadBytes((int)Length);
23 | Crc = Helper.ConvertEndian(ms.ReadUInt32());
24 |
25 | if (ms.Position != ms.Length)
26 | throw new Exception("Chunk length not correct.");
27 | if (Length != ChunkData.Length)
28 | throw new Exception("Chunk data length not correct.");
29 |
30 | ParseData(new MemoryStream(ChunkData));
31 | }
32 |
33 | internal Chunk(MemoryStream ms)
34 | {
35 | Length = Helper.ConvertEndian(ms.ReadUInt32());
36 | ChunkType = Encoding.ASCII.GetString(ms.ReadBytes(4));
37 | ChunkData = ms.ReadBytes((int)Length);
38 | Crc = Helper.ConvertEndian(ms.ReadUInt32());
39 |
40 | ParseData(new MemoryStream(ChunkData));
41 | }
42 |
43 | internal Chunk(Chunk chunk)
44 | {
45 | Length = chunk.Length;
46 | ChunkType = chunk.ChunkType;
47 | ChunkData = chunk.ChunkData;
48 | Crc = chunk.Crc;
49 |
50 | ParseData(new MemoryStream(ChunkData));
51 | }
52 |
53 | public uint Length { get; set; }
54 |
55 | public string ChunkType { get; set; }
56 |
57 | public byte[] ChunkData { get; set; }
58 |
59 | public uint Crc { get; set; }
60 |
61 | ///
62 | /// Get raw data of the chunk
63 | ///
64 | public byte[] RawData
65 | {
66 | get
67 | {
68 | var ms = new MemoryStream();
69 | ms.WriteUInt32(Helper.ConvertEndian(Length));
70 | ms.WriteBytes(Encoding.ASCII.GetBytes(ChunkType));
71 | ms.WriteBytes(ChunkData);
72 | ms.WriteUInt32(Helper.ConvertEndian(Crc));
73 |
74 | return ms.ToArray();
75 | }
76 | }
77 |
78 | ///
79 | /// Modify the ChunkData part.
80 | ///
81 | public void ModifyChunkData(int postion, byte[] newData)
82 | {
83 | Array.Copy(newData, 0, ChunkData, postion, newData.Length);
84 |
85 | using (var msCrc = new MemoryStream())
86 | {
87 | msCrc.WriteBytes(Encoding.ASCII.GetBytes(ChunkType));
88 | msCrc.WriteBytes(ChunkData);
89 |
90 | Crc = CrcHelper.Calculate(msCrc.ToArray());
91 | }
92 | }
93 |
94 | ///
95 | /// Modify the ChunkData part.
96 | ///
97 | public void ModifyChunkData(int postion, uint newData)
98 | {
99 | ModifyChunkData(postion, BitConverter.GetBytes(newData));
100 | }
101 |
102 | protected virtual void ParseData(MemoryStream ms)
103 | {
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/ModdingTools/Windows/ConfigWindow.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs;
2 | using CUFramework.Windows;
3 | using ModdingTools.Engine;
4 | using ModdingTools.GUI;
5 | using ModdingTools.Settings;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.ComponentModel;
9 | using System.Data;
10 | using System.Diagnostics;
11 | using System.Drawing;
12 | using System.IO;
13 | using System.Linq;
14 | using System.Text;
15 | using System.Windows.Forms;
16 |
17 | namespace ModdingTools.Windows
18 | {
19 | public partial class ConfigWindow : CUWindow
20 | {
21 | public ConfigWindow()
22 | {
23 | InitializeComponent();
24 | if (!DesignMode)
25 | {
26 | LoadSettings();
27 | }
28 | }
29 |
30 | private void LoadSettings()
31 | {
32 | checkBox1.Checked = !OMMSettings.Instance.AutoScanDownloadedMods;
33 | checkBox2.Checked = OMMSettings.Instance.Memes;
34 | checkBox4.Checked = OMMSettings.Instance.MultilangCook;
35 | checkBox3.Checked = OMMSettings.Instance.RmShaderOnCook;
36 | checkBox5.Checked = OMMSettings.Instance.UpdateCheck;
37 | checkBox6.Checked = OMMSettings.Instance.FastCook;
38 | checkBox7.Checked = OMMSettings.Instance.VSCIntegration;
39 | checkBox8.Checked = OMMSettings.Instance.KillGameBeforeCooking;
40 | checkBox9.Checked = OMMSettings.Instance.KillEditorBeforeCooking;
41 | checkBox10.Checked = OMMSettings.Instance.MafiaPunchGameToo;
42 | checkBox11.Checked = OMMSettings.Instance.AlwaysloadedWorkaround;
43 | }
44 |
45 | private void SaveSettings()
46 | {
47 | OMMSettings.Instance.AutoScanDownloadedMods = !checkBox1.Checked;
48 | OMMSettings.Instance.Memes = checkBox2.Checked;
49 | OMMSettings.Instance.MultilangCook = checkBox4.Checked;
50 | OMMSettings.Instance.RmShaderOnCook = checkBox3.Checked;
51 | OMMSettings.Instance.UpdateCheck = checkBox5.Checked;
52 | OMMSettings.Instance.FastCook = checkBox6.Checked;
53 | OMMSettings.Instance.VSCIntegration = checkBox7.Checked;
54 | OMMSettings.Instance.KillGameBeforeCooking = checkBox8.Checked;
55 | OMMSettings.Instance.KillEditorBeforeCooking = checkBox9.Checked;
56 | OMMSettings.Instance.MafiaPunchGameToo = checkBox10.Checked;
57 | OMMSettings.Instance.AlwaysloadedWorkaround = checkBox11.Checked;
58 | OMMSettings.Instance.Save();
59 | }
60 |
61 | private void mButton3_Click(object sender, EventArgs e)
62 | {
63 | this.Close();
64 | }
65 |
66 | private void mButton2_Click(object sender, EventArgs e)
67 | {
68 | if (checkBox11.Checked && checkBox6.Checked)
69 | {
70 | CUMessageBox.Show("Fast script cooking and alwaysloaded workaround cannot be enabled at the same time!");
71 | return;
72 | }
73 |
74 | SaveSettings();
75 | this.Close();
76 | }
77 |
78 | private void label1_Click(object sender, EventArgs e)
79 | {
80 | Utils.StartInDefaultBrowser("https://marketplace.visualstudio.com/items?itemName=EliotVU.uc");
81 | }
82 |
83 | private void cuButton1_Click(object sender, EventArgs e)
84 | {
85 | Utils.KillUpdater();
86 | Process.Start(Path.Combine(Program.GetAppRoot(), "ModdingTools.Updater.exe"));
87 | Program.CloseApp(0);
88 | }
89 |
90 | private void cuButton2_Click(object sender, EventArgs e)
91 | {
92 | var conf = new ArgEditor();
93 | conf.StartPosition = FormStartPosition.CenterParent;
94 | conf.ShowDialog();
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/Validators/ModdingValidators.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs.Validators;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 |
9 | namespace ModdingTools.Windows.Validators
10 | {
11 | public class ModNameValidator : IValidator
12 | {
13 | public string Validate(string inputText)
14 | {
15 | if (inputText.Length < 3)
16 | {
17 | return "Mod name should have at least 3 characters";
18 | }
19 |
20 | if (!Regex.IsMatch(inputText, @"^[a-zA-Z0-9_]+$"))
21 | {
22 | return "Invalid characters in mod folder name - you can only use numbers and letters and _";
23 | }
24 |
25 | if (inputText.ToLower().Trim() == "newmod" || inputText.ToLower().Trim() == "mymod")
26 | {
27 | return "Seriously? Give it some more unique name...";
28 | }
29 |
30 | string modName = inputText;
31 | string modsRoot = Path.Combine(Program.ProcFactory.GetGamePath(), @"HatinTimeGame\Mods");
32 | string modPath = Path.Combine(modsRoot, modName);
33 | string modInfoPath = Path.Combine(modPath, "modinfo.ini");
34 |
35 | if (File.Exists(modInfoPath))
36 | {
37 | return "There's already a mod with name \"" + modName + "\". Please delete it or set it up.";
38 | }
39 |
40 | return null;
41 | }
42 | }
43 |
44 | public class ARValidator : IValidator
45 | {
46 | public string Validate(string inputText)
47 | {
48 |
49 | if (!Regex.IsMatch(inputText, @"[A-Za-z0-9]{1,255}\'[A-Za-z0-9\.\-_]{1,255}\'$"))
50 | {
51 | return "Invalid asset name!\nIt should look something like this: StaticMesh'MyPackage.MyMesh'";
52 | }
53 | return null;
54 | }
55 | }
56 |
57 | public class WildcardValidator : IValidator
58 | {
59 | public string Validate(string inputText)
60 | {
61 | var e = inputText.Trim().Replace("/", "\\");
62 | if (e.StartsWith("\\") || e.StartsWith(".\\"))
63 | return "Use only relative file paths here!";
64 |
65 | if (e.Contains(".."))
66 | return "No, you can't use .. here...";
67 |
68 | if (e.Contains("<") || e.Contains(">") || e.Contains("]") || e.Contains("|") || e.Contains("?") || e.Contains("\"") || e.Contains(":"))
69 | return "No, you can't use []|?<>\": characters here...";
70 |
71 | if (e.EndsWith("\\"))
72 | return "Don't add \\ character at the end... If you want to exclude directory contents, type 'DirectoryName\\*' instead!";
73 |
74 | var exploded = e.Split('\\');
75 | if (exploded.Length > 1)
76 | {
77 | for (var x = 0; x != exploded.Length - 2; x++)
78 | if (exploded[x].Contains("*"))
79 | return "No, you can't use wildcards in the top directory names!";
80 | }
81 |
82 | return null;
83 | }
84 | }
85 |
86 | public class SplitListValidator : IValidator
87 | {
88 | char SplitChar;
89 | public SplitListValidator(char splitChar)
90 | {
91 | this.SplitChar = splitChar;
92 | }
93 |
94 | public string Validate(string inputText)
95 | {
96 | if (inputText.Contains(SplitChar))
97 | {
98 | return $"Item shouldn't contain the '{SplitChar}' character.";
99 | }
100 | return null;
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/ScriptWatcher.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Modding;
2 | using ModdingTools.Windows;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Threading.Tasks;
7 |
8 | namespace ModdingTools.Engine
9 | {
10 | class ScriptWatcherManager
11 | {
12 | private static Dictionary WatcherProcesses = new Dictionary();
13 | public static void AttachWatcher(ModObject o)
14 | {
15 | if (WatcherProcesses.ContainsKey(o.GetDirectoryName()))
16 | {
17 | return;
18 | }
19 | WatcherProcesses.Add(o.GetDirectoryName(), new ScriptWatcher(o));
20 | }
21 |
22 | public static void DetachWatcher(ModObject o)
23 | {
24 | if (WatcherProcesses.ContainsKey(o.GetDirectoryName()))
25 | {
26 | WatcherProcesses[o.GetDirectoryName()].Dispose();
27 | WatcherProcesses.Remove(o.GetDirectoryName());
28 | }
29 | }
30 |
31 | public static bool IsWatcherAttached(ModObject o)
32 | {
33 | return WatcherProcesses.ContainsKey(o.GetDirectoryName());
34 | }
35 | }
36 |
37 | class ScriptWatcher : IDisposable
38 | {
39 | FileSystemWatcher watcher;
40 | readonly ModObject Mod;
41 |
42 | public ScriptWatcher(ModObject mod)
43 | {
44 | this.Mod = mod;
45 | var path = mod.RootPath;
46 |
47 | // Create a new FileSystemWatcher and set its properties.
48 | watcher = new FileSystemWatcher();
49 | watcher.Path = Path.Combine(path, "Classes");
50 |
51 | /* Watch for changes in LastAccess and LastWrite times, and
52 | the renaming of files or directories. */
53 | watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
54 | | NotifyFilters.FileName | NotifyFilters.DirectoryName;
55 |
56 | // Only watch script files.
57 | watcher.Filter = "*.uc";
58 |
59 | // Add event handlers.
60 | watcher.Changed += new FileSystemEventHandler(OnChanged);
61 | watcher.Renamed += new RenamedEventHandler(OnRenamed);
62 |
63 | watcher.EnableRaisingEvents = true;
64 | }
65 |
66 |
67 |
68 | // Define the event handlers.
69 |
70 | long lastMillis;
71 | private void OnChanged(object source, FileSystemEventArgs e)
72 | {
73 | if (Utils.GetUnixTimestamp(DateTime.Now) - lastMillis > 1000)
74 | {
75 | lastMillis = Utils.GetUnixTimestamp(DateTime.Now);
76 | }
77 | else
78 | {
79 | return;
80 | }
81 |
82 | try
83 | {
84 | watcher.EnableRaisingEvents = false;
85 | if (e.ChangeType == WatcherChangeTypes.Changed)
86 | {
87 | var ph = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(e.FullPath)));
88 | Mod.UnCookMod();
89 | Task.Factory.StartNew(() =>
90 | {
91 | MainWindow.Instance.Runner.KillAllWorkers();
92 | Mod.CompileScripts(MainWindow.Instance.Runner, true);
93 | });
94 | }
95 |
96 | }
97 | finally
98 | {
99 | watcher.EnableRaisingEvents = true;
100 | }
101 | }
102 |
103 | private void OnRenamed(object source, RenamedEventArgs e)
104 | {
105 | }
106 |
107 | public void Dispose()
108 | {
109 | watcher.Dispose();
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/MapChooser.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Windows;
2 | using ModdingTools.Modding;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Data;
7 | using System.Drawing;
8 | using System.IO;
9 | using System.Linq;
10 | using System.Runtime.InteropServices;
11 | using System.Text;
12 | using System.Windows.Forms;
13 | using static ModdingTools.Windows.ModProperties;
14 | using static System.Windows.Forms.VisualStyles.VisualStyleElement;
15 |
16 | namespace ModdingTools.Windows
17 | {
18 | public partial class MapChooser : CUWindow
19 | {
20 | [DllImport("user32.dll")]
21 | static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
22 |
23 | static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
24 | const UInt32 SWP_NOSIZE = 0x0001;
25 | const UInt32 SWP_NOMOVE = 0x0002;
26 | const UInt32 SWP_SHOWWINDOW = 0x0040;
27 |
28 | private ModObject Mod;
29 | public MapChooser(ModObject o)
30 | {
31 | InitializeComponent();
32 | Mod = o;
33 |
34 | this.HandleCreated += MapChooser_HandleCreated;
35 |
36 | string lastMap = "";
37 | try
38 | {
39 | var flagFile = Path.Combine(Mod.RootPath, ".lastMap");
40 | if (File.Exists(flagFile))
41 | lastMap = File.ReadAllText(flagFile);
42 | }
43 | catch (Exception)
44 | {
45 | }
46 |
47 | comboBox1.Items.Add(new MapItem("hub_spaceship", "Spaceship", true));
48 | comboBox1.Items.Add(new MapItem("mafia_town", "Mafia Town", true));
49 | comboBox1.Items.Add(new MapItem("hatintimeentry", "HatInTimeEntry", true));
50 | comboBox1.Items.Add(new MapItem("??menu", "Main Menu", true));
51 |
52 | var maps = Mod.GetCookedMaps();
53 | if (maps != null)
54 | foreach (var a in maps)
55 | {
56 | comboBox1.Items.Add(new MapItem(a, null, true));
57 | if (a.Equals(Mod.IntroductionMap, StringComparison.InvariantCultureIgnoreCase))
58 | {
59 | comboBox1.SelectedIndex = comboBox1.Items.Count - 1;
60 | }
61 | }
62 | if (comboBox1.SelectedIndex < 0)
63 | {
64 | comboBox1.SelectedIndex = 0;
65 | }
66 |
67 | if (string.IsNullOrEmpty(lastMap)) return;
68 |
69 | foreach(var x in comboBox1.Items)
70 | {
71 | var item = (MapItem)x;
72 | if (item.Name.Equals(lastMap, StringComparison.InvariantCultureIgnoreCase))
73 | {
74 | comboBox1.SelectedItem = x;
75 | break;
76 | }
77 | }
78 | }
79 |
80 | private void MapChooser_HandleCreated(object sender, EventArgs e)
81 | {
82 | SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
83 | }
84 |
85 | public string GetSelectedMap()
86 | {
87 | return ((MapItem)comboBox1.SelectedItem).Name;
88 | }
89 |
90 | private void mButton9_Click(object sender, EventArgs e)
91 | {
92 | var item = (MapItem)comboBox1.SelectedItem;
93 | try
94 | {
95 | File.WriteAllText(Path.Combine(Mod.RootPath, ".lastMap"), item.Name);
96 | }
97 | catch (Exception) { }
98 | this.DialogResult = DialogResult.OK;
99 | }
100 |
101 | private void cuButton1_Click(object sender, EventArgs e)
102 | {
103 | this.DialogResult = DialogResult.Cancel;
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/UModelFacade.cs:
--------------------------------------------------------------------------------
1 | using ModdingTools.Engine.TGA;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Drawing;
6 | using System.Drawing.Imaging;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Text;
10 |
11 | namespace ModdingTools.Engine
12 | {
13 | public class UModelFacade
14 | {
15 |
16 | public UModelFacade()
17 | {
18 | if (!File.Exists(GetUModelEXE()))
19 | {
20 | throw new Exception("Please, place the umodel.exe and SDL2.dll into the program root directory and try again!\nYou can download it from https://www.gildor.org/en/projects/umodel");
21 | }
22 | }
23 |
24 |
25 | public enum ExportType
26 | {
27 | SoundNodeWave, Texture2D, StaticMesh, AnimSet, Font
28 | }
29 |
30 | private string GetUModelEXE()
31 | {
32 | return Path.Combine(Program.GetAppRoot(), "umodel.exe");
33 | }
34 |
35 | private string GetTMPDir()
36 | {
37 | return Path.Combine(Program.GetAppRoot(), "ExporterTMP");
38 | }
39 |
40 | public static string GetExtensionForType(ExportType exportType, bool forcePng = false)
41 | {
42 | string extension = null;
43 | switch (exportType)
44 | {
45 | case ExportType.SoundNodeWave:
46 | extension = ".ogg";
47 | break;
48 | case ExportType.Texture2D:
49 | extension = forcePng ? ".png" : ".tga";
50 | break;
51 | }
52 | return extension;
53 | }
54 |
55 | public bool Run(string args)
56 | {
57 | Debug.WriteLine("CmdArgs >> " + args);
58 | var p = new Process();
59 | p.StartInfo.FileName = GetUModelEXE();
60 | p.StartInfo.Arguments = args;
61 | p.StartInfo.UseShellExecute = false;
62 | p.StartInfo.CreateNoWindow = true;
63 | p.Start();
64 |
65 | p.WaitForExit();
66 |
67 | return p.ExitCode == 0;
68 | }
69 |
70 | public bool Export(string root, string package, string assetName, string group, ExportType exportType, string destination, bool forceTgaToPng = false)
71 | {
72 | var tmpDir = GetTMPDir();
73 | if (Directory.Exists(tmpDir))
74 | {
75 | Directory.Delete(tmpDir, true);
76 | }
77 | Directory.CreateDirectory(tmpDir);
78 |
79 | // .\umodel.exe -game=ue3 -path="C:\Program Files (x86)\Steam\steamapps\common\HatinTime\HatinTimeGame\EditorCookedPC" -export HatinTime_Music_Metro4 Act_4_Pink_Paw_Station -sounds -out=".\test"
80 | var res = Run($"-game=ue3 -path=\"{root}\" -3rdparty -groups -export {package} {assetName}{(exportType == ExportType.SoundNodeWave ? " -sounds" : " " + exportType.ToString())} -out=\"{tmpDir}\"");
81 | if (!res)
82 | {
83 | return false;
84 | }
85 |
86 | var extension = GetExtensionForType(exportType);
87 |
88 | var path = Path.Combine(tmpDir, package, group.Replace('.', Path.DirectorySeparatorChar), assetName + extension);
89 | Debug.WriteLine("ExceptedPath: " + path);
90 |
91 | if (File.Exists(path))
92 | {
93 | if (File.Exists(destination))
94 | {
95 | File.Delete(destination);
96 | }
97 |
98 | if (forceTgaToPng && exportType == ExportType.Texture2D)
99 | {
100 | using (var b = new TargaImage(path))
101 | {
102 | b.Image.Save(destination, ImageFormat.Png);
103 | }
104 | }
105 | else
106 | {
107 | File.Move(path, destination);
108 | }
109 | return true;
110 | }
111 |
112 | return false;
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/ARList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using ModdingTools.Windows;
10 | using ModdingTools.Windows.Validators;
11 | using CUFramework.Dialogs;
12 |
13 | namespace ModdingTools.GUI
14 | {
15 | public partial class ARList : UserControl
16 | {
17 | private static int BarOffset = 10;
18 |
19 | public ARList()
20 | {
21 | InitializeComponent();
22 | }
23 |
24 | public void Fill(Dictionary dictonary)
25 | {
26 | this.flowLayoutPanel1.SuspendLayout();
27 |
28 | this.flowLayoutPanel1.Controls.Clear();
29 | foreach (var item in dictonary)
30 | {
31 | var e = new ARItem(item.Key, item.Value);
32 | e.Padding = new Padding(0);
33 | e.Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
34 | this.flowLayoutPanel1.Controls.Add(e);
35 | }
36 | this.flowLayoutPanel1.ResumeLayout();
37 |
38 | UpdateWidths();
39 | }
40 |
41 | public void Append(string key, string val)
42 | {
43 | this.flowLayoutPanel1.SuspendLayout();
44 |
45 | var e = new ARItem(key, val);
46 | e.Padding = new Padding(0);
47 | e.Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
48 | this.flowLayoutPanel1.Controls.Add(e);
49 |
50 | this.flowLayoutPanel1.ResumeLayout();
51 |
52 | UpdateWidths();
53 | }
54 |
55 | private void UpdateWidths(bool useHack = true)
56 | {
57 | flowLayoutPanel1.SuspendLayout();
58 | foreach (var a in flowLayoutPanel1.Controls)
59 | {
60 | if (a is ARItem)
61 | {
62 | ((Control)a).Width = flowLayoutPanel1.ClientSize.Width - BarOffset;
63 | }
64 | }
65 | flowLayoutPanel1.ResumeLayout();
66 |
67 | if (useHack)
68 | {
69 | this.flowLayoutPanel1.Width -= 1;
70 | this.flowLayoutPanel1.Width += 1; // little hack to force-update the layout
71 | }
72 | }
73 |
74 | public Dictionary Collect()
75 | {
76 | var d = new Dictionary();
77 | foreach (var a in flowLayoutPanel1.Controls)
78 | {
79 | if (a is ARItem)
80 | {
81 | var item = (ARItem)a;
82 | d.Add(item.Target, item.Replacement);
83 | }
84 | }
85 | return d;
86 | }
87 |
88 | private void CUButtonBorderless1_Click(object sender, EventArgs e)
89 | {
90 | string source = CUInputWindow.Ask(this, "Asset Replacement: from", "Enter the asset name which you want to replace", new ARValidator());
91 | if (source != null)
92 | {
93 | if (Collect().Where(item => item.Key.ToLowerInvariant() == source.ToLowerInvariant()).Count() > 0)
94 | {
95 | CUMessageBox.Show("ARList already contains item with key: " + source, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
96 | return;
97 | }
98 |
99 | string target = CUInputWindow.Ask(this, "Asset Replacement: to", $"Replacement: {source}{Environment.NewLine}Enter the target asset name", new ARValidator());
100 | if (target != null)
101 | {
102 | Append(source, target);
103 | CallOnUpdateEvent();
104 | }
105 | }
106 | }
107 |
108 | private void flowLayoutPanel1_SizeChanged(object sender, EventArgs e)
109 | {
110 | UpdateWidths(false);
111 | }
112 |
113 | public event EventHandler OnUpdate;
114 | public virtual void CallOnUpdateEvent()
115 | {
116 | OnUpdate?.Invoke(this, new EventArgs());
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/WorkshopLocker.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs;
2 | using CUFramework.Windows;
3 | using ModdingTools.Engine;
4 | using System;
5 | using System.Drawing;
6 | using System.IO;
7 | using System.Security.AccessControl;
8 | using System.Security.Principal;
9 |
10 | namespace ModdingTools.Windows
11 | {
12 | public partial class WorkshopLocker : CUWindow
13 | {
14 | public WorkshopLocker()
15 | {
16 | InitializeComponent();
17 | UpdateState();
18 | }
19 |
20 | private void UpdateState()
21 | {
22 | var wsDir = GameFinder.GetWorkshopDir();
23 | if (!Directory.Exists(wsDir))
24 | Directory.CreateDirectory(wsDir);
25 | DirectoryInfo dInfo = new DirectoryInfo(wsDir);
26 | try
27 | {
28 | var testFile = Path.Combine(wsDir, ".test");
29 | File.WriteAllText(testFile, "test");
30 | File.Delete(testFile);
31 | label1.Text = "UNLOCKED";
32 | label1.ForeColor = Color.Green;
33 | }
34 | catch (UnauthorizedAccessException)
35 | {
36 | label1.Text = "LOCKED";
37 | label1.ForeColor = Color.Red;
38 | }
39 | }
40 |
41 |
42 | public void ChangeLockState(string path, bool unlocked)
43 | {
44 | try
45 | {
46 | RemoveOldProtection(path);
47 | var x = path + ".disabled";
48 | if (unlocked && Directory.Exists(x))
49 | {
50 | ApplyProtection(path, false);
51 | Directory.Delete(path, false);
52 | Directory.Move(x, path);
53 | }
54 | else if (!unlocked && !Directory.Exists(x))
55 | {
56 | Directory.Move(path, x);
57 | Directory.CreateDirectory(path);
58 | ApplyProtection(path, true);
59 | }
60 | }
61 | catch (Exception e)
62 | {
63 | CUMessageBox.Show(e.Message);
64 | }
65 | UpdateState();
66 | }
67 |
68 | public void RemoveOldProtection(string path)
69 | {
70 | // for compatibilty with old algo
71 | DirectoryInfo dInfo = new DirectoryInfo(path);
72 | DirectorySecurity dSecurity = dInfo.GetAccessControl();
73 | var rule = new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
74 | FileSystemRights.Write | FileSystemRights.ReadAndExecute | FileSystemRights.ListDirectory, InheritanceFlags.None,
75 | PropagationFlags.NoPropagateInherit, AccessControlType.Deny);
76 | dSecurity.RemoveAccessRule(rule);
77 | dInfo.SetAccessControl(dSecurity);
78 | }
79 |
80 |
81 | public void ApplyProtection(string path, bool v)
82 | {
83 | DirectoryInfo dInfo = new DirectoryInfo(path);
84 | DirectorySecurity dSecurity = dInfo.GetAccessControl();
85 | var rule = new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
86 | FileSystemRights.Write, InheritanceFlags.None,
87 | PropagationFlags.NoPropagateInherit, AccessControlType.Deny);
88 | if(v)
89 | {
90 | dSecurity.AddAccessRule(rule);
91 | }
92 | else
93 | {
94 | dSecurity.RemoveAccessRule(rule);
95 | }
96 | dInfo.SetAccessControl(dSecurity);
97 | }
98 |
99 | private void mButton2_Click(object sender, EventArgs e)
100 | {
101 | var wsDir = GameFinder.GetWorkshopDir();
102 | if (!Directory.Exists(wsDir))
103 | Directory.CreateDirectory(wsDir);
104 |
105 | ChangeLockState(wsDir, false);
106 | }
107 |
108 | private void cuButton1_Click(object sender, EventArgs e)
109 | {
110 | var wsDir = GameFinder.GetWorkshopDir();
111 | if (!Directory.Exists(wsDir))
112 | Directory.CreateDirectory(wsDir);
113 |
114 | ChangeLockState(wsDir, true);
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/ModdingTools.Updater.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {25AAAE0C-404D-4877-AF19-F6245EB17F0E}
8 | WinExe
9 | ModdingTools.Updater
10 | ModdingTools.Updater
11 | v4.8
12 | 512
13 | true
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | false
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Form
53 |
54 |
55 | Form
56 |
57 |
58 | MainWindow.cs
59 |
60 |
61 |
62 |
63 |
64 | MainWindow.cs
65 |
66 |
67 | ResXFileCodeGenerator
68 | Resources.Designer.cs
69 | Designer
70 |
71 |
72 | True
73 | Resources.resx
74 | True
75 |
76 |
77 |
78 | SettingsSingleFileGenerator
79 | Settings.Designer.cs
80 |
81 |
82 | True
83 | Settings.settings
84 | True
85 |
86 |
87 |
88 |
89 | {50A7E9B0-70EF-11D1-B75A-00A0C90564FE}
90 | 1
91 | 0
92 | 0
93 | tlbimp
94 | False
95 | True
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/ArrayInputWindow.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs;
2 | using CUFramework.Dialogs.Validators;
3 | using CUFramework.Windows;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 |
13 | namespace ModdingTools.Windows
14 | {
15 | public partial class ArrayInputWindow : CUWindow
16 | {
17 | public bool AllowDuplicates { get; set; }
18 |
19 | public IValidator Validator;
20 |
21 | public ArrayInputWindow(IValidator validator = null)
22 | {
23 | InitializeComponent();
24 | this.Validator = validator;
25 | }
26 |
27 | public static List Ask(string title, string desc, string[] defaultItems, IValidator validator)
28 | {
29 | var a = new ArrayInputWindow(validator);
30 | a.label1.Text = desc;
31 | a.Text = title;
32 | if (defaultItems != null)
33 | a.listBox1.Items.AddRange(defaultItems);
34 | var result = a.ShowDialog();
35 | if (result == DialogResult.OK)
36 | {
37 | var res = new List();
38 | foreach (var i in a.listBox1.Items)
39 | res.Add((string)i);
40 | return res;
41 | }
42 | return null;
43 | }
44 |
45 | private void cuButton2_Click(object sender, EventArgs e)
46 | {
47 | this.DialogResult = DialogResult.Cancel;
48 | }
49 |
50 | private void cuButton1_Click(object sender, EventArgs e)
51 | {
52 | this.DialogResult = DialogResult.OK;
53 | }
54 |
55 | private void cuButton3_Click(object sender, EventArgs e)
56 | {
57 | if (listBox1.Items.Contains(cuTextBox1.Text) && !AllowDuplicates)
58 | {
59 | CUMessageBox.Show("The list already contains an element with this name!");
60 | return;
61 | }
62 | var result = Validator != null ? Validator.Validate(cuTextBox1.Text) : "";
63 | if (string.IsNullOrEmpty(result))
64 | {
65 | listBox1.Items.Add(cuTextBox1.Text);
66 | cuTextBox1.Text = "";
67 | }
68 | else
69 | {
70 | CUMessageBox.Show(result);
71 | }
72 | }
73 |
74 | private void cuButton5_Click(object sender, EventArgs e)
75 | {
76 | MoveItem(-1);
77 | }
78 |
79 | // https://stackoverflow.com/questions/4796109/how-to-move-item-in-listbox-up-and-down
80 | public void MoveItem(int direction)
81 | {
82 | // Checking selected item
83 | if (listBox1.SelectedItem == null || listBox1.SelectedIndex < 0)
84 | return; // No selected item - nothing to do
85 |
86 | // Calculate new index using move direction
87 | int newIndex = listBox1.SelectedIndex + direction;
88 |
89 | // Checking bounds of the range
90 | if (newIndex < 0 || newIndex >= listBox1.Items.Count)
91 | return; // Index out of range - nothing to do
92 |
93 | object selected = listBox1.SelectedItem;
94 |
95 | // Removing removable element
96 | listBox1.Items.Remove(selected);
97 | // Insert it in new position
98 | listBox1.Items.Insert(newIndex, selected);
99 | // Restore selection
100 | listBox1.SetSelected(newIndex, true);
101 | }
102 |
103 | private void cuButton6_Click(object sender, EventArgs e)
104 | {
105 | MoveItem(1);
106 | }
107 |
108 | private void cuButton4_Click(object sender, EventArgs e)
109 | {
110 | while (listBox1.SelectedItems.Count > 0)
111 | listBox1.Items.Remove(listBox1.SelectedItem);
112 | }
113 |
114 | private void cuTextBox1_KeyDown(object sender, KeyEventArgs e)
115 | {
116 | if (e.KeyCode == Keys.Enter)
117 | {
118 | cuButton3_Click(sender, e);
119 | e.Handled = true;
120 | e.SuppressKeyPress = true;
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/CUFormEx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace ModdingTools.Updater
9 | {
10 | public class CUFormEx : Form
11 | {
12 | [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
13 | private static extern IntPtr CreateRoundRectRgn
14 | (
15 | int nLeftRect, // x-coordinate of upper-left corner
16 | int nTopRect, // y-coordinate of upper-left corner
17 | int nRightRect, // x-coordinate of lower-right corner
18 | int nBottomRect, // y-coordinate of lower-right corner
19 | int nWidthEllipse, // height of ellipse
20 | int nHeightEllipse // width of ellipse
21 | );
22 |
23 | [DllImport("dwmapi.dll")]
24 | public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
25 |
26 | [DllImport("dwmapi.dll")]
27 | public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
28 |
29 | [DllImport("dwmapi.dll")]
30 | public static extern int DwmIsCompositionEnabled(ref int pfEnabled);
31 |
32 | private bool m_aeroEnabled; // variables for box shadow
33 | private const int CS_DROPSHADOW = 0x00020000;
34 | private const int WM_NCPAINT = 0x0085;
35 | private const int WM_ACTIVATEAPP = 0x001C;
36 |
37 | public struct MARGINS // struct for box shadow
38 | {
39 | public int leftWidth;
40 | public int rightWidth;
41 | public int topHeight;
42 | public int bottomHeight;
43 | }
44 |
45 | private const int WM_NCHITTEST = 0x84; // variables for dragging the form
46 | private const int HTCLIENT = 0x1;
47 | private const int HTCAPTION = 0x2;
48 |
49 | protected override void WndProc(ref Message m)
50 | {
51 | switch (m.Msg)
52 | {
53 | case WM_NCPAINT: // box shadow
54 | if (m_aeroEnabled)
55 | {
56 | var v = 2;
57 | DwmSetWindowAttribute(this.Handle, 2, ref v, 4);
58 | MARGINS margins = new MARGINS()
59 | {
60 | bottomHeight = 1,
61 | leftWidth = 1,
62 | rightWidth = 1,
63 | topHeight = 1
64 | };
65 | DwmExtendFrameIntoClientArea(this.Handle, ref margins);
66 |
67 | }
68 | break;
69 | default:
70 | break;
71 | }
72 | base.WndProc(ref m);
73 |
74 | if (m.Msg == WM_NCHITTEST && (int)m.Result == HTCLIENT) // drag the form
75 | m.Result = (IntPtr)HTCAPTION;
76 |
77 | }
78 |
79 | public CUFormEx()
80 | {
81 | this.MouseDown += HandleDrag;
82 | }
83 |
84 | protected override CreateParams CreateParams
85 | {
86 | get
87 | {
88 | m_aeroEnabled = CheckAeroEnabled();
89 |
90 | CreateParams cp = base.CreateParams;
91 | if (!m_aeroEnabled)
92 | cp.ClassStyle |= CS_DROPSHADOW;
93 |
94 | return cp;
95 | }
96 | }
97 |
98 | private bool CheckAeroEnabled()
99 | {
100 | if (Environment.OSVersion.Version.Major >= 6)
101 | {
102 | int enabled = 0;
103 | DwmIsCompositionEnabled(ref enabled);
104 | return (enabled == 1) ? true : false;
105 | }
106 | return false;
107 | }
108 |
109 | [DllImport("user32.dll")]
110 | public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
111 | [DllImport("user32.dll")]
112 | public static extern bool ReleaseCapture();
113 | protected void HandleDrag(object sender, MouseEventArgs e)
114 | {
115 | bool flag = e.Button == MouseButtons.Left;
116 | if (flag)
117 | {
118 | ReleaseCapture();
119 | SendMessage(base.Handle, 161, 2, 0);
120 | }
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/APNG/CrcHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace LibAPNG
5 | {
6 | internal class CrcHelper
7 | {
8 | #region Consts
9 |
10 | private static readonly UInt32[] CrcTable =
11 | {
12 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
13 | 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
14 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
15 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
16 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
17 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
18 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
19 | 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
20 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
21 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
22 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
23 | 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
24 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
25 | 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
26 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
27 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
28 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
29 | 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
30 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
31 | 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
32 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
33 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
34 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
35 | 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
36 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
37 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
38 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
39 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
40 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
41 | 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
42 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
43 | 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
44 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
45 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
46 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
47 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
48 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
49 | 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
50 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
51 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
52 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
53 | 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
54 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
55 | 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
56 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
57 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
58 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
59 | 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
60 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
61 | 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
62 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
63 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
64 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
65 | 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
66 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
67 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
68 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
69 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
70 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
71 | 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
72 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
73 | 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
74 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
75 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
76 | };
77 |
78 | #endregion Consts
79 |
80 | public static uint Calculate(byte[] what)
81 | {
82 | UInt32 crc = what.Aggregate(
83 | 0xffffffff,
84 | (current, t) => (current >> 8) ^ CrcTable[(current & 0xff) ^ t]);
85 | crc ^= 0xffffffff;
86 |
87 | return crc;
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/ModdingTools.Updater/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Windows.Forms;
9 |
10 | namespace ModdingTools.Updater
11 | {
12 | internal static class Program
13 | {
14 | ///
15 | /// The main entry point for the application.
16 | ///
17 | [STAThread]
18 | static void Main()
19 | {
20 | var args = Environment.GetCommandLineArgs();
21 | if (Process.GetCurrentProcess().ProcessName.Equals("ModdingTools.Updater", StringComparison.InvariantCultureIgnoreCase))
22 | {
23 | AttachBugTracker();
24 |
25 | // Enable TLS 1.2 & 1.1 because .Net Framework 4.0 doesn't have it enabled by default
26 | System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)(768 | 3072);
27 |
28 | Application.EnableVisualStyles();
29 | Application.SetCompatibleTextRenderingDefault(false);
30 | Application.Run(new MainWindow());
31 | }
32 | else
33 | {
34 | Process.Start(Path.Combine(GetAppRoot(), "ModdingTools.exe"));
35 | Environment.Exit(0);
36 | }
37 | }
38 |
39 | public static string GetAppRoot()
40 | {
41 | return Path.GetDirectoryName(Application.ExecutablePath);
42 | }
43 |
44 | private static void AttachBugTracker()
45 | {
46 | if (!Debugger.IsAttached)
47 | {
48 | // Add the event handler for handling UI thread exceptions to the event.
49 | Application.ThreadException += (sender, e)
50 | => FatalExceptionObject(e);
51 |
52 | // Set the unhandled exception mode to force all Windows Forms errors to go through our handler.
53 | Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
54 |
55 | // Add the event handler for handling non-UI thread exceptions to the event.
56 | AppDomain.CurrentDomain.UnhandledException += (sender, e)
57 | => FatalExceptionObject(e.ExceptionObject);
58 |
59 | // This AppDomain-wide event provides a mechanism to prevent exception escalation policy (which, by default, terminates the process) from triggering.
60 | // Each handler is passed a UnobservedTaskExceptionEventArgs instance, which may be used to examine the exception and to mark it as observed.
61 | TaskScheduler.UnobservedTaskException += (sender, e)
62 | => FatalExceptionObject(e);
63 | }
64 | }
65 |
66 | static bool isReported = false;
67 | static int threads;
68 | public static void FatalExceptionObject(object exc)
69 | {
70 | if (!Debugger.IsAttached)
71 | {
72 | if (isReported)
73 | {
74 | CloseApp(1);
75 | }
76 |
77 | var e = exc as Exception;
78 | if (e == null)
79 | {
80 | e = new NotSupportedException(
81 | "Unhandled exception doesn't derive from System.Exception: "
82 | + exc.ToString()
83 | );
84 | }
85 |
86 | threads = Process.GetCurrentProcess().Threads.Count;
87 |
88 | var x = new StringBuilder();
89 | x.AppendLine("Failed to launch OMM Updater: ");
90 | x.AppendLine(e.Message);
91 | x.AppendLine(e.StackTrace);
92 | if (e.InnerException != null)
93 | {
94 | x.AppendLine("---[inner exception]---");
95 | x.AppendLine(e.InnerException.Message);
96 | x.AppendLine(e.InnerException.StackTrace);
97 | }
98 | x.AppendLine("");
99 | x.AppendLine("Threads: " + threads);
100 |
101 | MessageBox.Show(x.ToString());
102 | isReported = true;
103 | CloseApp(1);
104 | }
105 | }
106 |
107 | public static void CloseApp(int i)
108 | {
109 | Debug.WriteLine("Closing application...");
110 | if (!Debugger.IsAttached)
111 | {
112 | Application.Exit();
113 | }
114 | else
115 | {
116 | Environment.Exit(i);
117 | }
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/ModdingTools/Windows/ArgEditor.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ModdingTools.Windows
2 | {
3 | partial class ArgEditor
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ArgEditor));
32 | this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
33 | this.label3 = new System.Windows.Forms.Label();
34 | this.SuspendLayout();
35 | //
36 | // flowLayoutPanel1
37 | //
38 | this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
39 | | System.Windows.Forms.AnchorStyles.Left)
40 | | System.Windows.Forms.AnchorStyles.Right)));
41 | this.flowLayoutPanel1.AutoScroll = true;
42 | this.flowLayoutPanel1.Location = new System.Drawing.Point(2, 89);
43 | this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
44 | this.flowLayoutPanel1.Name = "flowLayoutPanel1";
45 | this.flowLayoutPanel1.Size = new System.Drawing.Size(910, 416);
46 | this.flowLayoutPanel1.TabIndex = 1;
47 | this.flowLayoutPanel1.SizeChanged += new System.EventHandler(this.flowLayoutPanel1_SizeChanged);
48 | //
49 | // label3
50 | //
51 | this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
52 | | System.Windows.Forms.AnchorStyles.Right)));
53 | this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
54 | this.label3.ForeColor = System.Drawing.Color.Yellow;
55 | this.label3.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
56 | this.label3.Location = new System.Drawing.Point(6, 36);
57 | this.label3.Name = "label3";
58 | this.label3.Size = new System.Drawing.Size(902, 43);
59 | this.label3.TabIndex = 27;
60 | this.label3.Text = "Only use if you know what you are doing!\r\nModifying these options may mess some t" +
61 | "hings up, but you can restore the default settings at any time!";
62 | this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
63 | //
64 | // ArgEditor
65 | //
66 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
67 | this.ClientSize = new System.Drawing.Size(915, 507);
68 | this.Controls.Add(this.label3);
69 | this.Controls.Add(this.flowLayoutPanel1);
70 | this.DoubleBuffered = true;
71 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
72 | this.IsMaximizeButtonEnabled = false;
73 | this.IsMinimizeButtonEnabled = false;
74 | this.Location = new System.Drawing.Point(0, 0);
75 | this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
76 | this.MaximizeBox = false;
77 | this.MaximumSize = new System.Drawing.Size(1920, 1029);
78 | this.MinimizeBox = false;
79 | this.MinimumSize = new System.Drawing.Size(915, 507);
80 | this.Name = "ArgEditor";
81 | this.Text = "ARGUMENT EDITOR";
82 | this.SizeChanged += new System.EventHandler(this.ArgEditor_SizeChanged);
83 | this.Controls.SetChildIndex(this.flowLayoutPanel1, 0);
84 | this.Controls.SetChildIndex(this.label3, 0);
85 | this.ResumeLayout(false);
86 |
87 | }
88 |
89 | #endregion
90 |
91 | private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
92 | private System.Windows.Forms.Label label3;
93 | }
94 | }
--------------------------------------------------------------------------------
/ModdingTools/GUI/GUIWorker.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ModdingTools.GUI
2 | {
3 | partial class GUIWorker
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.label4 = new System.Windows.Forms.Label();
32 | this.cuGradientTextBox1 = new CUFramework.Controls.CUGradientTextBox();
33 | this.huehProgressBar1 = new ModdingTools.GUI.HuehProgressBar();
34 | this.SuspendLayout();
35 | //
36 | // label4
37 | //
38 | this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
39 | | System.Windows.Forms.AnchorStyles.Right)));
40 | this.label4.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(16)))), ((int)(((byte)(16)))), ((int)(((byte)(16)))));
41 | this.label4.Cursor = System.Windows.Forms.Cursors.Arrow;
42 | this.label4.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
43 | this.label4.ForeColor = System.Drawing.Color.White;
44 | this.label4.Location = new System.Drawing.Point(0, 376);
45 | this.label4.Name = "label4";
46 | this.label4.Padding = new System.Windows.Forms.Padding(5);
47 | this.label4.Size = new System.Drawing.Size(660, 31);
48 | this.label4.TabIndex = 9;
49 | this.label4.Text = "Please wait...";
50 | this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
51 | //
52 | // cuGradientTextBox1
53 | //
54 | this.cuGradientTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
55 | | System.Windows.Forms.AnchorStyles.Left)
56 | | System.Windows.Forms.AnchorStyles.Right)));
57 | this.cuGradientTextBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(42)))), ((int)(((byte)(42)))), ((int)(((byte)(42)))));
58 | this.cuGradientTextBox1.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
59 | this.cuGradientTextBox1.Location = new System.Drawing.Point(3, -2);
60 | this.cuGradientTextBox1.Name = "cuGradientTextBox1";
61 | this.cuGradientTextBox1.Size = new System.Drawing.Size(402, 375);
62 | this.cuGradientTextBox1.TabIndex = 10;
63 | this.cuGradientTextBox1.Text = "cuGradientTextBox1";
64 | this.cuGradientTextBox1.TextAlign = CUFramework.Controls.CUGradientTextBox.ETextAlign.Left;
65 | //
66 | // huehProgressBar1
67 | //
68 | this.huehProgressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
69 | | System.Windows.Forms.AnchorStyles.Right)));
70 | this.huehProgressBar1.ForeColor = System.Drawing.Color.White;
71 | this.huehProgressBar1.Location = new System.Drawing.Point(412, 32);
72 | this.huehProgressBar1.Name = "huehProgressBar1";
73 | this.huehProgressBar1.Size = new System.Drawing.Size(246, 365);
74 | this.huehProgressBar1.TabIndex = 11;
75 | this.huehProgressBar1.Value = 0;
76 | //
77 | // GUIWorker
78 | //
79 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
80 | this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(42)))), ((int)(((byte)(42)))), ((int)(((byte)(42)))));
81 | this.Controls.Add(this.label4);
82 | this.Controls.Add(this.huehProgressBar1);
83 | this.Controls.Add(this.cuGradientTextBox1);
84 | this.Name = "GUIWorker";
85 | this.Size = new System.Drawing.Size(660, 407);
86 | this.ResumeLayout(false);
87 |
88 | }
89 |
90 | #endregion
91 | private System.Windows.Forms.Label label4;
92 | private CUFramework.Controls.CUGradientTextBox cuGradientTextBox1;
93 | private HuehProgressBar huehProgressBar1;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/MainWindow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Net;
6 | using System.Threading.Tasks;
7 | using System.Windows.Forms;
8 |
9 | namespace ModdingTools.Updater
10 | {
11 | public partial class MainWindow : CUFormEx
12 | {
13 | private int CurrentProgress = -1;
14 | private string CurrentStatus;
15 | private bool DownloadCompleted;
16 | private bool IsCancelling = false;
17 | private bool IsLocked = false;
18 |
19 | public MainWindow()
20 | {
21 | InitializeComponent();
22 | this.StartPosition = FormStartPosition.CenterScreen;
23 | this.Shown += MainWindow_Shown;
24 | label2.MouseDown += HandleDrag;
25 | timer1.Tick += Timer1_Tick;
26 | }
27 |
28 | private void Timer1_Tick(object sender, EventArgs e)
29 | {
30 | label2.Text = CurrentStatus;
31 | button1.Enabled = !IsLocked;
32 | if (CurrentProgress >= 0)
33 | {
34 | progressBar1.Value = CurrentProgress;
35 | progressBar1.Style = ProgressBarStyle.Blocks;
36 | }
37 | else progressBar1.Style = ProgressBarStyle.Marquee;
38 | }
39 |
40 | private void MainWindow_Shown(object sender, EventArgs e)
41 | {
42 | Task.Factory.StartNew(() =>
43 | {
44 | if (!Debugger.IsAttached)
45 | {
46 | try
47 | {
48 | RunUpdaterTasks();
49 | }
50 | catch (Exception ex)
51 | {
52 | Program.FatalExceptionObject(ex);
53 | }
54 | }
55 | else
56 | {
57 | RunUpdaterTasks();
58 | }
59 | });
60 | }
61 |
62 | public void RunUpdaterTasks()
63 | {
64 | CurrentStatus = "Killing OMM instances...";
65 | OMMHelper.KillOMM();
66 |
67 | CurrentStatus = "Downloading update data...";
68 | var data = OMMHelper.GetUpdateData();
69 |
70 | if (IsCancelling)
71 | {
72 | Program.CloseApp(-1);
73 | return;
74 | }
75 |
76 | var appRoot = Program.GetAppRoot();
77 | var updateZipPath = Path.Combine(appRoot, "update.zip");
78 |
79 | CurrentStatus = "Downloading update package...";
80 | using(var wc = new WebClient())
81 | {
82 | wc.Headers.Add("User-agent", "OpenModManager.Updater/1.0");
83 | if (File.Exists(updateZipPath)) File.Delete(updateZipPath);
84 | wc.DownloadProgressChanged += Wc_DownloadProgressChanged;
85 | DownloadCompleted = false;
86 | wc.DownloadFileAsync(new Uri(data.URL), updateZipPath);
87 | wc.DownloadFileCompleted += Wc_DownloadFileCompleted;
88 |
89 | while (!DownloadCompleted)
90 | {
91 | if (IsCancelling)
92 | wc.CancelAsync();
93 |
94 | }
95 |
96 | if (IsCancelling)
97 | {
98 | if (File.Exists(updateZipPath))
99 | File.Delete(updateZipPath);
100 | Program.CloseApp(-1);
101 | return;
102 | }
103 |
104 | CurrentProgress = -1;
105 | IsLocked = true;
106 | CurrentStatus = "Verifying downloaded package...";
107 | if (data.Verify(updateZipPath))
108 | {
109 | CurrentStatus = "Extracting downloaded package...";
110 | OMMHelper.ExtractZIP(updateZipPath, appRoot);
111 | CurrentStatus = "OK!";
112 | CurrentProgress = 100;
113 | File.Delete(updateZipPath);
114 | System.Diagnostics.Process.Start(Path.Combine(appRoot, "ModdingTools.exe"));
115 | Program.CloseApp(0);
116 | }
117 | else
118 | {
119 | throw new Exception("Checksum verify failed!");
120 | }
121 | }
122 | }
123 |
124 | private void Wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
125 | {
126 | DownloadCompleted = true;
127 | }
128 |
129 | private void Wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
130 | {
131 | CurrentProgress = e.ProgressPercentage;
132 | CurrentStatus = $"Downloading update package... [{e.BytesReceived}/{e.TotalBytesToReceive}]";
133 | }
134 |
135 | private void button1_Click(object sender, EventArgs e)
136 | {
137 | if (!IsLocked)
138 | IsCancelling = true;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/ModdingTools.Updater/OMMHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.IO.Packaging;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Security.Cryptography;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Windows.Forms;
12 |
13 | namespace ModdingTools.Updater
14 | {
15 | public class OMMHelper
16 | {
17 | public struct DownloadData
18 | {
19 | public string URL;
20 | public string SHA256;
21 |
22 | public bool IsValid()
23 | {
24 | return !string.IsNullOrWhiteSpace(URL)
25 | && URL.StartsWith("https://")
26 | && !string.IsNullOrWhiteSpace(SHA256)
27 | && SHA256.Length == 64;
28 | }
29 |
30 | public bool Verify(string filePath)
31 | {
32 | using (var sha = System.Security.Cryptography.SHA256.Create())
33 | {
34 | using (FileStream fileStream = File.OpenRead(filePath))
35 | {
36 | var hash = BitConverter.ToString(sha.ComputeHash(fileStream)).Replace("-", string.Empty);
37 | return hash.Equals(SHA256, StringComparison.InvariantCultureIgnoreCase);
38 | }
39 | }
40 | }
41 |
42 | public override string ToString()
43 | {
44 | return $"URL: {URL}\nSHA256: {SHA256}\nIsValid: {IsValid()}";
45 | }
46 | }
47 |
48 | public static DownloadData GetUpdateData()
49 | {
50 | // Well, I should parse this json file by using Newtonsoft.JSON...
51 | // ...but I don't want to add any extra dependencies just for that one file lol
52 | var baseUrl = "https://api.github.com/repos/mcu8/OpenModManager/releases/latest";
53 | string jsonData;
54 | using(var wc = new WebClient())
55 | {
56 | wc.Headers.Add("User-agent", "OpenModManager.Updater/1.0");
57 | jsonData = wc.DownloadString(baseUrl);
58 | }
59 |
60 | // get "browser_download_url" tag... the harder way :p
61 | if (string.IsNullOrEmpty(jsonData))
62 | throw new Exception("Unable to find download URL... [1]");
63 |
64 | var data = new DownloadData();
65 |
66 | var x = jsonData.Split(new string[] { "\"browser_download_url\":\"" }, StringSplitOptions.None);
67 | if (x.Length > 1)
68 | {
69 | foreach (var e in x)
70 | {
71 | var result = e.Split('"')[0];
72 | if (result.StartsWith("https://") && result.EndsWith("-bin.zip"))
73 | data.URL = result;
74 | else if (result.StartsWith("https://") && result.EndsWith("-bin.zip.sha256"))
75 | {
76 | using (var wc = new WebClient())
77 | {
78 | wc.Headers.Add("User-agent", "OpenModManager.Updater/1.0");
79 | data.SHA256 = wc.DownloadString(result).Split(' ')[0];
80 | }
81 | }
82 |
83 | if (data.IsValid()) return data;
84 | }
85 | }
86 | else
87 | {
88 | throw new Exception("Unable to find download URL... [3]");
89 | }
90 |
91 | // well, probably an error
92 | throw new Exception("Unable to find download URL... [2]");
93 | }
94 |
95 | public static void KillOMM()
96 | {
97 | KillProcessByImageName("ModdingTools", false);
98 | KillProcessByImageName("ModdingTools.Cli", false);
99 | }
100 |
101 | public static void KillProcessByImageName(string name, bool async)
102 | {
103 | if (async)
104 | {
105 | Task.Factory.StartNew(() =>
106 | {
107 | foreach (var x in Process.GetProcessesByName(name))
108 | x.Kill();
109 | });
110 | }
111 | else
112 | {
113 | foreach (var x in Process.GetProcessesByName(name))
114 | x.Kill();
115 | }
116 | }
117 |
118 | public static void ExtractZIP(string zipFilePath, string targetFolderPath)
119 | {
120 | var zip = GetShell32Folder(zipFilePath).Items();
121 | GetShell32Folder(targetFolderPath).CopyHere(zip, 16 | 4 | 8);
122 | }
123 |
124 | private static Shell32.Folder GetShell32Folder(string folderPath)
125 | {
126 | Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
127 | Object shell = Activator.CreateInstance(shellAppType);
128 | return (Shell32.Folder)shellAppType.InvokeMember("NameSpace",
129 | System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { folderPath });
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/ModdingTools/Engine/GameFinder.cs:
--------------------------------------------------------------------------------
1 |
2 | //#define STEAM_NO_REGISTRY_TEST
3 |
4 | using Microsoft.Win32;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Text;
10 |
11 | namespace ModdingTools.Engine
12 | {
13 |
14 | public class GameFinder
15 | {
16 | public const string AppID = "253230";
17 |
18 | #if STEAM_NO_REGISTRY_TEST
19 | public static string GetSteamDir()
20 | {
21 | return null;
22 | }
23 | #else
24 | public static string GetSteamDir()
25 | {
26 | try
27 | {
28 | var key = @"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam";
29 | if (Environment.Is64BitOperatingSystem)
30 | {
31 | key = @"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Valve\Steam";
32 | }
33 | return (string)Registry.GetValue(key, "InstallPath", null);
34 | }
35 | catch
36 | {
37 | // if it somehow fails... we don't care lol
38 | return null;
39 | }
40 | }
41 | #endif
42 |
43 | public static string GetWorkshopDir()
44 | {
45 | var steamDir = GetSteamDir();
46 | if (steamDir == null || !Directory.Exists(steamDir))
47 | {
48 | // fallback to more cheap dir detection... probably using Proton or bad Steam install?
49 |
50 | // the funny
51 | var baseDir = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(FindGameDir()))));
52 | return Path.Combine(baseDir, @"workshop\content", AppID);
53 | }
54 | return Path.Combine(steamDir, @"steamapps\workshop\content", AppID);
55 | }
56 |
57 | public static string GetModsDir()
58 | {
59 | return Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(FindGameDir())), "HatInTimeGame", "Mods");
60 | }
61 |
62 | public static string GetSrcDir()
63 | {
64 | return Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(FindGameDir())), "Development", "Src");
65 | }
66 |
67 | public static string GetCookedPcDir()
68 | {
69 | return Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(FindGameDir())), "HatInTimeGame", "CookedPC");
70 | }
71 |
72 | public static string GetEditorCookedPcDir()
73 | {
74 | return Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(FindGameDir())), "HatInTimeGame", "EditorCookedPC");
75 | }
76 |
77 | // Cache that, cuz we changing the working dir - must be absolute!
78 | private static string CachedGameDir = null;
79 | public static string FindGameDir()
80 | {
81 | if (CachedGameDir != null)
82 | return CachedGameDir;
83 |
84 | if (File.Exists("GameDirPath.dat"))
85 | {
86 | try
87 | {
88 | var testPath = File.ReadAllText("GameDirPath.dat");
89 | var gamePath = Path.Combine(testPath, "HatinTimeGame.exe");
90 | var editorPath = Path.Combine(testPath, "HatinTimeEditor.exe");
91 |
92 | if (File.Exists(gamePath) && File.Exists(editorPath))
93 | {
94 | CachedGameDir = Path.GetFullPath(testPath);
95 | return testPath;
96 | }
97 | else
98 | {
99 | File.Delete("GameDirPath.dat");
100 | }
101 | }
102 | catch (Exception)
103 | {
104 | File.Delete("GameDirPath.dat");
105 | }
106 | }
107 |
108 | var strSteamInstallPath = GetSteamDir();
109 |
110 | if (strSteamInstallPath != null && Directory.Exists(strSteamInstallPath))
111 | {
112 | var libPathes = new List();
113 | libPathes.Add(strSteamInstallPath);
114 |
115 | var libFile = File.ReadAllLines(Path.Combine(strSteamInstallPath, "steamapps\\libraryfolders.vdf"));
116 | int i = 0;
117 | foreach (var line in libFile)
118 | {
119 | if (i >= 4)
120 | {
121 | var d = line.Trim().Split('"');
122 | if (d.Count() == 5)
123 | {
124 | libPathes.Add(d[3].Replace(@"\\", @"\"));
125 | }
126 | }
127 | i++;
128 | }
129 |
130 | foreach (var lib in libPathes)
131 | {
132 | var testPath = Path.Combine(lib, "steamapps\\common\\HatinTime\\Binaries\\Win64");
133 | var gamePath = Path.Combine(testPath, "HatinTimeGame.exe");
134 | var editorPath = Path.Combine(testPath, "HatinTimeEditor.exe");
135 |
136 | if (File.Exists(gamePath) && File.Exists(editorPath))
137 | {
138 | CachedGameDir = Path.GetFullPath(testPath);
139 | return testPath;
140 | }
141 | }
142 | }
143 | return null;
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/ConfigItem.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Dialogs.Validators;
2 | using ModdingTools.Modding;
3 | using ModdingTools.Windows;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Windows.Forms;
12 | using static ModdingTools.Modding.ModObject;
13 |
14 | namespace ModdingTools.GUI
15 | {
16 | public partial class ConfigItem : UserControl
17 | {
18 | ModObject.ModConfigItem Conf;
19 | ModObject Obj;
20 |
21 | public ConfigItem(ModObject.ModConfigItem item, ModObject ob)
22 | {
23 | InitializeComponent();
24 | Conf = item;
25 | Obj = ob;
26 |
27 | label4.Text = Conf.PropertyName;
28 | label3.Text = Conf.Description.Replace("[br]", Environment.NewLine);
29 | label5.Text = Conf.Name;
30 |
31 | RepopulateOptionsDict(true);
32 | }
33 |
34 | private void mButtonBorderless1_Click(object sender, EventArgs e)
35 | {
36 | CallUpdateEvent();
37 | if (this.Parent is FlowLayoutPanel)
38 | {
39 | this.Parent.Controls.Remove(this);
40 | }
41 | Obj.Config.Remove(Conf);
42 | }
43 |
44 | private void CallUpdateEvent()
45 | {
46 | if (this.Parent.Parent is ConfigList)
47 | ((ConfigList)this.Parent.Parent).CallOnUpdateEvent();
48 | }
49 |
50 | private void label4_Click(object sender, EventArgs e)
51 | {
52 | var a = CUInputWindow.Ask(this, "Config Editor", "Please, enter config property name (var config int )", new NonEmptyValidator(), label4.Text);
53 | if (a != null)
54 | {
55 | label4.Text = a;
56 | Conf.PropertyName = a;
57 | CallUpdateEvent();
58 | }
59 | }
60 |
61 | private void label3_Click(object sender, EventArgs e)
62 | {
63 | var a = CUInputWindow.Ask(this, "Config Editor", "Please, enter the description", new NonEmptyValidator(), label3.Text, true);
64 | if (a != null)
65 | {
66 | label3.Text = a;
67 | Conf.Description = a.Replace(Environment.NewLine, "[br]");
68 | CallUpdateEvent();
69 | }
70 | }
71 |
72 | private void ConfigItem_Load(object sender, EventArgs e)
73 | {
74 |
75 | }
76 |
77 | private void label5_Click(object sender, EventArgs e)
78 | {
79 | var a = CUInputWindow.Ask(this, "Config Editor", "Please, enter config display name", new NonEmptyValidator(), label5.Text);
80 | if (a != null)
81 | {
82 | label5.Text = a;
83 | Conf.Name = a;
84 | CallUpdateEvent();
85 | }
86 | }
87 |
88 | private void RepopulateOptionsDict(bool firstRun = false)
89 | {
90 | int i = 0;
91 | if (!firstRun)
92 | {
93 | Conf.Options.Clear();
94 | foreach (var _item in listBox1.Items)
95 | {
96 | var item = (ModConfigItem_Indexed)_item;
97 | Conf.Options.Add(i, item);
98 | i++;
99 | }
100 | }
101 | else
102 | {
103 | foreach (var conf in Conf.Options)
104 | {
105 | listBox1.Items.Add(conf.Value);
106 | }
107 | listBox1.Update();
108 | }
109 | }
110 |
111 | private void mButtonBorderless3_Click(object sender, EventArgs e)
112 | {
113 | var a = CUInputWindow.Ask(this, "Config Editor", "Please, enter a new value name", new NonEmptyValidator());
114 | if (a != null)
115 | {
116 | listBox1.Items.Add(new ModConfigItem_Indexed(FindLowestAvailableConfigId(), a));
117 | RepopulateOptionsDict();
118 | CallUpdateEvent();
119 | }
120 | }
121 |
122 | private int FindLowestAvailableConfigId()
123 | {
124 | int i = 0;
125 | while (true)
126 | {
127 | bool found = false;
128 | foreach (var _item in listBox1.Items)
129 | {
130 | var item = (ModConfigItem_Indexed)_item;
131 | if (item.Id == i)
132 | {
133 | found = true;
134 | break;
135 | }
136 | }
137 | if (found)
138 | {
139 | i++;
140 | continue;
141 | }
142 | return i;
143 | }
144 | }
145 |
146 | private void mButtonBorderless2_Click(object sender, EventArgs e)
147 | {
148 | listBox1.Items.Remove(listBox1.SelectedItem);
149 | RepopulateOptionsDict();
150 | CallUpdateEvent();
151 | }
152 |
153 | private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
154 | {
155 | /*if (Conf.DefaultIndex != comboBox1.SelectedIndex)
156 | CallUpdateEvent();
157 |
158 | Conf.DefaultIndex = comboBox1.SelectedIndex;*/
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/ModdingTools/GUI/ContentBrowser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using System.IO;
10 | using ModdingTools.Modding;
11 | using ModdingTools.Engine;
12 | using System.Diagnostics;
13 |
14 | namespace ModdingTools.GUI
15 | {
16 | public partial class ContentBrowser : UserControl
17 | {
18 | public bool HasContentError { get; private set; }
19 |
20 | Dictionary Adict = new Dictionary
21 | {
22 | { ".upk", "Only Asset Packages (.upk) are allowed in the Content folder." },
23 | { ".umap", "Only Unreal Maps (.umap) are allowed in the Maps folder." },
24 | { ".int", "Only Localization Files (.int) are allowed in the Localization folder." }
25 | };
26 |
27 | Dictionary BDict = new Dictionary
28 | {
29 | { ".upk", "This is an Asset Package (.upk) which goes in the Content folder." },
30 | { ".umap", "This is an Unreal Map (.umap) which goes in the Maps folder." },
31 | { ".int", "This is a Localization File (.int) which goes in the Localization folder." }
32 | };
33 |
34 | public ContentBrowser()
35 | {
36 | InitializeComponent();
37 | }
38 |
39 | private struct ContentTreeViewInfo
40 | {
41 | public string Filename;
42 |
43 | public string ErrorMessage;
44 |
45 | public ContentTreeViewInfo(string InFilename, string InErrorMessage)
46 | {
47 | Filename = InFilename;
48 | ErrorMessage = InErrorMessage;
49 | }
50 | }
51 |
52 | public void LoadMod(ModObject mod)
53 | {
54 | HasContentError = false;
55 | AssetNameLabel.Text = "(none selected)";
56 | AssetDescriptionLabel.Text = "";
57 |
58 | ContentTreeView.Nodes.Clear();
59 | IterateContent(ContentTreeView.Nodes, mod, mod.GetContentDir(), ".upk", true);
60 | IterateContent(ContentTreeView.Nodes, mod, mod.GetMapsDir(), ".umap", true);
61 | IterateContent(ContentTreeView.Nodes, mod, mod.GetLocsDir(), ".int", true);
62 | ContentTreeView.ExpandAll();
63 | }
64 |
65 | private void IterateContent(TreeNodeCollection root, ModObject mod, string currPath, string acceptExt, bool isBase = false)
66 | {
67 | if (!Directory.Exists(currPath))
68 | return;
69 |
70 | if (isBase)
71 | {
72 | var node = root.Add("folder", Path.GetFileName(currPath), "folder", "folder");
73 | IterateContent(node.Nodes, mod, currPath, acceptExt);
74 | return;
75 | }
76 | foreach (string path in Directory.GetFiles(currPath, "*.*"))
77 | {
78 | Debug.WriteLine(GameFinder.GetCookedPcDir());
79 | var exts = acceptExt.Split('|');
80 | var extension = Path.GetExtension(path);
81 | var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
82 | if (!exts.Contains(acceptExt))
83 | {
84 | var treeNode = root.Add("", Path.GetFileName(path), "error", "error");
85 | var text = "This asset does not belong here.";
86 | foreach (var a in Adict)
87 | {
88 | if (exts.Contains(a.Key)) text += Environment.NewLine + a.Value;
89 | }
90 |
91 | foreach (var b in BDict)
92 | {
93 | if (extension == b.Key) text += Environment.NewLine + b.Value;
94 | }
95 |
96 | treeNode.Tag = new ContentTreeViewInfo(Path.GetFileName(path), text);
97 | HasContentError = true;
98 | }
99 | else if (fileNameWithoutExtension.ToLower() == mod.GetDirectoryName().ToLower() && !exts.Contains(".int") && !exts.Contains(".umap"))
100 | {
101 | var treeNode = root.Add("", Path.GetFileName(path), "error", "error");
102 | treeNode.Tag = new ContentTreeViewInfo(Path.GetFileName(path), "Packages can't have the same name as your mod folder.\nAdd a _Content suffix or something. Example:\n" + fileNameWithoutExtension + "_Content" + extension);
103 | HasContentError = true;
104 | }
105 | else if (Utils.FileExists(GameFinder.GetCookedPcDir(), Path.GetFileName(path)))
106 | {
107 | var treeNode = root.Add("", Path.GetFileName(path), "error", "error");
108 | treeNode.Tag = new ContentTreeViewInfo(Path.GetFileName(path), "There's an asset with an identical name in CookedPC.\nPlease give your asset another name.\n(btw don't put your own stuff in CookedPC. Keep it to the mods folder.)");
109 | HasContentError = true;
110 | }
111 | else
112 | {
113 | var ext = exts.Contains(".int") ? "localization" : "package";
114 | var treeNode = root.Add("", Path.GetFileName(path), ext, ext);
115 | treeNode.Tag = new ContentTreeViewInfo(Path.GetFileName(path), "");
116 | }
117 | }
118 | foreach (var file in Directory.GetDirectories(currPath))
119 | {
120 | var node = root.Add("", Path.GetFileName(file), "folder", "folder");
121 | IterateContent(node.Nodes, mod, file, acceptExt);
122 | }
123 | }
124 |
125 | private void ContentTreeView_AfterSelect(object sender, TreeViewEventArgs e)
126 | {
127 | if (ContentTreeView.SelectedNode.Tag == null)
128 | {
129 | AssetNameLabel.Text = "(none selected)";
130 | return;
131 | }
132 | ContentTreeViewInfo contentTreeViewInfo = (ContentTreeViewInfo)ContentTreeView.SelectedNode.Tag;
133 | AssetNameLabel.Text = contentTreeViewInfo.Filename;
134 | AssetDescriptionLabel.Text = contentTreeViewInfo.ErrorMessage;
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/ModdingTools/Logging/Logger.cs:
--------------------------------------------------------------------------------
1 | using CUFramework.Shared;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Data;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Windows.Forms.VisualStyles;
8 |
9 | namespace ModdingTools.Logging
10 | {
11 | static class Logger
12 | {
13 | private static Dictionary HANDLER_REGISTRY { get; set; }
14 |
15 | private static bool IsInitialized = false;
16 | public static void InitializeLogger()
17 | {
18 | HANDLER_REGISTRY = new Dictionary();
19 |
20 | if (Debugger.IsAttached)
21 | RegisterOutputHandler("DebuggerLogger", new Logging.Handlers.DebuggerLogger());
22 |
23 | RegisterOutputHandler("CommandLineLogger", new Logging.Handlers.CommandLineLogger());
24 |
25 | IsInitialized = true;
26 | }
27 |
28 | public static void RegisterOutputHandler(string name, ILogger handler)
29 | {
30 | if (!HANDLER_REGISTRY.ContainsKey(name))
31 | {
32 | HANDLER_REGISTRY.Add(name, handler);
33 | HANDLER_REGISTRY[name].Init();
34 | }
35 | }
36 |
37 | public static void UnregisterOutputHandler(string name)
38 | {
39 | if (HANDLER_REGISTRY.ContainsKey(name))
40 | {
41 | HANDLER_REGISTRY[name].Unregister();
42 | HANDLER_REGISTRY.Remove(name);
43 | }
44 | }
45 |
46 | public static string GetLoggerDate()
47 | {
48 | System.DateTime regDate = System.DateTime.Now;
49 | return regDate.ToString("HH:mm:ss");
50 | }
51 |
52 | public static string GetLevelText(LogLevel level)
53 | {
54 | return level.ToString();
55 | }
56 |
57 | public static void Log(LogLevel Level, string Message, string Sender = "")
58 | {
59 | if (!IsInitialized) InitializeLogger();
60 | if ((Message != null))
61 | {
62 | if (Message.Contains("\n"))
63 | {
64 | foreach (string msg in Message.Split('\n'))
65 | {
66 | SendToHandlers(msg, Sender, Level);
67 | }
68 | }
69 | else
70 | {
71 | SendToHandlers(Message, Sender, Level);
72 | }
73 | }
74 | }
75 |
76 | public static void PrintBoxed(string text, ConsoleColor color)
77 | {
78 |
79 | Console.ResetColor();
80 | string[] lines = text.Split('\n');
81 |
82 | for (int i = 0; i != lines.Length; i++)
83 | {
84 | lines[i] = lines[i].Replace("\n", String.Empty);
85 | lines[i] = lines[i].Replace("\r", String.Empty);
86 | lines[i] = lines[i].Replace("\t", String.Empty);
87 | }
88 |
89 | int total = (lines.Length <= 1 ? text.Length : lines.Max(a => a.Length)) + 6;
90 |
91 | string x = "";
92 | string y = "";
93 | for (int i = 0; i != total; i++)
94 | {
95 | x += "█";
96 | }
97 | for (int i = 0; i != total - 2; i++)
98 | {
99 | y += " ";
100 | }
101 |
102 | for (int i = 0; i < lines.Length; i++)
103 | {
104 | while (lines[i].Length < total - 6)
105 | {
106 | lines[i] += " ";
107 | }
108 | }
109 |
110 | Console.WriteLine("");
111 | Console.WriteLine("");
112 | Console.Write(" ");
113 | Console.ForegroundColor = color;
114 | Console.Write(x);
115 | Console.WriteLine("");
116 | Console.ResetColor();
117 | Console.Write(" ");
118 | Console.ForegroundColor = color;
119 | Console.Write("█");
120 | Console.ResetColor();
121 | Console.Write(y);
122 | Console.ForegroundColor = color;
123 | Console.Write("█");
124 |
125 | foreach (var line in lines)
126 | {
127 | Console.WriteLine("");
128 | Console.ResetColor();
129 | Console.Write(" ");
130 | Console.ForegroundColor = color;
131 | Console.Write("█");
132 | Console.ResetColor();
133 | Console.Write(" " + line + " ");
134 | Console.ForegroundColor = color;
135 | Console.Write("█");
136 | Console.ResetColor();
137 | }
138 |
139 | Console.WriteLine("");
140 |
141 | Console.Write(" ");
142 | Console.ForegroundColor = color;
143 | Console.Write("█");
144 | Console.ResetColor();
145 | Console.Write(y);
146 | Console.ForegroundColor = color;
147 | Console.WriteLine("█");
148 | Console.ResetColor();
149 | Console.Write(" ");
150 | Console.ForegroundColor = color;
151 | Console.Write(x);
152 | Console.ResetColor();
153 | Console.WriteLine("");
154 | }
155 |
156 | private static void SendToHandlers(string text, string sender, LogLevel level)
157 | {
158 | foreach (var entity in new List(HANDLER_REGISTRY.Values))
159 | {
160 | if (level < entity.VerbosityLevel()) continue;
161 | entity.Append(text, sender, level);
162 | }
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/.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 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
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 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
262 |
263 | # Ignore ModManager executables
264 | ModManager.exe
265 | ModdingTools/ModManager.exe
266 | /ModdingTools/.vshistory
267 | /ModdingTools/GUI/.vshistory
268 | /ModdingTools/Modding/.vshistory/ModObject.cs
269 | /ModdingTools/Properties/.vshistory/Settings.settings
270 | /ModdingTools/UEngine/.vshistory
271 | /Release
272 | *.vshistory
--------------------------------------------------------------------------------