Skip to content

Commit cfc8add

Browse files
authored
Merge pull request #76 from hocha113/8075
8075
2 parents 092ab17 + 594262d commit cfc8add

Some content is hidden

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

42 files changed

+1086
-614
lines changed

CWRNetWork.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public enum CWRMessageType : byte
4444
ResurrectionRate,
4545
DespawnDestroyer,
4646
MachineEffect,
47-
DeathTrackingNPCKill,
4847
}
4948

5049
public static class CWRNetWork
@@ -94,9 +93,6 @@ public static void HandlePacket(Mod mod, BinaryReader reader, int whoAmI) {
9493
else if (type == CWRMessageType.DespawnDestroyer) {
9594
DestroyerHeadAI.HandleDespawn();
9695
}
97-
else if (type == CWRMessageType.DeathTrackingNPCKill) {
98-
DeathTrackingNPC.HandleKillSync(reader, whoAmI);
99-
}
10096

10197
ModifyCrabulon.NetHandle(type, reader, whoAmI);
10298
HalibutPlayer.NetHandle(type, reader, whoAmI);

Content/ADV/ADVHook.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,23 @@
1-
using System.IO;
2-
using Terraria;
1+
using Terraria;
32
using Terraria.ModLoader;
43

54
namespace CalamityOverhaul.Content.ADV.Common
65
{
76
internal class DeathTrackingNPC : GlobalNPC
87
{
98
public override bool InstancePerEntity => true;
10-
/// <summary>
11-
/// 当NPC被击杀时调用,在客户端或者服务端上均会运行
12-
/// </summary>
13-
/// <param name="npc"></param>
14-
public override void OnKill(NPC npc) { }
159

16-
/// <summary>
17-
/// 遍历NPC上所有DeathTrackingNPC子类并调用OnKill
18-
/// </summary>
19-
internal static void DispatchOnKill(NPC npc) {
20-
foreach (var n in npc.EntityGlobals) {
21-
if (n is not DeathTrackingNPC tracker) {
22-
continue;
23-
}
24-
tracker.OnKill(npc);
25-
}
26-
}
27-
28-
/// <summary>
29-
/// 从服务端向所有客户端发送击杀同步包
30-
/// </summary>
31-
internal static void SendKillSync(int npcWhoAmI, int npcType) {
32-
if (VaultUtils.isSinglePlayer) {
10+
public override void HitEffect(NPC npc, NPC.HitInfo hit) {
11+
if (npc.life > 0) {
3312
return;
3413
}
35-
ModPacket packet = CWRMod.Instance.GetPacket();
36-
packet.Write((byte)CWRMessageType.DeathTrackingNPCKill);
37-
packet.Write(npcWhoAmI);
38-
packet.Write(npcType);
39-
packet.Send();
14+
OnKill(npc);
4015
}
4116

4217
/// <summary>
43-
/// 客户端接收击杀同步包并触发OnKill调用
18+
/// 当NPC被击杀时调用,在客户端或者服务端上均会运行
4419
/// </summary>
45-
internal static void HandleKillSync(BinaryReader reader, int whoAmI) {
46-
int npcWhoAmI = reader.ReadInt32();
47-
int npcType = reader.ReadInt32();
48-
if (npcWhoAmI.TryGetNPC(out NPC npc)) {
49-
DispatchOnKill(npc);
50-
}
51-
}
20+
/// <param name="npc"></param>
21+
public new virtual void OnKill(NPC npc) { }
5222
}
5323
}

Content/CWRPlayer.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,6 @@ public class CWRPlayer : ModPlayer
217217
/// </summary>
218218
public int DontUseItemTime;
219219
/// <summary>
220-
/// 毁灭者的存在索引
221-
/// </summary>
222-
internal static int TheDestroyer = -1;
223-
/// <summary>
224220
/// 抬棺人下一发弩箭的伤害倍率,默认为1
225221
/// </summary>
226222
public float PallbearerNextArrowDamageMult = 1;
@@ -297,7 +293,6 @@ private void Reset() {
297293
KreloadTimeIncrease = 1;
298294
HeldStyle = -1;
299295
ReloadingRatio = 0;
300-
TheDestroyer = -1;
301296
IsUnsunghero = false;
302297
InFoodStallChair = false;
303298
HeldMurasamaBool = false;

Content/LegendWeapon/HalibutLegend/Resurrections/ResurrectionDeath.cs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Xna.Framework.Graphics;
1+
using CalamityOverhaul.Content.Items.Tools;
2+
using Microsoft.Xna.Framework.Graphics;
23
using System;
34
using System.Collections.Generic;
45
using Terraria;
@@ -89,6 +90,11 @@ private enum DeathState
8990
/// 玩家透明度修改
9091
/// </summary>
9192
private float playerAlphaMultiplier = 1f;
93+
/// <summary>
94+
/// 由Kill设置,标记玩家已死亡需要在下次PreUpdate时重置状态
95+
/// (PreUpdate在玩家死亡期间不运行,所以不能依赖Player.dead)
96+
/// </summary>
97+
private bool needsDeathReset = false;
9298
#endregion
9399

94100
public static LocalizedText DeathText { get; private set; }
@@ -107,17 +113,20 @@ public override void SetStaticDefaults() {
107113

108114
#region 主更新逻辑
109115
public override void PreUpdate() {
116+
if (!Player.Alives()) {
117+
return;
118+
}
119+
110120
var system = Player.GetResurrectionSystem();
111121
if (system == null) {
112122
ResetState();
113123
return;
114124
}
115125

116-
//如果玩家已经死亡,重置状态
117-
if (Player.dead) {
118-
if (currentState != DeathState.None && currentState != DeathState.Cooldown) {
119-
ResetState();
120-
}
126+
//如果Kill中标记了需要重置,在此处执行
127+
if (needsDeathReset) {
128+
needsDeathReset = false;
129+
Respawn();
121130
return;
122131
}
123132

@@ -365,6 +374,7 @@ private void ExecuteDeath() {
365374
DeathText.ToNetworkText(Player.name)
366375
);
367376

377+
SirenMusicalBoxPlayerDeath.MusichasEnded = true;
368378
//杀死玩家
369379
Player.KillMe(damageSource, Player.statLife + 1, 0, false);
370380

@@ -432,6 +442,7 @@ private void ResetState() {
432442
hasExecutedDeath = false;
433443
midPhaseSoundPlayed = false;
434444
playerAlphaMultiplier = 1f;
445+
needsDeathReset = false;
435446

436447
//清理效果
437448
abyssParticles.Clear();
@@ -446,7 +457,7 @@ private void ResetState() {
446457
#endregion
447458

448459
#region 重生处理
449-
public override void OnRespawn() {
460+
public void Respawn() {
450461
var system = Player.GetResurrectionSystem();
451462
if (system == null) {
452463
return;
@@ -473,7 +484,13 @@ public override void OnRespawn() {
473484
}
474485
}
475486

487+
public override void OnRespawn() {
488+
needsDeathReset = false;
489+
Respawn();
490+
}
491+
476492
public override void Kill(double damage, int hitDirection, bool pvp, PlayerDeathReason damageSource) {
493+
needsDeathReset = true;
477494
if (Player.TryGetHalibutPlayer(out var halibutPlayer)) {
478495
halibutPlayer.CanCloseEye = true;
479496
}

Content/NPCs/BrutalNPCs/BrutalDestroyer/Core/DestroyerStateMachine.cs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
namespace CalamityOverhaul.Content.NPCs.BrutalNPCs.BrutalDestroyer.Core
1+
using CalamityOverhaul.Content.NPCs.BrutalNPCs.BrutalDestroyer.States;
2+
using Terraria;
3+
4+
namespace CalamityOverhaul.Content.NPCs.BrutalNPCs.BrutalDestroyer.Core
25
{
36
/// <summary>
4-
/// 毁灭者状态机
7+
/// 毁灭者状态机,服务端/单人端驱动状态转移,客户端通过npc.ai[]同步
58
/// </summary>
69
internal class DestroyerStateMachine
710
{
@@ -16,6 +19,7 @@ public DestroyerStateMachine(DestroyerStateContext context) {
1619
public void SetInitialState(IDestroyerState state) {
1720
CurrentState = state;
1821
CurrentState?.OnEnter(Context);
22+
SyncStateToAI();
1923
}
2024

2125
public void ForceChangeState(IDestroyerState newState) {
@@ -24,18 +28,74 @@ public void ForceChangeState(IDestroyerState newState) {
2428
PreviousState = CurrentState;
2529
CurrentState = newState;
2630
CurrentState.OnEnter(Context);
31+
SyncStateToAI();
32+
Context.Npc.netUpdate = true;
2733
}
2834

2935
public void Update() {
3036
if (CurrentState == null) return;
3137

38+
//客户端通过ai[]检测服务端的状态切换
39+
if (VaultUtils.isClient) {
40+
SyncStateFromAI();
41+
}
42+
3243
IDestroyerState nextState = CurrentState.OnUpdate(Context);
33-
if (nextState != null && nextState != CurrentState) {
44+
45+
//只有服务端/单人端才能驱动状态转移
46+
if (!VaultUtils.isClient && nextState != null && nextState != CurrentState) {
3447
CurrentState.OnExit(Context);
3548
PreviousState = CurrentState;
3649
CurrentState = nextState;
3750
CurrentState.OnEnter(Context);
51+
SyncStateToAI();
52+
Context.Npc.netUpdate = true;
53+
}
54+
}
55+
56+
/// <summary>
57+
/// 将当前状态索引写入npc.ai[2],以便网络同步
58+
/// </summary>
59+
private void SyncStateToAI() {
60+
if (CurrentState != null && Context.Npc != null) {
61+
Context.Npc.ai[2] = (float)CurrentState.StateIndex;
62+
}
63+
}
64+
65+
/// <summary>
66+
/// 客户端从npc.ai[2]读取服务端状态,若不一致则切换
67+
/// </summary>
68+
private void SyncStateFromAI() {
69+
if (Context.Npc == null || CurrentState == null) return;
70+
int serverStateIndex = (int)Context.Npc.ai[2];
71+
if (serverStateIndex != (int)CurrentState.StateIndex) {
72+
IDestroyerState newState = CreateStateFromIndex((DestroyerStateIndex)serverStateIndex);
73+
if (newState != null) {
74+
CurrentState.OnExit(Context);
75+
PreviousState = CurrentState;
76+
CurrentState = newState;
77+
CurrentState.OnEnter(Context);
78+
}
3879
}
3980
}
81+
82+
/// <summary>
83+
/// 根据索引创建状态实例(客户端同步用)
84+
/// </summary>
85+
internal static IDestroyerState CreateStateFromIndex(DestroyerStateIndex index) {
86+
return index switch {
87+
DestroyerStateIndex.Intro => new DestroyerIntroState(),
88+
DestroyerStateIndex.Patrol => new DestroyerPatrolState(),
89+
DestroyerStateIndex.DashPrepare => new DestroyerDashPrepareState(),
90+
DestroyerStateIndex.Dashing => new DestroyerDashingState(0, 3),
91+
DestroyerStateIndex.DashCooldown => new DestroyerDashCooldownState(0, 3),
92+
DestroyerStateIndex.LaserBarrage => new DestroyerLaserBarrageState(),
93+
DestroyerStateIndex.Encircle => new DestroyerEncircleState(),
94+
DestroyerStateIndex.ProbeMatrix => new DestroyerProbeMatrixState(),
95+
DestroyerStateIndex.Despawn => new DestroyerDespawnState(),
96+
DestroyerStateIndex.Death => new DestroyerDeathState(),
97+
_ => null,
98+
};
99+
}
40100
}
41101
}

Content/NPCs/BrutalNPCs/BrutalDestroyer/Core/IDestroyerState.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,30 @@
22

33
namespace CalamityOverhaul.Content.NPCs.BrutalNPCs.BrutalDestroyer.Core
44
{
5+
/// <summary>
6+
/// 毁灭者状态索引,用于网络同步
7+
/// </summary>
8+
internal enum DestroyerStateIndex : int
9+
{
10+
Intro = 0,
11+
Patrol = 1,
12+
DashPrepare = 2,
13+
Dashing = 3,
14+
DashCooldown = 4,
15+
LaserBarrage = 5,
16+
Encircle = 6,
17+
ProbeMatrix = 7,
18+
Despawn = 8,
19+
Death = 9,
20+
}
21+
522
/// <summary>
623
/// 毁灭者状态接口
724
/// </summary>
825
internal interface IDestroyerState
926
{
1027
string StateName { get; }
28+
DestroyerStateIndex StateIndex { get; }
1129
void OnEnter(DestroyerStateContext context);
1230
IDestroyerState OnUpdate(DestroyerStateContext context);
1331
void OnExit(DestroyerStateContext context);
@@ -19,6 +37,7 @@ internal interface IDestroyerState
1937
internal abstract class DestroyerStateBase : IDestroyerState
2038
{
2139
public abstract string StateName { get; }
40+
public abstract DestroyerStateIndex StateIndex { get; }
2241
protected int Timer { get; set; }
2342
protected int Counter { get; set; }
2443

Content/NPCs/BrutalNPCs/BrutalDestroyer/DestroyerHeadAI.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,16 @@ private void InitializeStateContext() {
6666
IsDeathMode = CWRRef.GetDeathMode() || CWRRef.GetBossRushActive()
6767
};
6868
stateMachine = new DestroyerStateMachine(stateContext);
69-
stateMachine.SetInitialState(new DestroyerIntroState());
69+
70+
//客户端加入时从npc.ai[2]恢复服务端当前状态,避免状态desync
71+
if (VaultUtils.isClient) {
72+
int serverStateIndex = (int)npc.ai[2];
73+
IDestroyerState syncedState = DestroyerStateMachine.CreateStateFromIndex((DestroyerStateIndex)serverStateIndex);
74+
stateMachine.SetInitialState(syncedState ?? new DestroyerIntroState());
75+
}
76+
else {
77+
stateMachine.SetInitialState(new DestroyerIntroState());
78+
}
7079
}
7180
#endregion
7281

@@ -81,8 +90,6 @@ public override bool AI() {
8190
return true;
8291
}
8392

84-
CWRPlayer.TheDestroyer = npc.whoAmI;
85-
8693
//延迟初始化保护
8794
if (stateContext == null || stateMachine == null) {
8895
InitializeStateContext();
@@ -189,7 +196,7 @@ private void FindTarget() {
189196
targetPlayer = Main.player[npc.target];
190197

191198
if (!targetPlayer.Alives()) {
192-
if (stateMachine?.CurrentState is not DestroyerDespawnState) {
199+
if (!VaultUtils.isClient && stateMachine?.CurrentState is not DestroyerDespawnState) {
193200
stateMachine?.ForceChangeState(new DestroyerDespawnState());
194201
}
195202
}

0 commit comments

Comments
 (0)