-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1fc2aee
commit 6c29ec5
Showing
9 changed files
with
437 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
Extensions/AtsEx.CoreExtensions/ConductorPatch/ConductorBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using BveTypes.ClassWrappers; | ||
|
||
namespace AtsEx.Extensions.ConductorPatch | ||
{ | ||
/// <summary> | ||
/// 車掌動作を上書きするための基本クラスを表します。 | ||
/// </summary> | ||
public abstract class ConductorBase | ||
{ | ||
/// <summary> | ||
/// オリジナルの車掌動作が定義されている <see cref="Conductor"/> です。 | ||
/// </summary> | ||
protected readonly Conductor Original; | ||
|
||
/// <summary> | ||
/// 停止位置の修正を要求したことを通知します。 | ||
/// </summary> | ||
protected abstract event EventHandler FixStopPositionRequested; | ||
|
||
/// <summary> | ||
/// 停止位置が良いことを確認したことを通知します。 | ||
/// </summary> | ||
protected abstract event EventHandler StopPositionChecked; | ||
|
||
/// <summary> | ||
/// ドアスイッチを開方向に扱ったことを通知します。 | ||
/// </summary> | ||
protected abstract event EventHandler DoorOpening; | ||
|
||
/// <summary> | ||
/// 発車ベルスイッチを扱ったこと、つまり停車場リストで定義した departureSound の再生を開始することを通知します。 | ||
/// </summary> | ||
protected abstract event EventHandler DepartureSoundPlaying; | ||
|
||
/// <summary> | ||
/// ドアスイッチを閉方向に扱ったことを通知します。 | ||
/// </summary> | ||
protected abstract event EventHandler DoorClosing; | ||
|
||
/// <summary> | ||
/// 車側灯の滅灯を確認したこと、つまり全てのドアが閉まりきったことを通知します。 | ||
/// </summary> | ||
protected abstract event EventHandler DoorClosed; | ||
|
||
/// <summary> | ||
/// <see cref="ConductorBase"/> クラスの新しいインスタンスを生成します。 | ||
/// </summary> | ||
/// <param name="original">オリジナルの車掌動作が定義されている <see cref="Conductor"/>。</param> | ||
protected ConductorBase(Conductor original) | ||
{ | ||
Original = original; | ||
|
||
FixStopPositionRequested += (sender, e) => Original.FixStopPositionRequested_Invoke(); | ||
StopPositionChecked += (sender, e) => Console.WriteLine("車掌: 停止位置よし"); | ||
DoorOpening += (sender, e) => Console.WriteLine("車掌スイッチ: 開"); | ||
DepartureSoundPlaying += (sender, e) => Console.WriteLine("発車ベル: ON"); | ||
DoorClosing += (sender, e) => Console.WriteLine("車掌スイッチ: 閉"); | ||
DoorClosed += (sender, e) => | ||
{ | ||
Console.WriteLine("側灯滅"); | ||
Original.DepartureRequested_Invoke(); | ||
}; | ||
} | ||
|
||
/// <summary> | ||
/// 自列車がテレポートしたときに呼び出されます。 | ||
/// </summary> | ||
/// <param name="nextStationIndex">ジャンプ先の距離程における次駅のインデックス。</param> | ||
/// <param name="isDoorClosed">ドアが閉まっているかどうか。</param> | ||
/// <returns>オリジナルの処理をオーバーライドする方法。</returns> | ||
internal protected virtual MethodOverrideMode OnJumped(int nextStationIndex, bool isDoorClosed) | ||
{ | ||
return MethodOverrideMode.RunOriginal; | ||
} | ||
|
||
/// <summary> | ||
/// ドアの状態が変更されたときに呼び出されます。 | ||
/// </summary> | ||
/// <returns>オリジナルの処理をオーバーライドする方法。</returns> | ||
internal protected virtual MethodOverrideMode OnDoorStateChanged() | ||
{ | ||
return MethodOverrideMode.RunOriginal; | ||
} | ||
|
||
/// <summary> | ||
/// 毎フレーム呼び出されます。 | ||
/// </summary> | ||
/// <returns>オリジナルの処理をオーバーライドする方法。</returns> | ||
internal protected virtual MethodOverrideMode OnTick() | ||
{ | ||
return MethodOverrideMode.RunOriginal; | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
Extensions/AtsEx.CoreExtensions/ConductorPatch/ConductorPatch.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace AtsEx.Extensions.ConductorPatch | ||
{ | ||
/// <summary> | ||
/// 車掌動作を上書きするパッチを表します。 | ||
/// </summary> | ||
public class ConductorPatch | ||
{ | ||
/// <summary> | ||
/// 新しい車掌動作を定義した <see cref="ConductorBase"/> を取得します。 | ||
/// </summary> | ||
public ConductorBase Conductor { get; } | ||
|
||
/// <summary> | ||
/// 車掌動作の上書き宣言の優先度を取得します。 | ||
/// </summary> | ||
public DeclarationPriority Priority { get; } | ||
|
||
|
||
internal ConductorPatch(ConductorBase conductor, DeclarationPriority priority) | ||
{ | ||
Conductor = conductor; | ||
Priority = priority; | ||
} | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
Extensions/AtsEx.CoreExtensions/ConductorPatch/ConductorPatchFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using BveTypes.ClassWrappers; | ||
using ObjectiveHarmonyPatch; | ||
|
||
using AtsEx.PluginHost.Plugins; | ||
using AtsEx.PluginHost.Plugins.Extensions; | ||
|
||
namespace AtsEx.Extensions.ConductorPatch | ||
{ | ||
[PluginType(PluginType.Extension)] | ||
[ExtensionMainDisplayType(typeof(IConductorPatchFactory))] | ||
internal class ConductorPatchFactory : AssemblyPluginBase, IConductorPatchFactory | ||
{ | ||
private readonly HarmonyPatchSet HarmonyPatches; | ||
private readonly ConductorPatchInvoker PatchInvoker; | ||
|
||
private readonly List<ConductorPatch> Patches = new List<ConductorPatch>(); | ||
|
||
public override string Title { get; } = nameof(ConductorPatch); | ||
public override string Description { get; } = "車掌の動作を自由に変更できるようにするパッチを提供します。"; | ||
|
||
public ConductorPatchFactory(PluginBuilder builder) : base(builder) | ||
{ | ||
HarmonyPatches = new HarmonyPatchSet(BveHacker.BveTypes); | ||
PatchInvoker = new ConductorPatchInvoker(HarmonyPatches); | ||
|
||
BveHacker.ScenarioClosed += OnScenarioClosed; | ||
} | ||
|
||
public override void Dispose() | ||
{ | ||
HarmonyPatches.Dispose(); | ||
} | ||
|
||
private void OnScenarioClosed(object sender, EventArgs e) | ||
{ | ||
PatchInvoker.ActivePatch = null; | ||
} | ||
|
||
public override TickResult Tick(TimeSpan elapsed) => new ExtensionTickResult(); | ||
|
||
public void BeginPatch(Func<Conductor, ConductorBase> conductorFactory, DeclarationPriority priority, Action<ConductorPatch> patchedCallback) | ||
{ | ||
HarmonyPatches.Constructor.Invoked += OnConductorConstructed; | ||
|
||
|
||
PatchInvokationResult OnConductorConstructed(object sender, PatchInvokedEventArgs e) | ||
{ | ||
HarmonyPatches.Constructor.Invoked -= OnConductorConstructed; | ||
|
||
Conductor original = Conductor.FromSource(e.Instance); | ||
ConductorBase conductor = conductorFactory(original); | ||
ConductorPatch patch = Patch(conductor, priority); | ||
|
||
patchedCallback(patch); | ||
return PatchInvokationResult.DoNothing(e); | ||
} | ||
} | ||
|
||
public ConductorPatch Patch(ConductorBase conductor, DeclarationPriority priority) | ||
{ | ||
if (PatchInvoker.ActivePatch?.Priority == DeclarationPriority.TopMost) | ||
{ | ||
throw new InvalidOperationException($"優先度 {DeclarationPriority.TopMost} のパッチが既に適用されています。"); | ||
} | ||
|
||
ConductorPatch patch = new ConductorPatch(conductor, priority); | ||
Patches.Add(patch); | ||
|
||
PatchInvoker.ActivePatch = GetStrongest(); | ||
return patch; | ||
} | ||
|
||
public void Unpatch(ConductorPatch patch) | ||
{ | ||
Patches.Remove(patch); | ||
PatchInvoker.ActivePatch = GetStrongest(); | ||
} | ||
|
||
private ConductorPatch GetStrongest() | ||
{ | ||
ConductorPatch topMost = Patches.FirstOrDefault(patch => patch.Priority == DeclarationPriority.TopMost); | ||
if (!(topMost is null)) return topMost; | ||
|
||
ConductorPatch sequentially = Patches.LastOrDefault(patch => patch.Priority == DeclarationPriority.Sequentially); | ||
if (!(sequentially is null)) return sequentially; | ||
|
||
ConductorPatch asDefaultValue = Patches.LastOrDefault(); | ||
return asDefaultValue; | ||
} | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
Extensions/AtsEx.CoreExtensions/ConductorPatch/ConductorPatchInvoker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using ObjectiveHarmonyPatch; | ||
|
||
namespace AtsEx.Extensions.ConductorPatch | ||
{ | ||
internal class ConductorPatchInvoker | ||
{ | ||
private readonly HarmonyPatchSet HarmonyPatches; | ||
|
||
public ConductorPatch ActivePatch { get; set; } = null; | ||
|
||
public ConductorPatchInvoker(HarmonyPatchSet harmonyPatches) | ||
{ | ||
HarmonyPatches = harmonyPatches; | ||
|
||
HarmonyPatches.OnJumped.Invoked += OnJumped; | ||
HarmonyPatches.OnDoorStateChanged.Invoked += OnDoorStateChanged; | ||
HarmonyPatches.OnTick.Invoked += OnTick; | ||
} | ||
|
||
private PatchInvokationResult OnJumped(object sender, PatchInvokedEventArgs e) | ||
{ | ||
if (ActivePatch is null) return PatchInvokationResult.DoNothing(e); | ||
|
||
MethodOverrideMode overrideMode = ActivePatch.Conductor.OnJumped((int)e.Args[0], (bool)e.Args[1]); | ||
return CreateInvokationResult(overrideMode); | ||
} | ||
|
||
private PatchInvokationResult OnDoorStateChanged(object sender, PatchInvokedEventArgs e) | ||
{ | ||
if (ActivePatch is null) return PatchInvokationResult.DoNothing(e); | ||
|
||
MethodOverrideMode overrideMode = ActivePatch.Conductor.OnDoorStateChanged(); | ||
return CreateInvokationResult(overrideMode); | ||
} | ||
|
||
private PatchInvokationResult OnTick(object sender, PatchInvokedEventArgs e) | ||
{ | ||
if (ActivePatch is null) return PatchInvokationResult.DoNothing(e); | ||
|
||
MethodOverrideMode overrideMode = ActivePatch.Conductor.OnTick(); | ||
return CreateInvokationResult(overrideMode); | ||
} | ||
|
||
private PatchInvokationResult CreateInvokationResult(MethodOverrideMode overrideMode) | ||
{ | ||
switch (overrideMode) | ||
{ | ||
case MethodOverrideMode.SkipOriginal: | ||
return new PatchInvokationResult(SkipModes.SkipOriginal); | ||
|
||
case MethodOverrideMode.RunOriginal: | ||
return new PatchInvokationResult(SkipModes.Continue); | ||
|
||
default: | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
Extensions/AtsEx.CoreExtensions/ConductorPatch/DeclarationPriority.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace AtsEx.Extensions.ConductorPatch | ||
{ | ||
/// <summary> | ||
/// 車掌動作の上書き宣言の優先度を指定します。 | ||
/// </summary> | ||
public enum DeclarationPriority | ||
{ | ||
/// <summary> | ||
/// 既定値として宣言することを指定します。他に宣言が存在する場合は無条件に上書きされます。 | ||
/// </summary> | ||
AsDefaultValue = 0, | ||
|
||
/// <summary> | ||
/// 通常の優先度で宣言することを指定します。既になされた優先度 <see cref="Sequentially"/> の宣言を上書きしますが、後に他の優先度 <see cref="Sequentially"/> の宣言がなされた場合は上書きされます。 | ||
/// </summary> | ||
Sequentially, | ||
|
||
/// <summary> | ||
/// 最上級の優先度で宣言することを指定します。全ての他の宣言を無条件に上書きします。 | ||
/// </summary> | ||
TopMost, | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
Extensions/AtsEx.CoreExtensions/ConductorPatch/HarmonyPatchSet.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using BveTypes; | ||
using BveTypes.ClassWrappers; | ||
using ObjectiveHarmonyPatch; | ||
using TypeWrapping; | ||
|
||
namespace AtsEx.Extensions.ConductorPatch | ||
{ | ||
internal class HarmonyPatchSet : IDisposable | ||
{ | ||
public HarmonyPatch Constructor { get; } | ||
public HarmonyPatch OnJumped { get; } | ||
public HarmonyPatch OnDoorStateChanged { get; } | ||
public HarmonyPatch OnTick { get; } | ||
|
||
public HarmonyPatchSet(BveTypeSet bveTypes) | ||
{ | ||
ClassMemberSet members = bveTypes.GetClassInfoOf<Conductor>(); | ||
|
||
Constructor = HarmonyPatch.Patch(nameof(ConductorPatchFactory), members.GetSourceConstructor().Source, PatchType.Postfix); | ||
OnJumped = HarmonyPatch.Patch(nameof(ConductorPatchFactory), members.GetSourceMethodOf(nameof(Conductor.OnJumped)).Source, PatchType.Prefix); | ||
OnDoorStateChanged = HarmonyPatch.Patch(nameof(ConductorPatchFactory), members.GetSourceMethodOf(nameof(Conductor.OnDoorStateChanged)).Source, PatchType.Prefix); | ||
OnTick = HarmonyPatch.Patch(nameof(ConductorPatchFactory), members.GetSourceMethodOf(nameof(Conductor.OnTick)).Source, PatchType.Prefix); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Constructor.Dispose(); | ||
OnJumped.Dispose(); | ||
OnDoorStateChanged.Dispose(); | ||
OnTick.Dispose(); | ||
} | ||
} | ||
} |
Oops, something went wrong.