master
D4VID 7 months ago
parent 9787444372
commit 4978487e2e

4
.gitignore vendored

@ -4,4 +4,6 @@ obj/
riderModule.iml
/_ReSharper.Caches/
.idea/
LogicWorld/
LogicWorld
HarmonyForLogicWorld
EccsLogicWorldAPI

@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CriticalPathAnalyzer", "CriticalPathAnalyzer\CriticalPathAnalyzer.csproj", "{0328A941-5B63-44F5-B7BF-BF036CC9A5FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EccsLogicWorldAPI", "EccsLogicWorldAPI\EccsLogicWorldAPI.csproj", "{EDBF6818-E1D2-4A57-AC4B-647B69858817}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -12,5 +14,9 @@ Global
{0328A941-5B63-44F5-B7BF-BF036CC9A5FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0328A941-5B63-44F5-B7BF-BF036CC9A5FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0328A941-5B63-44F5-B7BF-BF036CC9A5FE}.Release|Any CPU.Build.0 = Release|Any CPU
{EDBF6818-E1D2-4A57-AC4B-647B69858817}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDBF6818-E1D2-4A57-AC4B-647B69858817}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDBF6818-E1D2-4A57-AC4B-647B69858817}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDBF6818-E1D2-4A57-AC4B-647B69858817}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

@ -8,6 +8,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="0Harmony">
<HintPath>..\HarmonyForLogicWorld\HarmonyForLogicWorld\assemblies\client\0Harmony.dll</HintPath>
</Reference>
<Reference Include="FancyInput">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\FancyInput.dll</HintPath>
</Reference>
@ -20,12 +23,45 @@
<Reference Include="LogicLog">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicLog.dll</HintPath>
</Reference>
<Reference Include="LogicLog">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicUI.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Building">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Building.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.BuildingManagement">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.BuildingManagement.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Building">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Players.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Building">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Physics.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.GameStates">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.GameStates.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Input">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Input.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Interfaces">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Interfaces.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Modding">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Modding.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.Outlines">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Outlines.dll</HintPath>
</Reference>
<Reference Include="LogicWorld.SharedCode">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\LogicWorld.SharedCode.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\LogicWorld\Logic_World_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EccsLogicWorldAPI\EccsLogicWorldAPI.csproj"/>
</ItemGroup>
</Project>

@ -1,3 +1,6 @@
CriticalPathAnalyzer.CriticalPathAnalyzer:
InjectTriggersInto:
- MHG.BuildActions
Triggers:
- CriticalPathAnalyzer.AnalyzeCriticalPath
- CriticalPathAnalyzer.AnalyzePathStart
- CriticalPathAnalyzer.AnalyzePathEnd

@ -1,4 +1,10 @@
CriticalPathAnalyzer.AnalyzeCriticalPath:
CriticalPathAnalyzer.AnalyzePathStart:
Heading: "CriticalPathAnalyzer"
DefaultBinding:
Options:
- I
CriticalPathAnalyzer.AnalyzePathEnd:
Heading: "CriticalPathAnalyzer"
DefaultBinding:
Options:

@ -1,6 +1,11 @@
MHG.SettingsMenu.Pages.Controls.Headings.CriticalPathAnalyzer: "Mod: Critical Path Analyzer"
FancyInput.Trigger.CriticalPathAnalyzer.AnalyzeCriticalPath: "Analyze Critical Path"
FancyInput.Trigger.CriticalPathAnalyzer.AnalyzeCriticalPath.Description : """
Press once to select the start of the path and a second time to select the end.
FancyInput.Trigger.CriticalPathAnalyzer.AnalyzePathStart: "Select start of path"
FancyInput.Trigger.CriticalPathAnalyzer.AnalyzePathStart.Description : """
Press to select the start of the path to be analyzed.
"""
FancyInput.Trigger.CriticalPathAnalyzer.AnalyzePathEnd: "Select end of path"
FancyInput.Trigger.CriticalPathAnalyzer.AnalyzePathEnd.Description : """
Press to select the end of the path to be analyzed.
"""

@ -1,16 +1,27 @@

using CriticalPathAnalyzer.Client.Keybindings;
using EccsLogicWorldAPI.Client.Injectors;
using FancyInput;
using LogicAPI.Client;
using LogicLog;
namespace CriticalPathAnalyzer.Client {
public class CriticalPathAnalyzerClient : ClientMod {
public static ILogicLogger LoggerInstance;
protected override void Initialize() {
LoggerInstance = Logger;
Logger.Info("CriticalPathAnalyzer mod loading");
// Register keybindings in the settings menu
CustomInput.Register<CriticalPathAnalyzerContext, CriticalPathAnalyzerTrigger>("CriticalPathAnalyzer");
// Inject our own game state
GameStateInjector.inject(CriticalPathAnalyzerGameState.Id, typeof(CriticalPathAnalyzerGameState));
// Inject a hook into the game code to check for our keybindings
KeybindingsInjector.Inject();
Logger.Info("CriticalPathAnalyzer mod loaded");
}
}

@ -0,0 +1,39 @@
using System.Collections.Generic;
using CriticalPathAnalyzer.Client.Keybindings;
using CriticalPathAnalyzer.Client.tool;
using FancyInput;
using LogicUI;
using LogicWorld.GameStates;
namespace CriticalPathAnalyzer.Client {
public class CriticalPathAnalyzerGameState : GameState {
public const string Id = "CriticalPathAnalyzer.Analyzing";
public override bool MouseLocked => true;
public override string TextID => Id;
public override IEnumerable<InputTrigger> HelpScreenTriggers => new InputTrigger[] {
UITrigger.Back,
CriticalPathAnalyzerTrigger.AnalyzePathStart,
CriticalPathAnalyzerTrigger.AnalyzePathEnd,
};
public override void OnEnter() {
CriticalPathAnalyzerClient.LoggerInstance.Info("CPA enter");
}
public override void OnRun() {
if (CustomInput.DownThisFrame(UITrigger.Back)) {
GameStateManager.TransitionBackToBuildingState();
} else if (CustomInput.DownThisFrame(CriticalPathAnalyzerTrigger.AnalyzePathStart)) {
CriticalPathAnalyzerTool.SelectPathStart();
} else if (CustomInput.DownThisFrame(CriticalPathAnalyzerTrigger.AnalyzePathEnd)) {
CriticalPathAnalyzerTool.SelectPathEnd();
}
}
public override void OnExit() {
CriticalPathAnalyzerClient.LoggerInstance.Info("CPA exit");
}
}
}

@ -0,0 +1,31 @@
using CriticalPathAnalyzer.Client.Keybindings;
using EccsLogicWorldAPI.Shared.AccessHelper;
using FancyInput;
using HarmonyLib;
using LogicWorld.Building;
using LogicWorld.GameStates;
namespace CriticalPathAnalyzer.Client {
public class KeybindingsInjector {
// Fairly generic hook into adding custom keybindings to the main building game state of LW.
// Allows to add keybindings to open new GUI elements or add new core building actions (which are not build-operations).
public static void Inject() {
var methodTarget = Methods.getPrivateStatic(typeof(StuffDeleter), "RunFirstPersonWireDeleting");
var methodHook = Methods.getPrivateStatic(typeof(KeybindingsInjector), nameof(Hook));
var harmony = new Harmony(nameof(CriticalPathAnalyzer));
harmony.Patch(methodTarget, prefix: new HarmonyMethod(methodHook));
}
private static bool Hook(out bool deletedWire) {
if (CustomInput.DownThisFrame(CriticalPathAnalyzerTrigger.AnalyzePathStart)) {
GameStateManager.TransitionTo(CriticalPathAnalyzerGameState.Id);
deletedWire = true; // True = Cancel remaining keybinding handling.
return false; // Prevent execution of the original/further functionality.
}
deletedWire = false; // Default, might be overwritten. False = Do not cancel remaining keybinding handling.
return true; // Allow original/further functionality.
}
}
}

@ -1,6 +1,7 @@
namespace CriticalPathAnalyzer.Client.Keybindings {
public enum CriticalPathAnalyzerTrigger {
None,
AnalyzeCriticalPath
AnalyzePathStart,
AnalyzePathEnd,
}
}

@ -0,0 +1,51 @@
using LogicAPI.Data;
using LogicWorld.Interfaces;
using LogicWorld.Physics;
using LogicWorld.Players;
namespace CriticalPathAnalyzer.Client.tool {
public class CriticalPathAnalyzerTool {
private static PegAddress _startPegAddress;
private static PegAddress _endPegAddress;
private static PegAddress? RayCastPeg() {
// Ray-cast into the world to find what the player is looking at
HitInfo hitInfo = PlayerCaster.CameraCast(Masks.Environment | Masks.Structure | Masks.Peg | Masks.Wire);
if (!hitInfo.HitSomething) {
return null;
}
// Resolve hit target:
if (hitInfo.HitPeg) {
CriticalPathAnalyzerClient.LoggerInstance.Info("Hit peg");
return _startPegAddress = hitInfo.pAddress;
}
if (hitInfo.HitWire) {
CriticalPathAnalyzerClient.LoggerInstance.Info("Hit wire");
WireAddress wireAddress = hitInfo.wAddress;
Wire wire = Instances.MainWorld.Data.Lookup(wireAddress);
// Assume that wire is never null, as we did just ray-casted it.
return wire.Point1.IsInputAddress() ? wire.Point1 : wire.Point2;
}
return null;
}
public static void SelectPathStart() {
CriticalPathAnalyzerClient.LoggerInstance.Info("Analyze Path Start");
PegAddress? pegAddress = RayCastPeg();
if (pegAddress != null) {
_startPegAddress = pegAddress.Value;
}
}
public static void SelectPathEnd() {
CriticalPathAnalyzerClient.LoggerInstance.Info("Analyze Path End");
PegAddress? pegAddress = RayCastPeg();
if (pegAddress != null) {
_endPegAddress = pegAddress.Value;
}
}
}
}
Loading…
Cancel
Save