Conversation
- fix team fastswitch from player spawn packet - also fix initial team change message not being broadcast on player spawning in
Greptile SummaryThis PR fixes several PvP-mode bypass vectors by taking full control of the non-SSC spawn packet path and wiring in an Key changes:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant C as Client
participant HS as HandleSpawn
participant HT as HandlePlayerTeam
participant OSU as OnSecondUpdate
C->>HS: PlayerSpawn (team=N, context=SpawningIntoWorld)
Note over HS: pvpwithnoteam? → force team=0, teamCorrectNeeded=true
Note over HS: Fast-switch? (FinishedHandshake && <5s) → teamCorrectNeeded=true
HS->>HS: FinishedHandshake=true<br/>InitialTeamChangePending=true (non-SSC, team≠0, !teamCorrectNeeded)<br/>LastPvPTeamChange=UtcNow
HS->>C: PlayerSpawn broadcast (team corrected if needed)
HS-->>C: PlayerTeam correction (if teamCorrectNeeded)
C->>HT: PlayerTeam (team=N)
Note over HT: InitialTeamChangePending=true → skip early-return
alt pvpwithnoteam
HT-->>C: PlayerTeam correction (reject)
else InitialTeamChangePending
HT->>HT: InitialTeamChangePending=false<br/>LastPvPTeamChange=DateTime.MinValue
HT->>C: Broadcast team change (return false → engine handles)
else rate limit (<5s)
HT-->>C: PlayerTeam correction (reject)
else allowed
HT->>HT: LastPvPTeamChange=UtcNow
HT->>C: Broadcast team change
end
loop Every second
OSU->>OSU: Expire InitialTeamChangePending if ≥5s elapsed
OSU->>OSU: Enforce pvp hostile flag (disabled/always/pvpwithnoteam)
OSU->>OSU: Enforce team=0 for pvpwithnoteam
OSU-->>C: TogglePvp / PlayerTeam corrections if needed
end
Last reviewed commit: d31bde4 |
| player.InitialTeamChangePending = false; | ||
|
|
||
| // We need to make sure the pvp mode is enforced properly. Maybe this should be moved elsewhere? | ||
| string pvpMode = Config.Settings.PvPMode.ToLowerInvariant(); |
There was a problem hiding this comment.
ToLowerInvariant() called per player per tick
Config.Settings.PvPMode.ToLowerInvariant() allocates a new string on every call. Since this runs inside the OnSecondUpdate loop (once per connected player, every second), it creates unnecessary allocations proportional to the player count. Consider computing it once before the loop, or caching a lowercased copy of the setting when it changes.
| string pvpMode = Config.Settings.PvPMode.ToLowerInvariant(); | |
| string pvpMode = Config.Settings.PvPMode.ToLowerInvariant(); |
Move this line outside the per-player foreach loop to compute it only once per tick.
TShockAPI/GetDataHandlers.cs
Outdated
| if (respawnTimer > 0) | ||
| args.Player.TPlayer.dead = true; | ||
|
|
||
| args.Player.TPlayer.Spawn(context); |
There was a problem hiding this comment.
TPlayer.dead assignment overwritten by Spawn()
Terraria.Player.Spawn() resets this.dead = false internally, so the assignment on line 3068 is immediately overwritten by the Spawn(context) call on line 3071. The authoritative death-state for TShock is tracked via TSPlayer.Dead (already set earlier at line 2986 for the non-SSC path), so this doesn't break anything — but the assignment here is a no-op that may confuse future readers.
Consider either removing the dead = true assignment, or placing it after the Spawn() call if the intent is to override Terraria's reset:
| if (respawnTimer > 0) | |
| args.Player.TPlayer.dead = true; | |
| args.Player.TPlayer.Spawn(context); | |
| args.Player.TPlayer.Spawn(context); | |
| if (respawnTimer > 0) | |
| args.Player.TPlayer.dead = true; |
TShockAPI/GetDataHandlers.cs
Outdated
| NetMessage.TrySendData(139, args.Player.Index, -1, null, args.Player.Index, flag11.ToInt()); | ||
|
|
||
| NetMessage.TrySendData(129, args.Player.Index); |
There was a problem hiding this comment.
Magic packet-type numbers
The raw numeric literals 139 and 129 are used in calls to NetMessage.TrySendData. These are opaque to anyone not familiar with the Terraria protocol and will silently break if Terraria ever renumbers its packet types. The rest of TShock casts PacketTypes enum members (e.g. (int)PacketTypes.PlayerSpawn) instead of hard-coding integers.
If these packet types are missing from the PacketTypes enum, consider adding them; otherwise, reference the existing named constants to keep the code consistent and self-documenting.
- readd missing assignment of data
This is a redo of #3237 without any conventional commits this time.
OnSecondUpdateto enforce current pvp mode