Skip to content

Group friendly fire: cover explosions (2/4, part of #277) - #302

Merged
Zaldaryon merged 1 commit into
feat/issue-277-ff-verify-docfrom
feat/issue-277-ff-explosions
Sep 8, 2026
Merged

Zaldaryon merged 1 commit into
feat/issue-277-ff-verify-docfrom
feat/issue-277-ff-explosions

Conversation

@Zaldaryon

Copy link
Copy Markdown
Contributor

Summary

Second of four stacked follow-ups to #300. Extends the group friendly fire toggle to explosions, the biggest gap #300's body called out.

Base branch is feat/issue-277-ff-verify-doc (PR 1/4). The stack rebases onto indev once #300 and PR 1 land.

Change

ServerMain.CreateExplosion already receives ignitedByPlayerUid: BEBomb records who lit a bomb and passes it down through chain reactions (OnBlockExploded). It just never reaches the damage path. This resolves the igniter once at the top of the blast and, while the toggle is off, drops the igniter's group mates from the hurt list.

  • patches/VintagestoryLib/Vintagestory.Server/ServerMain.cs.patch: one new hunk in CreateExplosion. The filter is in the GetEntitiesAround predicate, so an excluded player is skipped by both the particle-intersection loop and the damage loop. The rest of the patch diff is +N line-offset shifts on the hunks after the insertion point.
  • sources/VintagestoryLib/Vintagestory.Server/StratumFriendlyFireConfig.cs: the "not covered: explosions" comment becomes the real rule.

The igniter still takes damage from their own blast, matching the melee != this rule. Blocks are still destroyed: that is land-claim territory (BEBomb.HasPermissionToUse already gates it), not friendly fire.

Not setting the igniter as the explosion DamageSource.CauseEntity is deliberate. GetDeathMessage checks GetCauseEntity() first, so that would replace the vanilla "was blown up" death message with "killed by X" for every server. It would also newly run explosions through the AllowPvP / attackplayers gate.

Gates

  • Two-pass build green, 4 pre-existing NU1904, none on ServerMain.cs.
  • bash scripts/smoke-test.sh: PASS ... 13 console command(s) verified.
  • scripts/extract-patches.sh: only ServerMain.cs.patch changes. The committed copy of that patch is not in canonical git diff form, so a plain re-extract rewrites unrelated hunks; this PR carries the minimal hand-spliced form (new hunk plus offset bumps) that applies identically.
  • Private Atlas suite: Explosions_skip_the_igniters_group_mates is written but needs two connected players, so it is blocked by the same 1.22.7 synthetic-join gap as Stack multiple role prefixes on one player, ordered by Priority #274's suite. The CreateExplosion signature and the igniter-uid plumbing are exercised by the build.

Limitations

  • An explosion with no known igniter (environmental, a mod that does not thread a placer) is unchanged: there is no attacker to compare against.

Type

  • Bug fix
  • Performance
  • New feature
  • Refactor or cleanup
  • Docs or build

Checklist

  • scripts/extract-patches.sh ran clean (only ServerMain.cs.patch, minimal form).
  • dotnet build VintageStory.slnx -c Release -p:EmbedPatchedFiles=true is green.
  • Every vanilla edit has a // Stratum marker.
  • No vanilla source committed.
  • Tested on a real server start, not just compilation.

Related issues

Part of #277

CreateExplosion already receives the igniting player's uid: BEBomb
records who lit a bomb and passes it down through chain reactions. It
just never reaches the damage path. Resolve it once at the top of the
blast and drop the igniter's group mates from the hurt list while the
toggle is off.

Filtering happens in the GetEntitiesAround predicate, so an excluded
player is skipped by both the particle-intersection loop and the damage
loop. The igniter still takes damage from their own blast, matching the
melee rule. Blocks are still destroyed: that is land-claim territory,
not friendly fire.

The igniter is not put in the DamageSource's CauseEntity on purpose.
That would rewrite the vanilla explosion death message (GetDeathMessage
checks GetCauseEntity first) and newly subject explosions to the
AllowPvP / attackplayers gate.

Part of #277

@Pixnop Pixnop left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call filtering inside the GetEntitiesAround predicate rather than stuffing the igniter into DamageSource.CauseEntity. I applied the base and head copies of ServerMain.cs.patch against .baseline and diffed the two results: exactly the one hunk in CreateExplosion, nothing else moved, so the offset-only claim holds. Skipping the entity there drops knockback too, which matches what the page promises for melee, and leaving CauseEntity alone keeps the vanilla death message and stays clear of the AllowPvP gate.

One gap the Limitations section does not name. PlayerByUid reads PlayersByUid, which is cleared in SaveGame.Init and only refilled on join. BEBomb persists lit, RemainingSeconds and ignitedByPlayerUid, so a bomb lit before a restart can go off afterwards with no resolvable igniter: stratumIgniter is null and a group mate takes the full blast with the toggle off. PlayerDataManager.GetPlayerDataByUid gives you the memberships offline, and #301 already carries the SharesGroup(Dictionary, Dictionary) overload for exactly that. Three lines, or a Limitations bullet, your call.

docs/commands/friendlyfire.md:120 still lists ShouldReceiveDamage as the only blocking point; CreateExplosion is now a second one.

Approving. On the two-client run, see my note on #300: the join gap is our first-packet gate, not 1.22.7.

@Zaldaryon
Zaldaryon merged commit 1215c26 into feat/issue-277-ff-verify-doc Sep 8, 2026
3 checks passed
@Zaldaryon
Zaldaryon deleted the feat/issue-277-ff-explosions branch September 8, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants