Skip to content

Commit

Permalink
change: シナリオの読込検知処理を整理、イベントからScenarioInfoを取得可能に
Browse files Browse the repository at this point in the history
  • Loading branch information
automatic9045 committed Oct 18, 2023
1 parent 5e52a79 commit e1f2507
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 61 deletions.
1 change: 1 addition & 0 deletions AtsEx.PluginHost/AtsEx.PluginHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
<Compile Include="Binding\BindingMode.cs" />
<Compile Include="Binding\IBinding.cs" />
<Compile Include="DictionaryExtensions.cs" />
<Compile Include="EventArgs\ScenarioOpenedEventArgs.cs" />
<Compile Include="Exceptions\ConflictException.cs" />
<Compile Include="Exceptions\MemberNotInitializedException.cs" />
<Compile Include="ITwoWayConverter.cs" />
Expand Down
19 changes: 16 additions & 3 deletions AtsEx.PluginHost/BveHacker/IBveHacker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@

namespace AtsEx.PluginHost
{
/// <summary>
/// <see cref="IBveHacker.ScenarioOpened"/> イベントを処理するメソッドを表します。
/// </summary>
/// <param name="e">イベント データを格納している <see cref="ScenarioOpenedEventArgs"/>。</param>
public delegate void ScenarioOpenedEventHandler(ScenarioOpenedEventArgs e);

/// <summary>
/// <see cref="IBveHacker.ScenarioClosed"/> イベントを処理するメソッドを表します。
/// </summary>
/// <param name="e">イベント データを格納している <see cref="EventArgs"/>。</param>
public delegate void ScenarioClosedEventHandler(EventArgs e);

/// <summary>
/// <see cref="IBveHacker.ScenarioCreated"/> または <see cref="IBveHacker.PreviewScenarioCreated"/> イベントを処理するメソッドを表します。
/// </summary>
Expand Down Expand Up @@ -139,17 +151,18 @@ public interface IBveHacker : IDisposable
/// シナリオが選択され、読込を開始したときに発生します。
/// </summary>
/// <remarks>
/// このイベントは入力デバイスプラグイン版でのみ発生します。ATS プラグイン版では発生しません。
/// このイベントは入力デバイスプラグイン版でのみ発生します。ATS プラグイン版では発生しません。<br/>
/// 読み込まれたシナリオを表す <see cref="BveTypes.ClassWrappers.Scenario"/> を取得するには、<see cref="ScenarioCreated"/> または <see cref="PreviewScenarioCreated"/> イベントを使用してください。
/// </remarks>
event EventHandler ScenarioOpened;
event ScenarioOpenedEventHandler ScenarioOpened;

/// <summary>
/// シナリオが閉じられたときに発生します。
/// </summary>
/// <remarks>
/// このイベントは入力デバイスプラグイン版でのみ発生します。ATS プラグイン版では発生しません。
/// </remarks>
event EventHandler ScenarioClosed;
event ScenarioClosedEventHandler ScenarioClosed;


/// <summary>
Expand Down
30 changes: 30 additions & 0 deletions AtsEx.PluginHost/EventArgs/ScenarioOpenedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using BveTypes.ClassWrappers;

namespace AtsEx.PluginHost
{
/// <summary>
/// <see cref="IBveHacker.ScenarioOpened"/> イベントのデータを提供します。
/// </summary>
public class ScenarioOpenedEventArgs : EventArgs
{
/// <summary>
/// 読込が開始されたシナリオの情報を格納する <see cref="BveTypes.ClassWrappers.ScenarioInfo"/> を取得します。
/// </summary>
public ScenarioInfo ScenarioInfo { get; }

/// <summary>
/// <see cref="ScenarioOpenedEventArgs"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="scenarioInfo">読込が開始されたシナリオの情報を格納する <see cref="BveTypes.ClassWrappers.ScenarioInfo"/>。</param>
public ScenarioOpenedEventArgs(ScenarioInfo scenarioInfo)
{
ScenarioInfo = scenarioInfo;
}
}
}
48 changes: 9 additions & 39 deletions AtsEx/BveHacker/BveHacker.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
Expand All @@ -12,8 +9,6 @@

using BveTypes;
using BveTypes.ClassWrappers;
using ObjectiveHarmonyPatch;
using TypeWrapping;
using UnembeddedResources;

using AtsEx.BveHackerServices;
Expand Down Expand Up @@ -49,13 +44,8 @@ static BveHacker()
#endif
}

private readonly HarmonyPatch LoadScenarioPatch;
private readonly HarmonyPatch DisposeScenarioPatch;

private readonly StructureSetLifeProlonger StructureSetLifeProlonger;

private ScenarioInfo TargetScenarioInfo = null;

public BveHacker(BveTypeSet bveTypes)
{
BveTypes = bveTypes;
Expand All @@ -79,37 +69,20 @@ public BveHacker(BveTypeSet bveTypes)
break;

case LaunchMode.InputDevice:
ClassMemberSet mainFormMembers = BveTypes.GetClassInfoOf<MainForm>();
ClassMemberSet scenarioMembers = BveTypes.GetClassInfoOf<Scenario>();
LoadScenarioPatch = HarmonyPatch.Patch(nameof(BveHacker), mainFormMembers.GetSourceMethodOf(nameof(global::BveTypes.ClassWrappers.MainForm.LoadScenario)).Source, PatchType.Prefix);
DisposeScenarioPatch = HarmonyPatch.Patch(nameof(BveHacker), scenarioMembers.GetSourceMethodOf(nameof(global::BveTypes.ClassWrappers.Scenario.Dispose)).Source, PatchType.Prefix);

LoadScenarioPatch.Invoked += (sender, e) =>
ScenarioHacker.ScenarioOpened += e =>
{
ScenarioInfo scenarioInfo = ScenarioInfo.FromSource(e.Args[0]);
TargetScenarioInfo = scenarioInfo;

MapHeaders = HeaderSet.FromMap(scenarioInfo.RouteFiles.SelectedFile.Path);
MapHeaders = HeaderSet.FromMap(e.ScenarioInfo.RouteFiles.SelectedFile.Path);
ScenarioHacker.BeginObserveInitialization();

ScenarioOpened?.Invoke(this, EventArgs.Empty);

return new PatchInvokationResult(SkipModes.Continue);
ScenarioOpened?.Invoke(new ScenarioOpenedEventArgs(e.ScenarioInfo));
};

DisposeScenarioPatch.Invoked += (sender, e) =>
ScenarioHacker.ScenarioClosed += e =>
{
if (ScenarioInfo == TargetScenarioInfo)
{
MapHeaders = null;
MapStatements = null;

TargetScenarioInfo = null;
}
MapHeaders = null;
MapStatements = null;

ScenarioClosed?.Invoke(this, EventArgs.Empty);

return new PatchInvokationResult(SkipModes.Continue);
ScenarioClosed?.Invoke(EventArgs.Empty);
};

break;
Expand All @@ -122,9 +95,6 @@ public BveHacker(BveTypeSet bveTypes)
/// <inheritdoc/>
public void Dispose()
{
LoadScenarioPatch?.Dispose();
DisposeScenarioPatch?.Dispose();

StructureSetLifeProlonger.Dispose();
ScenarioHacker.Dispose();
}
Expand Down Expand Up @@ -185,12 +155,12 @@ public void Tick(TimeSpan elapsed)
IStatementSet IBveHacker.MapStatements => MapStatements;


public event EventHandler ScenarioOpened;
public event EventHandler ScenarioClosed;


private readonly ScenarioHacker ScenarioHacker;

public event ScenarioOpenedEventHandler ScenarioOpened;
public event ScenarioClosedEventHandler ScenarioClosed;
public event ScenarioCreatedEventHandler PreviewScenarioCreated;
public event ScenarioCreatedEventHandler ScenarioCreated;

Expand Down
74 changes: 56 additions & 18 deletions AtsEx/BveHacker/Services/ScenarioHacker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,83 @@ internal sealed class ScenarioHacker : IDisposable
{
private readonly MainForm MainForm;

private readonly HarmonyPatch LoadPatch;
private readonly HarmonyPatch DisposePatch;
private readonly HarmonyPatch InitializeTimeAndLocationMethodPatch;
private readonly HarmonyPatch InitializeMethodPatch;

private ScenarioInfo TargetScenarioInfo = null;

public ScenarioInfo CurrentScenarioInfo
{
get => MainForm.CurrentScenarioInfo;
set => MainForm.CurrentScenarioInfo = value;
}

public Scenario CurrentScenario
{
get => MainForm.CurrentScenario;
set => MainForm.CurrentScenario = value;
}

public event ScenarioOpenedEventHandler ScenarioOpened;
public event ScenarioClosedEventHandler ScenarioClosed;
public event ScenarioCreatedEventHandler ScenarioCreated;

public ScenarioHacker(MainFormHacker mainFormHacker, BveTypeSet bveTypes)
{
MainForm = mainFormHacker.TargetForm;

ClassMemberSet mainFormMembers = bveTypes.GetClassInfoOf<MainForm>();
ClassMemberSet scenarioMembers = bveTypes.GetClassInfoOf<Scenario>();

FastMethod loadMethod = mainFormMembers.GetSourceMethodOf(nameof(BveTypes.ClassWrappers.MainForm.LoadScenario));
FastMethod disposeMethod = scenarioMembers.GetSourceMethodOf(nameof(Scenario.Dispose));
FastMethod initializeTimeAndLocationMethod = scenarioMembers.GetSourceMethodOf(nameof(Scenario.InitializeTimeAndLocation));
FastMethod initializeMethod = scenarioMembers.GetSourceMethodOf(nameof(Scenario.Initialize));

InitializeTimeAndLocationMethodPatch = CreateAndSetupPatch(nameof(ScenarioHacker), initializeTimeAndLocationMethod.Source);
InitializeMethodPatch = CreateAndSetupPatch(nameof(ScenarioHacker), initializeMethod.Source);
LoadPatch = CreateAndSetupPatch(loadMethod.Source);
DisposePatch = CreateAndSetupPatch(disposeMethod.Source);
InitializeTimeAndLocationMethodPatch = CreateAndSetupPatch(initializeTimeAndLocationMethod.Source, PatchType.Postfix);
InitializeMethodPatch = CreateAndSetupPatch(initializeMethod.Source, PatchType.Postfix);

LoadPatch.Invoked += OnLoaded;
DisposePatch.Invoked += OnDisposed;


HarmonyPatch CreateAndSetupPatch(string name, MethodBase original)
HarmonyPatch CreateAndSetupPatch(MethodBase original, PatchType patchType = PatchType.Prefix)
{
HarmonyPatch patch = HarmonyPatch.Patch(name, original, PatchType.Postfix);
HarmonyPatch patch = HarmonyPatch.Patch(nameof(ScenarioHacker), original, patchType);
return patch;
}
}

private PatchInvokationResult OnLoaded(object sender, PatchInvokedEventArgs e)
{
ScenarioInfo scenarioInfo = ScenarioInfo.FromSource(e.Args[0]);
if (!(scenarioInfo is null) && scenarioInfo != TargetScenarioInfo) ScenarioClosed?.Invoke(EventArgs.Empty);
TargetScenarioInfo = scenarioInfo;

ScenarioOpened?.Invoke(new ScenarioOpenedEventArgs(scenarioInfo));

return PatchInvokationResult.DoNothing(e);
}

private PatchInvokationResult OnDisposed(object sender, PatchInvokedEventArgs e)
{
if (CurrentScenarioInfo == TargetScenarioInfo)
{
TargetScenarioInfo = null;
ScenarioClosed?.Invoke(EventArgs.Empty);
}

return PatchInvokationResult.DoNothing(e);
}

public void Dispose()
{
LoadPatch.Dispose();
DisposePatch.Dispose();
InitializeTimeAndLocationMethodPatch.Dispose();
InitializeMethodPatch.Dispose();
}
Expand All @@ -68,19 +120,5 @@ PatchInvokationResult OnPatchInvoked(object sender, PatchInvokedEventArgs e)
return PatchInvokationResult.DoNothing(e);
}
}

public event ScenarioCreatedEventHandler ScenarioCreated;

public ScenarioInfo CurrentScenarioInfo
{
get => MainForm.CurrentScenarioInfo;
set => MainForm.CurrentScenarioInfo = value;
}

public Scenario CurrentScenario
{
get => MainForm.CurrentScenario;
set => MainForm.CurrentScenario = value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public override void Dispose()
HarmonyPatches.Dispose();
}

private void OnScenarioClosed(object sender, EventArgs e)
private void OnScenarioClosed(EventArgs e)
{
PatchInvoker.ActivePatch = null;
}
Expand Down

0 comments on commit e1f2507

Please sign in to comment.