This commit does what official servers do:
- despawn the PlayerInfo if someone disconnects while in the lobby
- despawn all PlayerInfos at the end of a game when the EndGame screen
is shown. At this point a lot of other netobjects are destroyed as well,
with the PlayerInfos generally done first.
Looks like Innersloth added this but hasn't actually used this. Weird..
When sent it makes the new host perform a full rejoin, which gums up
Impostor's spawning logic. Fixing that causes the client to gum itself
up. Sigh.
After some testing it seems like host migration still works fine, so
this investigation wasn't needed. Committing for posterity.
Co-Authored-By: js6pak <me@6pak.dev>
In 2024.6.18 Innersloth changed the storage location of the PlayerName
from PlayerInfo to PlayerOutfit. If we don't set the PlayerName, we'll
send an incomplete PlayerInfo to new players, so new players are unable
to stay connected as they will not receive complete PlayerInfo objects
before a timeout in the client activates.
Because we publish PlayerName in the API, we can't completely remove
the PlayerName field from PlayerInfo. We also use it internally in a few
places, so I don't this is worth removing.
As tasks used to be part of the GameData, 2024.6.18 has moved them to
the PlayerInfo. Because they are now called on the PlayerInfo of the
correct player, the playerId field in the RPC is no longer necessary.
2024.6.18 adds a NetId field *in front* of the existing fields to help link back to the PlayerInfo. We don't actually need this NetId and assume it's called on the correct PlayerControl, so we ignore it.
In 2024.6.18 Innersloth promoted PlayerInfo to its own network object, and gave it to the server. InnerGameData is now a container that holds these players. This commit implements the changes necessary to handle these separate PlayerInfo network objects.
To prevent excessive modifications in the codebase, which is prone to
issues if a callsite is missed, automatically do this using properties.
Keep the access modifiers intact for now.
I'm seeing multiple warnings in my server log about forbidden scene
changes. Unfortunately this warning does not include the actual scene
that was triggering the issue, which makes diagnosis/remediation difficult.
Additionally change this logging call to use names suitable for
structured logging.
The default ListenIp for the base game server has been set to 0.0.0.0 in
config.json for as long as I remember, and a different value is only
sporadically used. I remember a case where someone was fancy with Split
DNS. 0 is better as a default than localhost, so change the code
accordingly to aligh with config.json
Fixes CVE-2024-30105 (High 7.5/10)
https://github.com/advisories/GHSA-hh2w-p6rv-4g7w
Impostor doesn't use the affected
JsonSerializer.DeserializeAsyncEnumerable method as it doesn't accept
JSON formatted payloads, but the NU1903 warning is shown on all builds,
leading to warning fatigue.
Previously Impostor liked to kill exiled players server side to raise an
event. This is quite early, as the host will SetRole them to a ghost
role later.
However as PlayerInfo is server-owned by default in 2024.6.18, it starts
killing players client side. This caused meetings to immediately
conclude if the final impostor was voted out, ruining the cutscene.
So this commit makes Impostor wait for hosts to actually kill the player
using SetRole. Do set the LastDeathReason property though for players
using the API.
This item is only used in a LogTrace call, so it seems excessive to kick
a player on servers just for a log statement
Co-Authored-By: js6pak <me@6pak.dev>
There are various bugs in the 2024.6.18 implementation of host-authoritive
multiplayer such that I can't recommend players to use it. Fixing these
issues on the server side is impossible, and I can't smell remotely if
clients have applied the necessary fixes. The currently known bugs
include at least:
- Unable to join more than 8 players in a room
- Unable for new players to join if host switched from host authoritive
to server authoritive
- Host is unable to kill if it is in a host authoritive game while it
thinks it is in server authoritive mode
If Innersloth fixes this mode in future game patches, this option may be
reconsidered.
Some people were confused by config-full.json, thinking that this file
should be edited too. This is not the case and the values in this file
don't apply as it was only meant as an example, so rename the file to
make that more clear.
Also update this file to add the options from the Modular Anticheat
Currently, Impostor will show an "Client is in an invalid state."
message if a player tries to join a match where the host or the joining
player is using a version unknown to Impostor.
This message confused a *lot* of people, so this PR changes the API such
that if the version is not registered, the version itself is put in a
compatibility group and compared, assuming no other game versions are
compatible with it. This works fine in most cases, as Among Us network
versions generally increase over time.
Failure on 2222.2.2 (which is ancient at this point, so likely no longer
used) and future cases where Innersloth messes up (which is unlikely) is
an acceptable consequence to me.
Previously Impostor would just throw when a method was called on a
GameManager, but this caused issues with client mods that did just this,
even through vanilla never calls an RPC on GameManager.
This commit changes that throw statement to pass the exception to the
custom message handler/anticheat instead, which is also how it works for
the other NetObjects
When a player is kicked or banned from a game, the client is expected to
disconnect in response. When they decide not to *or* the disconnect
packet is lost, Impostor just silently disposes of the connection.
This does not remove them from ClientManager, which is how I tracked
this bug down.
By sending them a proper disconnect message, clients should have
received *a* disconnection message before dropping their connection.
Future work should split this entire method in removing players from a
game and processing kick/bans because the latter feature is not relevant
for other callers of this method.