Hull no longer depends on FightSystem: plugin, world, region, ground
visibility and hidden blocks are passed in. HullRegion is the common block
box hulls work on. The generic HullHider<K> manages one hull per key and does
the block, entity and REntity tracking; FightHullHider keeps the fight
specific parts (team hulls, viewer rules, state dependent registration).
Entities are now checked against the hull with block coordinates, so entities
in the bottom layer and at the max z edge are handled correctly.
HiderCore holds the TechHider, ChunkHider and AccessPrivilegeProvider so that
FightSystem and BauSystem can both shade it. BlockIds and ProtocolUtils stay in
SpigotCore (used by AntiNocom and RFallingBlockEntity) and move to
de.steamwar.core to avoid a split package. The access widener entries the
TechHider needs are duplicated into hidercore.accesswidener; the legacy
TechHider still needs its own copies in SpigotCore.
Chunks encoded while the hull was filled as hidden contain obfuscated
blocks that become visible after initialize, and no block update is
generated for them. Reload the team's extend region for all players
that cannot see the hull.
Spectators hid HiddenBlocks in the whole arena for block updates, but
full chunk packets outside both extend regions were sent unfiltered, so
the same blocks were hidden or visible depending on the packet type.
Hidden regions are now a list: spectators hide both team extend
regions, team members the opposite one. Block checks and the per-chunk
bypass use the same regions, so everything outside the extend regions
is visible and unfiltered.
AccessPrivilegeProvider#forPlayer returns a PlayerAccess that resolves
the player's hidden region once. TechHider creates it once per outer
packet (shared across bundle sub-packets) and passes it to every
processor, so all decisions within a packet are consistent and the
region/referee lookup no longer runs per block on the netty thread.
getHiddenRegion looked the player up in FightTeam.players twice (team,
then FightPlayer) on netty threads. A concurrent reset or removePlayer
made the second lookup return null, the NPE was swallowed by the global
filter and the packet was dropped. Resolve the FightPlayer once and
derive team and canEntern from it.
Hull kept a set of affected players that was only filled by a join
listener active in the Schem states, so spectators joining earlier were
never hidden from the hull. The set was also a plain HashSet read on
netty threads, where a racing lookup meant "not hidden".
Invert it into a concurrent set of viewers (referees, own team, boarded
players); everyone else is hidden by default.
- Hull: viewer UUID set with addViewer/removeViewer/forgetViewer, a
null player counts as hidden
- Hull: entities are hidden/shown when they enter/leave the hull for all
non-viewer online players; uncovered blocks go to non-viewers
- HullHider: join/quit handled in a listener active in every state; quit
clears the viewer entry
- HullHider: TeamDeathEvent re-hides the enemy hull and resends its chunks
- FightPlayer: stop the enter countdown before firing TeamDeathEvent so
listeners see canEntern() == false
Chat is now handled entirely by VelocityCore through channels with
separate readers and writers (Global, Local/Fight, Blue/Red fight team,
Team, ServerTeam, Alert and 1:1 direct messages). Each player has a
saved default channel; messages from other channels are tagged with
the channel name, and every default change is announced.
- /global, /local, /tc, /stc, /msg and /r switch the default channel
when called without a message
- /chat <channel> switches, /chat <channel> join|leave toggles reading
(saved); moderators can join arenas by name and write with
/chat <channel> msg <text>
- '+' sends from global to local and from local/fight to the fight team
- Referees write yellow in the fight chat
- Subservers no longer receive chat; arenas get a record-only
ChatRecordPacket so replays keep their chat
- Remove the chat listeners of SpigotCore, FightSystem, MissileWars,
TowerRun and TNTLeague
Closes#460, #129