Commit Graph
81 Commits
Author SHA1 Message Date
MrBruh 8488a161eb Fix the text chat's review findings: no | in lines, case-blind mutes, wrapped lines, per-view and hidden chat, stream-only host messages, no chat in browser-joined public games (#399) 2026-10-18 19:33:08 +13:00
Jonas VolmanandClaude Opus 5.5 7abd376b85 Mute a player's voice and text chat from the scoreboard
A player's scoreboard menu (right-click, then the player) had Mute voice,
this machine's own choice. It is now Mute voice and chat: this machine
plays none of their voice and shows none of their lines, and tells no one.
It is offered whether or not voice chat is on.

The host's menu adds Mute for everyone / Unmute for everyone. It is the
chat's /mute for 20 minutes (every machine told "Milenko muted for 20
minutes"), and it now silences the player's voice too: the host relays
none of a muted player's machine's voice (voice_host_relay), as it relays
none of their lines. /mute from the chat mutes their voice the same way.

debug.network_test_chat now also has the host mute the last player for
everyone (network_chat_host_mute, as its scoreboard does) and unmute them,
and the last player's machine mute the host's for itself. On three Linux
machines over system link, with debug.voice_test's tone as open mic:
- the host's mute: no machine showed the player's line, they alone were
  told the minutes left, and the host and the other client stopped hearing
  their voice until the unmute (one second heard at the edge);
- the client's own mute: only that machine stopped showing the host's lines
  and hearing the host's voice.
CI's Linux test step passes (484, 6 skipped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:50:59 -07:00
Jonas VolmanandClaude Opus 5.5 e6d1e09bd7 Let the host turn the text chat off and refuse links, and players hide it
The host's TEXT CHAT row (Server Setup > Teamplay Options; in co-op, Voice
and Voting; network.text_chat) is ON (the default: lines with links are
refused), WITH LINKS or OFF: one row, as Teamplay Options has room for one
more. A game listed in the server browser (p2p_hosting_listed: a public
internet game) never has the text chat; a private game, joined by its
invite, and a LAN game have it as chosen.

The host sends its settings to every client in a new message,
_distributed_message_chat_config (89, one byte of flags), as they change
and every 3 seconds. A client without them, as from a host without the
chat, has the chat off. Pressing T where it is off says "Text chat is off
in this game". A line the settings refuse is refused on the sender's
machine and again by the host, whatever the client knew, which tells the
sender why: a changed build gets no further. Older builds drop the new
kind, so the network version stays 29.

Links are found by chat_text_has_link: a scheme, "www.", four numbers and
three dots, or a name and a common top-level domain ("discord.gg/x",
"example.com"), with the dots also written "(dot)", "[dot]", "(.)" or "[.]";
"1.5", "e.g.", "U.S.A" and "wait.comrades" are not links.

TEXT CHAT on Settings > Audio > Voice and Text Chat (display.text_chat)
HIDEs the chat for purists and streamers: no lines, and T and Y open
nothing. /mute's minutes are 20 when none are given.

debug.network_test_chat now also has each machine say a line with a link
(a client's sent past its own check, network_chat_say_unchecked, for the
host to refuse), then the host turns the chat off and on again around one
more line each. On three Linux machines over system link: every machine
showed "Links aren't allowed in this game" and "Text chat is off in this
game" once, the clients' from the host, and no refused line reached anyone.
The settings screens were drawn and the TEXT CHAT row's help follows its
choice. The harness gains four cases and six negative controls (55 pass);
CI's Linux test step passes (484, 6 skipped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:39:29 -07:00
Jonas VolmanandClaude Opus 5.5 da38822634 Re-land the in-game text chat (revert #397)
This reverts 4ac609f0, the revert of #395, so the chat is back as it was
merged: T, Y and Tab, team and vehicle lines, the host's /mute, the
VOICE AND TEXT CHAT settings page and the Android placement.

The one conflict is source/text/draw_string.c, where #395's streamer mode
and testing's (90dd65ca, text_filter.c) both hook the drawn text; testing's
hook is kept. #395's own filter (chat_filter.c, game.streamer_mode) is left
in place, unhooked, for the next commit to take out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:44:03 -07:00
MrBruh 4ac609f0df Revert "Add an in-game text chat for network games" 2026-10-18 15:03:39 +13:00
Jonas VolmanandClaude Opus 5.5 75b2393ccf Merge testing into ingame-chat
testing's SOUND PROCESSING page and the chat's VOICE AND TEXT CHAT page
both split rows off Audio Setup in tools/port_settings.py. Both are kept,
as two category rows, sound processing first. The settings screens and
menus.json are regenerated from it, so they match testing's apart from the
chat's page, its row on Audio Setup and Controls Setup's COMMUNICATION
group.

Checked after the merge: the Linux debug build, the network format check,
the CI Linux test step (467 passed, 6 skipped), and the three-machine
system-link chat test, /mute and /unmute included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:37:12 -07:00
Jonas VolmanandClaude Opus 5.5 8592780212 Let the host mute a player's text chat with /mute
The host types "/mute <player> [minutes]" in the chat (5 minutes when it
gives none, 1440 at most), or "/unmute <player>". The player is found as
the console's kick finds one: the whole name in either case, else the one
player whose name begins with what was typed; none, or more than one, is
said to the host alone. Every machine is told "Milenko muted for 5
minutes" and "Milenko unmuted", as a notice in the chat: a down line with
the new _chat_line_notice_bit, its text alone, drawn in a pale gold
(white in the white style).

The host keeps a mute by the player's name in ASCII, so one who leaves and
joins again under it is still muted, and its minutes by its own clock. It
drops a muted player's lines as they come up and tells that machine alone
"You are muted for N more minutes". The mute ends by itself. A client's
/mute is shown "Only the host can mute players" and never sent, and the
host takes a line that came up as a line, never as a command. The wire
format and the network version (29) are unchanged.

debug.network_test_chat now has the host mute the last player for a
minute, each machine say a line, the host unmute them and each say
another. On three Linux machines over system link the muted player's line
reached no one, they alone got the minutes left, every machine showed the
mute and the unmute, and the clients' own /mute was refused. A drawn
client showed the notices in the chat. The harness gains ten cases and
eleven negative controls for the command's parsing, the name match and
the mute's time (412 pass).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:02:07 -07:00
Jonas VolmanandClaude Opus 5.5 0ca693e681 Let a chat line go to everyone, the team or the vehicle, by Tab
The PC version's chat could talk to everyone, the team or the vehicle.
While a line is typed, Tab now turns it to each in turn ("Say:", "Say to
team:", "Say to vehicle:"), as T and Y still start a line to everyone and
to the team. A vehicle's line goes to the players riding in the vehicle
the sender rides in: the host finds each player's outermost parent object
(a unit in a seat is its vehicle's child), so any map's vehicles count,
Custom Edition maps' too, and a sender on foot sees their line alone. The
host now always sends a line back to its sender's machine. The channel is
a second bit of the line's flags, so the wire format is unchanged.

debug.network_test_chat has the host seat the last two players in one
vehicle and every machine say a line to it.

Checked: tools/harness/tests/test_chat_logic.py (who hears a vehicle's
line, the channel through the flags, with negative controls); three
machines on system link, the two clients seated in one Warthog seeing
each other's vehicle lines and the host's, on foot, seeing only its own;
a host on Xvfb turning a line to the vehicle with Tab, and typing a line of
f's without meleeing; the CI Linux test step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:02:07 -07:00
Jonas VolmanandClaude Opus 5.5 3efe79a38d Add a text chat to network games
Network games had voice chat but no way to type to the other players, as
the PC version's chat did. T (controls.chat) types a line to everyone and
Y (controls.team_chat) one to the team; Enter sends it, Escape cancels it.
The lines are drawn above the motion sensor with the HUD's font: the
player's name in their team's colour (blue without teams), then the text
in a pale blue, and fade after ten seconds (port/linux/game/network_chat.c).

A client sends its line to the host (_distributed_message_chat_up), which
takes it only from the client's own stream and one of that machine's
players, five at once and one each 1.5 seconds after, its text cut to 63
characters of printable ASCII, and sends it on to the machines that hear
it (_distributed_message_chat_down): all, or a team's line those with a
player of the team. Older builds drop both kinds as unknown, so the
network version stays 29, as for the vote kick; network_format.txt
records the two kinds.

While a line is typed the keyboard drives no player, as with the console
(xinput_sdl.c), nor voice chat's push to talk or the debug keys. Controls
Setup gets a COMMUNICATION group with PUSH TO TALK, CHAT and TEAM CHAT
(the controls screen's spinner strings changed by hand to what
port_settings.py writes: ce_menus.py needs the PC version's tags).

Checked: tools/harness/tests/test_chat_logic.py (the text's cleaning, the
host's rate, who hears a team's line, the fade, with negative controls);
the CI Linux test step; three machines on system link with
debug.network_test_chat (new), every machine showing the lines to all in
one order and a team's line only on its team's machines; and a host drawn
on Xvfb with lines typed on its keyboard through xdotool (sent on Enter,
not on Escape, the player still while typing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:02:07 -07:00
justinfilip 7cf24ae589 Stop carrying an unsteered vehicle once the host says it has stopped. 2026-10-15 12:35:57 -05:00
justinfilip e5e97c0526 Carry a vehicle no player drives along the host's positions. 2026-10-15 11:08:46 -05:00
MrBruh 3e0ba55111 Keep Custom Edition maps' own names: the version goes in the game record
A game's level name is the map's own (custom_maps\hugeass), so no screen or
server browser listing shows a hash, and the game record's map version is
the map's hash's first 32 bits, which a client finds its file by. Maps are
no longer renamed; a download beside another version of its name is named
<name>_<hash>.map and listed as "(2)"; maps the last build renamed get
their names back. Network version 29: the level name and the map version
mean something else.
2026-10-14 23:08:39 +13:00
MrBruh 6d64abdb42 Fix map sharing restart overflow and harden map validation 2026-10-13 07:43:41 +13:00
MrBruh 52e33a391e Harden map sharing and Custom Edition map loading 2026-10-12 22:26:25 +13:00
MrBruh c6a2f9004b Record the map sharing messages and the sizes of the wire format's arrays (#253)
The record read only network_*.c, so the map sharing messages in
map_share.c went unrecorded, and it took each struct sent whole by the text
of its declaration, so a change to a constant that sizes one of its arrays
(MAXIMUM_ENTRIES_PER_MESSAGE, DISTRIBUTED_INPUT_HISTORY and the others)
changed the message without failing the check. It now reads map_share*.c
too, and records each such constant by its definition, following the names
that uses, and the DISTRIBUTED_ sizes in the enum of no name (a unit state's
and a relayed action's least and largest sizes). A size with no definition
found fails the check rather than passing it.

Checked: the items only grow (35 added, none changed), so version 28 is
recorded again; changing MAXIMUM_ENTRIES_PER_MESSAGE in network_actors.c
fails the check as a change.
2026-10-12 21:07:30 +13:00
MrBruh 785e865a87 Merge pull request #302 from hkmodd/fix/limp-body-corrections 2026-10-12 20:46:49 +13:00
MrBruh 5d9081e91e Merge pull request #253 from addisonbair/network-format
# Conflicts:
#	port/linux/NETCODE.md
2026-10-12 20:35:16 +13:00
MrBruh 5a7c655a60 Testing branch review fixes
Network version 28: the host now holds a downloading machine's players out
of the game, and keeps a multiplayer map's first scripted BSP. Dynamic lights
and the flashlight stay on past the Xbox limits, and a second weapon picked
up while firing is readied. Machines of version 27 would disagree on these.

- A large co-op game's respawn fallback no longer picks a teammate who is in
  the air, outside the BSP, or riding an AI vehicle.
- A machine still downloading the map times out when it goes silent.
- Held players join through the late-join queue, so they get the same checks.
  A machine with no held players is started instead of being refused.
- The co-op teleport uses world positions, which are right for seated players.
- Overshield drain no longer cuts off a hit's flash, and hits over 0.02 flash.
- The menu XML is the generator's (Custom Edition's layout) again.
- port: markers on two new declarations.

Checked: ninja linux, android and web build; tools/harness,
test_touch_menu and test_web_build pass.
2026-10-12 20:01:49 +13:00
hkmoddandClaude Opus 5.5 e791cf9ae0 Bodies the host moves are no longer drawn floating or in walls on clients.
In large games, bodies on clients were drawn twisted, hanging in the air,
piled up or inside walls. There were two causes, both in how a client
takes the host's object states.

A body that comes to rest lies limp (bipeds.c): its nodes stay where they
are in the world and are no longer recomputed from the object. The game
stops this when something pushes the body (biped_accelerate). On a client,
that push comes from the damage aftermath, which is sent only to the
machines that see the body's player (network_damage.c). It never comes for
older bodies (a player's dead_unit_index is their latest) or for world
damage. When the host then moves the body, the client's copy moves with
the host's corrections and its own physics, but its pose stays where it
came to rest. A client now stops a body lying limp before it puts the body
somewhere and whenever the host says it is moving. units.c makes it lie
limp again, every tick, once it is at rest on the ground.

A client also takes the host's word that a body is at rest while its own
copy is still in the air, a little behind. Rest stops its physics, and
only its physics clears airborne, so the body kept the pose of its fall
(its root node about 0.36 above the ground) and never lay limp. A client
now clears airborne on a body the host has at rest: the host's is on the
ground, because it comes to rest only when it is not airborne.

Nothing sent changes, so the network version stays the same.

Checked:
- New harness test limp_body_moves takes the code from network_objects.c
  and bipeds.c. Its cases are pushed, landed, moved, blended and living.
  Each of its 5 negative controls (each line of the fix taken out) fails
  its case.
- The whole harness, run natively on Windows: 234 passed, and the
  failures are the environmental ones main also has on this machine.
- The Windows build has no warnings.
- local system link games on one machine (debug.network_test, bots and a
  kill every 2 seconds), with temporary instrumentation: each machine logs
  its bodies every second, and the host sets off a frag grenade's
  explosion under up to 4 resting bodies every 5 seconds. Result: bodies
  at rest drawn more than 0.15 from where the host draws them:
    4 machines, 120 s:  195 of 573 pairs before, 0 of 1221 after;
    32 machines, 150 s: 19479 of 96439 pairs before (20%), 157 of 71237
      after (0.2%), counting only pairs where the host and the client
      agree on the body's position. The rest are bodies still in their
      dying animation, a few ticks apart, at the same rate as on the
      host.
  Copies at rest but left airborne: 195 samples before and 0 after on 4
  machines, 10718 before and 0 after on 32.
- Not checked here: the Android and web builds (they don't build on this
  Windows machine), Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:46:27 +02:00
Addison Bair fab098a7bd Record the wire format of the network version
AGENTS.md asks for HALO_PORT_NETWORK_VERSION to be raised with any change
to what the machines send each other; nothing checked it, and #95, #99 and
and 18 caught up after them).

tools/network_format.py takes the wire format from the sources: the game's
message numbers, sizes and fields, the distributed netcode's message kinds
and flag bits, its DISTRIBUTED_ constants and the structs it sends whole, as
hashes. port/linux/network_format.txt records them for the version, and
test_linux_port.py fails when the sources differ: an item changed or removed
asks for the version to be raised (--record refuses it until then), an item
added (a new kind or bit, which older builds may ignore) only to be recorded.
It also fails when NETCODE.md says nothing of the version.

Checked by recording each merge's parent and checking the merge: #95, #99
and #106 fail as changed structs; #91, votes to kick, voice chat and the
integrated light bits as additions; #101, which raised the version, passes
once recorded. A comment, or a struct the netcode keeps to itself, changes
nothing.
2026-10-12 01:09:55 +00:00
Addison Bair 9180bd37c8 NETCODE.md: network versions 22 to 25
The versions' list stopped at 21. 22 to 25 as their commits give them:
Custom Edition maps named custom_maps\<name> (4e8ed2f1), their blocks kept
past the Xbox tools' limits (34e2d4fd), the gametype's PC vehicle set
(11117d7c) and a unit's integrated light in its object state (6b55f5cc).
2026-10-12 01:09:44 +00:00
MrBruh a2aad18f65 Custom Edition map sharing
Hosts send players who join without the game's Custom Edition map the map
and the resource maps it needs; the other players help, torrent-style.
Network version 27: new map sharing messages, and players of an internet
game now reach each other.
2026-10-12 08:07:14 +13:00
MrBruh a3277d94dc Fewer draws and GL calls
Decals and light volumes batched, web index and vertex array caches, no FULL_ES3. Prisoner, 15 players: 115 to 172 FPS (A/B).
2026-10-11 22:28:34 +13:00
MrBruh 6399ed9d4a Text drawn a string at a time, web immediate draws packed
Scoreboard text on the web: 1.41 to 0.41 ms a frame. The network test's browse joins the fullest game that is not co-op.
2026-10-11 16:16:35 +13:00
MrBruh 6dc423fdbf Internet play with browsers
Network version 26: signalling says each machine's WebRTC.
2026-10-11 12:46:28 +13:00
Luke 8dad0c759a Co-op elevators: the host takes a riding client's player only across, so they no longer fall through going up 2026-10-10 17:57:19 +11:00
MrBruh f30db75e49 Merge pull request #211 from startupfoundry/grenade-throw-sync
Network: a client no longer throws grenades it doesn't have right after spawning
2026-10-09 18:46:28 +13:00
MrBruh 86ddd22b29 Merge pull request #210 from startupfoundry/teleport-remote-player
Network: a player who used a teleporter no longer appears stuck on the pad they left
2026-10-09 18:46:28 +13:00
MrBruh cbc8da75f1 Merge pull request #209 from startupfoundry/hit-report-rejections
Network: a client's grenade shock waves are no longer refused (about half its grenade damage)
2026-10-09 18:46:28 +13:00
MrBruh f97b33391b Voice chat
Opus voice chat (port/third_party/opus 1.5.2, port/linux/src/voice_audio.c, port/linux/game/network_voice.c), relayed by the host, in the lobby too. The host decides in Server Setup > Teamplay Options: lobby voice (on by default), the game's mode (off, team near, anyone near, team, team and enemies near: the default), the near distance, and the quality, 8 to 64 kbps (24). Each player picks push to talk (V), open mic or off, the voices' volume, and the output and input devices in Settings > Audio, and mutes others from the scoreboard's menu. A speaker icon marks who talks in the lobby, on the scoreboard and in a list in game. The host takes a machine's frames only with the key it gave it over its stream, within the quality's size, 50 a second and 8 talkers at once, and sends voices only to machines that asked for them, so the network version stays.
2026-10-09 14:20:57 +13:00
MrBruh 3b20ef879a Votes to kick
Any player of a network game can start a vote to kick another, on any team, by picking their name on the scoreboard (right-click while it is open frees the mouse) or with the console's votekick; the host's own scoreboard also has Kick and Ban (Ban picked twice). The host alone counts (port/linux/game/network_votekick.c): votes only from each voter's stream, one per real address and again per hardware id (which only removes votes), time played on the host before starting (network.votekick_minutes) and voting, more than half of everyone with the target counted and at least two, one vote at a time with cooldowns for a failed vote's starter and target, and a passed vote keeps the player out for network.votekick_ban_minutes. Builds without it drop the new messages, so the network version stays.
2026-10-09 10:07:51 +13:00
Paul Hontz 1f87b4ff63 A client's copy of a unit carries no grenades until the host says
A client makes its copy of a unit the host spawns with object_new, and unit_new gives it the unit tag's grenades (a cyborg's four frags), where the host's game engine gives a player's unit the game's own (none on wizard slayer). The host's inventory, which corrects them, comes a tick or two later, so a client's player spawning with the throw button held began a throw with a grenade its unit did not have: the client saw it thrown and go off, and reported its hits, while the host's copy, with no grenade, never threw, and refused every report as damage the player could not deal. A client's copy of a host's unit now starts with no grenades, and takes the host's when its inventory comes.

In the network test (1v1 slayer on wizard, staged hits and the bots' own fire and grenades, with #209's shock wave fix in both builds), with no added latency over 8 games the client threw 41 grenades to the host copy's 39, and the host refused all 5 reports of the 2 explosions it never saw thrown (11 of 2959 reports refused in all); now 55 throws to 55, no explosion refused for want of a throw, and 2 of 2749 reports refused. At 50 ms a receiver (8 games before: 66 throws to 64, 7 reports of 2 explosions refused; 4 games after) 10 throws to 10 and none of 1396 reports refused. Every unseen throw was in the client's first tick or two alive, with four grenades there and none on the host. Kills and deaths stay balanced.
2026-10-08 13:29:28 -04:00
Paul Hontz 22fe5628b6 A remote player the host teleported stays where they landed
When the host's teleporter sent a player, a client's copy that had not stepped on the pad itself was put at the far end by the host's word, landing on the teleporter there with no note of it (the game's own teleporter notes the one it lands a player on). The client's teleporter sent it straight back, every tick the host's word put it there, until the player stepped half a world unit off: the copy stood on the pad left behind, 24 world units off, for 6 to 9 ticks after most such teleports and for as long as the player stood still (up to 143 ticks in earlier runs), and the client's hits on them there were refused. A player's unit the host's word moves further than a step at once is now on the teleporter it lands on, as one the teleporter sends is.

1v1 slayer on Wizard, two bots shooting, 16 runs of 12 minutes each way at 0 and 50 ms: the client's teleporter sending the host's player back 85 ticks in 18 episodes before, none after; the copy over 5 world units from the host's for 3 ticks or more 12 times (82 ticks, up to 9) before, none after. Hits refused 3.7% before and 4.0% after, the view error (p50 0.03, p95 0.08 world units) the same.
2026-10-08 13:23:09 -04:00
Paul Hontz 792711ca57 A grenade's shock wave is dealt with its explosion
A frag grenade's explosion deals two damage effects, its explosion and its shock wave (a plasma grenade's too), and a client reports each hit of each. The host took the first of them against the throw it had seen and spent the throw; the explosion's other hits came with it only when they were of the same damage, so every hit of the other damage found no throw left and was refused as damage the player could not deal. An explosion of the player's this tick is now one of the grenade, of any damage its tags deal, so its other damage takes no throw of its own (and is still paid for at the grenade's rate).

In the network test (1v1 slayer on wizard, staged hits and the bots' own fire and grenades, 8 games each) the host refused 4.4% of the client's reports with no added latency (134 of 3072, 104 of them a grenade's other damage) and 4.9% at a 100 ms round trip (153 of 3107); now 0.4% (11 of 2959) and 0.8% (25 of 2986). What it still refuses it should: grenades it never saw thrown, targets gone before the report came, and hits on a player the client still had at the teleporter they had left.
2026-10-08 11:42:32 -04:00
xshxdex98 6b4200e189 Grow a co-op squad to 8 times its size at most, per player
EXTRA ENEMIES' PER PLAYER grew each squad by its size for every player past
the first at 100%, held back only by the actor pool: in a game of 65
players each squad of six grunts had about 378 more. The host's ticks
stalled (every client froze, then its players jumped), the clients ran out
of objects (enemies the host had and they had not, which killed players
unseen) and past their renderer's limits, and the enemies with no free
ground left were placed off the map, where the clients' copies fell. A
squad now grows to COOP_ENEMIES_MAXIMUM_GROWTH (8) times its size at most.
2026-10-07 14:59:03 -05:00
MrBruh 07302a866f Co-op-only garbage throttle, network version 21 2026-10-07 13:43:50 +13:00
MrBruh 93846725e5 Merge PR #134 2026-10-07 13:38:30 +13:00
MrBruh 633492e4d0 Merge PR #133 2026-10-07 13:38:30 +13:00
MrBruh e4c83398f2 Merge PR #132 2026-10-07 13:38:30 +13:00
MrBruh 54abd34493 Third hardening round 2026-10-07 13:20:54 +13:00
xshxdex98 f20689db44 Co-op: only the host's crossing switches the BSP, and brings the team along
Any player crossing a loading zone used to pull the whole team to them, with a two-thirds vote to go back to a BSP already visited: one player running ahead or doubling back teleported everyone, and teams ended up several BSPs back. Now only the host's players switch the BSP (anyone's while none of the host's are alive), the team is brought to the host who crossed (not to a client waiting on the trigger), the stranded and the respawning come back beside the host first, and a client standing on a loading zone is told it waits for the host. Clients still never switch on their own, and the host still waits for every machine to load the new BSP.
2026-10-06 15:55:44 -05:00
xshxdex98 4d35b9cb10 Netcode: killing blows reach every client, and a player's body dies as the host's did
The killing blow went once, unreliably, while the units' states, sent every tick, killed a client's copy of a player the moment they said dead, so a late or lost blow left the body to die without its death animation, push or kill message. The host now also sends each killing blow reliably (a client replays one blow of a unit only; the reliable copy is not dropped as overtaken by the damage sent since), and a client waits half a second for it before a player's unit dies without it, as an actor's already did.
2026-10-06 15:55:43 -05:00
xshxdex98 9d8e471f78 Netcode: a body come to rest reaches every client, and none hangs in the air
The host sent an object coming to rest once, unreliably. One lost left a falling body hanging on a client until its turn in the round of objects at rest, four a tick: in a large game, many seconds. It is now sent three times over half a second. A client also takes the host's word on rest from every state, not only from one far enough off to move its copy, so a copy left at rest while the host's fell no longer hangs; a vehicle the client drives takes it only from a correction, as before, so it is not stopped as it sets off.
2026-10-06 15:55:43 -05:00
MrBruh 76addf661f Second hardening round 2026-10-07 00:01:28 +13:00
MrBruh 6112dcfc5a Password-protected public lobbies 2026-10-06 17:51:54 +13:00
MrBruh 62fa7e13ef Co-op player collisions option 2026-10-06 17:03:38 +13:00
MrBruh 5a35ea2b20 Network version 18
Fixups for #99 and #112: the version raised for the object message's
shader permutation, NETCODE.md brought up to date, a networked glass
break's sound placed where it broke, a frame scratch pool that runs out
logged once, and the new comments marked as the port's.
2026-10-06 13:39:26 +13:00
MrBruh 761210d405 Harden map and network input 2026-10-06 13:26:43 +13:00
MrBruh 2b0327bc80 Network version 17
Fixups for #102, #103 and #105-#107: the version raised for the glass,
scenery, cutscene cluster and revert messages, NETCODE.md brought up to
date, co-op's followers' object lists freed as soon as they are used, and
extra enemies that find no free ground placed on the rings they used before
rather than left out (at 32x a quarter of them were), with the places found
taken not tried again for the rest of the squad, and the way to a place
looked along level.
2026-10-06 08:59:22 +13:00
xshxdex98 b525bf8514 Network version 16
A client's input says which structure BSP it has loaded (co-op).
2026-10-05 08:09:47 -05:00