Skip to content

Commit fdd9394

Browse files
committed
chore(release): merge dev into main for v0.3.4
2 parents 81294af + 5f66fdb commit fdd9394

50 files changed

Lines changed: 5453 additions & 141 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Combat/HandSize/MaxHandSizePatchInstaller.cs

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ private static bool IsMaxHandSizeToken(CodeInstruction ins)
208208
return HarmonyIl.LoadsInt32(ins, DefaultMaxHandSize);
209209
#else
210210
return HarmonyIl.LoadsInt32(ins, DefaultMaxHandSize)
211-
|| HarmonyIl.IsCallTo(ins, MaxCardsInHandGetter);
211+
|| HarmonyIl.IsCall(MaxCardsInHandGetter)(ins);
212212
#endif
213213
}
214214

@@ -259,7 +259,7 @@ private static IEnumerable<CodeInstruction> PlayerArg1Transpiler(IEnumerable<Cod
259259
private static IEnumerable<CodeInstruction> StateMachineTranspiler(IEnumerable<CodeInstruction> instructions)
260260
{
261261
var rewriter = HarmonyIlRewriter.From(instructions);
262-
var loadPlayer = FindStateMachinePlayerLoad(rewriter.Code);
262+
var loadPlayer = FindStateMachinePlayerLoad(rewriter);
263263
if (loadPlayer == null)
264264
{
265265
RitsuLibFramework.Logger.Warn(
@@ -279,7 +279,7 @@ private static IEnumerable<CodeInstruction> StateMachineTranspiler(IEnumerable<C
279279
private static IEnumerable<CodeInstruction> CardOnPlayTranspiler(IEnumerable<CodeInstruction> instructions)
280280
{
281281
var rewriter = HarmonyIlRewriter.From(instructions);
282-
var loadCard = FindStateMachineCardLoad(rewriter.Code);
282+
var loadCard = FindStateMachineCardLoad(rewriter);
283283
if (loadCard == null)
284284
{
285285
RitsuLibFramework.Logger.Warn(
@@ -296,35 +296,29 @@ private static IEnumerable<CodeInstruction> CardOnPlayTranspiler(IEnumerable<Cod
296296
return rewriter.InstructionsChecked("[MaxHandSize] Card OnPlay max-hand-size replacement");
297297
}
298298

299-
private static IReadOnlyList<CodeInstruction>? FindStateMachinePlayerLoad(IReadOnlyList<CodeInstruction> code)
299+
private static IReadOnlyList<CodeInstruction>? FindStateMachinePlayerLoad(HarmonyIlRewriter rewriter)
300300
{
301-
var pattern = HarmonyIlPattern.Sequence(HarmonyIl.IsLdarg(0), HarmonyIl.IsLdfld());
302-
foreach (var match in pattern.FindAll(code))
303-
{
304-
var fieldInstruction = match.InstructionAt(code, 1);
305-
if (fieldInstruction.operand is not FieldInfo field || field.FieldType != typeof(Player))
306-
continue;
307-
308-
return [match.InstructionAt(code, 0).Clone(), fieldInstruction.Clone()];
309-
}
301+
return FindStateMachineFieldLoad(rewriter, field => field.FieldType == typeof(Player),
302+
"[MaxHandSize] state-machine Player field load");
303+
}
310304

311-
return null;
305+
private static IReadOnlyList<CodeInstruction>? FindStateMachineCardLoad(HarmonyIlRewriter rewriter)
306+
{
307+
return FindStateMachineFieldLoad(rewriter, field => typeof(CardModel).IsAssignableFrom(field.FieldType),
308+
"[MaxHandSize] state-machine CardModel field load");
312309
}
313310

314-
private static IReadOnlyList<CodeInstruction>? FindStateMachineCardLoad(IReadOnlyList<CodeInstruction> code)
311+
private static IReadOnlyList<CodeInstruction>? FindStateMachineFieldLoad(
312+
HarmonyIlRewriter rewriter,
313+
Func<FieldInfo, bool> fieldPredicate,
314+
string description)
315315
{
316316
var pattern = HarmonyIlPattern.Sequence(HarmonyIl.IsLdarg(0), HarmonyIl.IsLdfld());
317-
foreach (var match in pattern.FindAll(code))
318-
{
319-
var fieldInstruction = match.InstructionAt(code, 1);
320-
if (fieldInstruction.operand is not FieldInfo field ||
321-
!typeof(CardModel).IsAssignableFrom(field.FieldType))
322-
continue;
323-
324-
return [match.InstructionAt(code, 0).Clone(), fieldInstruction.Clone()];
325-
}
326-
327-
return null;
317+
return (from match in rewriter.FindMatches(pattern, description).Items
318+
where fieldPredicate(match.GetFieldOperand(rewriter.Code, 1))
319+
select (IReadOnlyList<CodeInstruction>?)
320+
[match.InstructionAt(rewriter.Code, 0).Clone(), match.InstructionAt(rewriter.Code, 1).Clone()])
321+
.FirstOrDefault();
328322
}
329323

330324
// ReSharper disable InconsistentNaming
@@ -371,7 +365,7 @@ private static IEnumerable<CodeInstruction> StartCardPlayTranspiler(IEnumerable<
371365

372366
private static bool ContainsCall(IReadOnlyList<CodeInstruction> code, MethodInfo method)
373367
{
374-
return code.Any(instruction => HarmonyIl.IsCallTo(instruction, method));
368+
return code.Any(HarmonyIl.IsCall(method));
375369
}
376370

377371
private static void WarnIfRewriteUnsatisfied(HarmonyIlRewriteReport report)

Const.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static class Const
2222
/// Assembly / manifest version string.
2323
/// 程序集/清单版本字符串。
2424
/// </summary>
25-
public const string Version = "0.3.3";
25+
public const string Version = "0.3.4";
2626

2727
/// <summary>
2828
/// Root key for RitsuLib JSON settings under the mod’s user folder.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace STS2RitsuLib.Interactions.RightClick
2+
{
3+
/// <summary>
4+
/// Handles a local right-click request before the built-in model-interface handler.
5+
/// 在内置模型接口 handler 之前处理本地右键请求。
6+
/// </summary>
7+
public interface IModRightClickHandler
8+
{
9+
/// <summary>
10+
/// Higher priority handlers run first.
11+
/// 优先级越高越先运行。
12+
/// </summary>
13+
int Priority => 0;
14+
15+
/// <summary>
16+
/// Returns true when the request was accepted and should consume input.
17+
/// 返回 true 表示请求已被接受,应消耗输入。
18+
/// </summary>
19+
bool TryHandle(ModRightClickContext context);
20+
}
21+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
namespace STS2RitsuLib.Interactions.RightClick
2+
{
3+
/// <summary>
4+
/// Implement on a model to receive synced right-click actions through RitsuLib.
5+
/// 在模型上实现此接口,即可通过 RitsuLib 接收同步右键动作。
6+
/// </summary>
7+
public interface IModRightClickableModel
8+
{
9+
/// <summary>
10+
/// Local preflight check. Returning false leaves the input unhandled.
11+
/// 本地预检;返回 false 时不会消耗输入。
12+
/// </summary>
13+
bool CanHandleRightClickLocal(ModRightClickContext context)
14+
{
15+
return true;
16+
}
17+
18+
/// <summary>
19+
/// Runs when the synced right-click action reaches the queue.
20+
/// 当同步右键动作到达队列时运行。
21+
/// </summary>
22+
Task OnRightClick(ModRightClickExecutionContext context);
23+
}
24+
25+
/// <inheritdoc />
26+
public interface IModRightClickableCard : IModRightClickableModel;
27+
28+
/// <inheritdoc />
29+
public interface IModRightClickableRelic : IModRightClickableModel;
30+
31+
/// <inheritdoc />
32+
public interface IModRightClickablePower : IModRightClickableModel;
33+
34+
/// <inheritdoc />
35+
public interface IModRightClickablePotion : IModRightClickableModel;
36+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using MegaCrit.Sts2.Core.Entities.Players;
2+
using MegaCrit.Sts2.Core.Models;
3+
4+
namespace STS2RitsuLib.Interactions.RightClick
5+
{
6+
/// <summary>
7+
/// Local right-click dispatch context.
8+
/// 本地右键分发上下文。
9+
/// </summary>
10+
/// <param name="Player">
11+
/// Local player that initiated the request.
12+
/// 发起请求的本地玩家。
13+
/// </param>
14+
/// <param name="Model">
15+
/// Clicked model.
16+
/// 被点击的模型。
17+
/// </param>
18+
/// <param name="Trigger">
19+
/// Input metadata.
20+
/// 输入元数据。
21+
/// </param>
22+
public readonly record struct ModRightClickContext(
23+
Player Player,
24+
AbstractModel Model,
25+
ModRightClickTrigger Trigger);
26+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using MegaCrit.Sts2.Core.Entities.Players;
2+
using MegaCrit.Sts2.Core.GameActions;
3+
using MegaCrit.Sts2.Core.GameActions.Multiplayer;
4+
using MegaCrit.Sts2.Core.Models;
5+
6+
namespace STS2RitsuLib.Interactions.RightClick
7+
{
8+
/// <summary>
9+
/// Context passed when a synced right-click action reaches the action queue.
10+
/// 当同步右键动作到达动作队列时传递的上下文。
11+
/// </summary>
12+
public readonly record struct ModRightClickExecutionContext(
13+
Player Player,
14+
AbstractModel Model,
15+
ModRightClickTrigger Trigger,
16+
GameActionPlayerChoiceContext? PlayerChoiceContext,
17+
GenericHookGameAction? Action);
18+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace STS2RitsuLib.Interactions.RightClick
2+
{
3+
/// <summary>
4+
/// Model families supported by the built-in right-click node patches.
5+
/// 内置右键节点 patch 支持的模型类别。
6+
/// </summary>
7+
public enum ModRightClickModelKind
8+
{
9+
/// <summary>
10+
/// Hand card.
11+
/// 手牌。
12+
/// </summary>
13+
Card = 0,
14+
15+
/// <summary>
16+
/// Relic.
17+
/// 遗物。
18+
/// </summary>
19+
Relic = 1,
20+
21+
/// <summary>
22+
/// Power.
23+
/// 能力。
24+
/// </summary>
25+
Power = 2,
26+
27+
/// <summary>
28+
/// Potion.
29+
/// 药水。
30+
/// </summary>
31+
Potion = 3,
32+
}
33+
}

0 commit comments

Comments
 (0)