Compare commits

..
28 Commits
Author SHA1 Message Date
miniduikboot 06f4f8bf00 Gate PackedGameDataTo behind AC check 2026-05-24 20:36:02 +02:00
NikoCat233 2cb9c648f3 Add support for PackedGameDataTo 2026-05-24 20:36:02 +02:00
miniduikboot b30775c2fc Add compat version for 17.3 (#724)
* Add compat version for 17.3

* Add compat version for 17.3.1
2026-04-20 22:00:32 +02:00
miniduikboot 764c42eae3 Merge pull request #723 from miniduikboot/fix/aof-concdict
Fix race conditions in Game.Data
2026-03-30 22:30:37 +02:00
miniduikboot 4244f39640 Rename _allObjectsFast to _allObjects
Done because there is no second datastructure anymore
2026-03-27 23:32:57 +01:00
miniduikboot 069ec446cd Switch to concurrent dictionary
PR proposed in #722 doesn't solve all issues, now Nullrefs show up.

Also drop _allObjects as it's never read.
2026-03-26 23:58:45 +01:00
miniduikboot 98783e5b42 Merge pull request #717 from Impostor/feature/17.2.2
Add 17.2.2 version
2026-03-22 23:06:45 +01:00
miniduikboot fd12cd1a39 Add 17.2.2 version
Only changes are ad related, and officials allow crossplay
2026-03-17 20:18:25 +01:00
miniduikboot 139f2334a2 Merge pull request #716 from Impostor/feature/17.2-hotfix
Add 17.2 hotfix version
2026-03-04 20:31:58 +01:00
miniduikboot 60371d538c Add 17.2 hotfix version 2026-02-19 21:34:54 +01:00
miniduikboot 6e68747fe0 Merge pull request #715 from Impostor/feature/17.2
Add 17.2 version
2026-02-18 07:24:47 +01:00
miniduikboot 3736b37831 Add 17.2 version
https://www.innersloth.com/announcing-among-us-x-ace-attorney-again/
2026-02-18 07:19:36 +01:00
miniduikboot eeb85e4abc Merge pull request #712 from miniduikboot/feature/aumi-host-chat-cmds
Add support for host chat cmds
2026-02-18 07:17:58 +01:00
miniduikboot fd33a892cd Reduce warnings about +25
As Innersloth documented it in their mod info document, assume it's here
to stay, so warn about it less heavily
2026-01-27 22:41:42 +01:00
miniduikboot fbdb708941 Implement host chat commands
On January 21 Innersloth released a document that details a few new
features. One of these are host chat commands: any chat message that
starts with "/cmd" is forwarded to the host and to the host only.

Implement this feature in Impostor too for implementation parity.

For more info, see their GitHub page:
https://github.com/Innersloth-LLC/AmongUsModdingInformation
2026-01-27 22:17:03 +01:00
miniduikboot 9a60ce3d56 Merge pull request #708 from Impostor/feature/17.1
Bump compatversion to support 17.1
2026-01-27 20:38:36 +01:00
miniduikboot d7601e8057 Add another mobile-only hotfix
From their Discord:

Admin has pushed hotfix v17.1.2 for mobile players! minor changes to the ad rewards to the daily cap (subject to future change) and updated the screen to clarify when the daily cap is reset.
2025-12-11 22:20:17 +01:00
miniduikbootandNiko233 0e9454ecdf Bump compatversion to support 17.1.1
https://www.innersloth.com/ad-rewards-v17-1-1/

Thanks to Niko for reminding me about this

Co-Authored-By: Niko233 <139348239+NikoCat233@users.noreply.github.com>
2025-12-07 10:33:23 +01:00
miniduikboot ce5a491cdb Bump compatversion to support 17.1 2025-11-18 20:50:57 +01:00
miniduikboot 16c8acc849 Merge pull request #706 from NikoCat233/patch-1
Add missing comment for game version 16.1.0
2025-11-18 20:50:46 +01:00
NikoCat233 195d31cad1 Add missing comment for game version 16.1.0 2025-11-05 01:35:52 +08:00
miniduikboot 18846d3dd4 Merge pull request #705 from Impostor/feature/17.0.1
Bump to 17.0.1
2025-10-15 20:42:47 +02:00
miniduikboot eb231dc393 Bump to 17.0.1 2025-10-14 20:29:33 +02:00
miniduikboot a00b9e63d8 Merge pull request #702 from Impostor/feature/17.0.0
Add support for 17.0.0
2025-09-26 20:22:43 +02:00
miniduikboot d7e5594cf6 Run Dumposter on 17.0.0 2025-09-22 21:06:05 +02:00
miniduikboot 8ba89d9844 Add GameOptions V10
Manually added roles to RoleTypes, will clean up later
2025-09-09 20:40:07 +02:00
miniduikboot ebd7f99438 Bump to 1.10.4
No breaking changes expected
2025-09-09 20:39:31 +02:00
miniduikboot 2197434bdc Add version block for 17.0.0 2025-09-09 20:16:31 +02:00
28 changed files with 593 additions and 158 deletions

No files matched your search

+15 -14
View File
@@ -25,20 +25,21 @@ Impostor has an Http Server that is used by recent versions of Among Us to conne
Impostor has an Anticheat that makes it possible to kick cheaters from games automatically. Note that the anticheat is tuned on the vanilla version of the game, so client-side modifications could trigger the Anticheat if you're playing with them.
| Key | Default | Value |
|-------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Enabled** | `true` | Whether the anticheat should be enabled. |
| **BanIpFromGame** | `true` | When anticheat is enabled and a player is caught hacking, they will be kicked from the server. If this value is set to `true`, the player will be banned instead and will not be able to rejoin that specific game. |
| **AllowCheatingHosts** | `"Never"` | Configure whether hosts are allowed to cheat. "Never" forbids it, "Always" allows it. "IfRequested" allows hosts to cheat if they connect with the DisableServerAuthorityFlag set. |
| **EnableGameFlowChecks** | `true` | Enable checks that check if certain actions are done in the appropriate order or at the appropriate moment in the game. This includes changing cosmetics while in game or murdering too fast. |
| **EnableInvalidObjectChecks** | `true` | Enables checks that check if network objects are spawned properly. Disabling this option also implies disabling EnableRoleChecks. |
| **EnableMustBeHostChecks** | `true` | Enables checks that check if players are the host before they can do actions that require them to be host of the game. This includes starting the game and spawning objects. |
| **EnableColorLimitChecks** | `true` | Enables checks that checks if players request colors that are already in use. |
| **EnableNameLimitChecks** | `true` | Enables checks that checks if player names have a length that is possible to set using the user interface. |
| **EnableOwnershipChecks** | `true` | Enables checks that check if players are allowed to perform a certain action on themself or another player. |
| **EnableRoleChecks** | `true` | Enables checks that check if players have the correct role when performing certain role abilities like venting or murdering. |
| **EnableTargetChecks** | `true` | Enables checks that check if certain packets to everyone that should only have been sent to certain players or vice versa. This includes sending votes or network objects. |
| **ForbidProtocolExtensions** | `true` | If disabled allows players to send network packets that go beyond the network packets sent by the vanilla game. This is necessary for most mods that need all players to install it. |
| Key | Default | Value |
|-------------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Enabled** | `true` | Whether the anticheat should be enabled. |
| **BanIpFromGame** | `true` | When anticheat is enabled and a player is caught hacking, they will be kicked from the server. If this value is set to `true`, the player will be banned instead and will not be able to rejoin that specific game. |
| **AllowCheatingHosts** | `"Never"` | Configure whether hosts are allowed to cheat. "Never" forbids it, "Always" allows it. "IfRequested" allows hosts to cheat if they connect with the DisableServerAuthorityFlag set. |
| **AllowHostOnlyExtensions** | "IfRequested" | Configure whether [Host-Only extensions](https://github.com/Innersloth-LLC/AmongUsModdingInformation#host-only-mods) are allowed in all games ("Always"), +25 games only ("IfRequested") or by nobody ("Never") |
| **EnableGameFlowChecks** | `true` | Enable checks that check if certain actions are done in the appropriate order or at the appropriate moment in the game. This includes changing cosmetics while in game or murdering too fast. |
| **EnableInvalidObjectChecks** | `true` | Enables checks that check if network objects are spawned properly. Disabling this option also implies disabling EnableRoleChecks. |
| **EnableMustBeHostChecks** | `true` | Enables checks that check if players are the host before they can do actions that require them to be host of the game. This includes starting the game and spawning objects. |
| **EnableColorLimitChecks** | `true` | Enables checks that checks if players request colors that are already in use. |
| **EnableNameLimitChecks** | `true` | Enables checks that checks if player names have a length that is possible to set using the user interface. |
| **EnableOwnershipChecks** | `true` | Enables checks that check if players are allowed to perform a certain action on themself or another player. |
| **EnableRoleChecks** | `true` | Enables checks that check if players have the correct role when performing certain role abilities like venting or murdering. |
| **EnableTargetChecks** | `true` | Enables checks that check if certain packets to everyone that should only have been sent to certain players or vice versa. This includes sending votes or network objects. |
| **ForbidProtocolExtensions** | `true` | If disabled allows players to send network packets that go beyond the network packets sent by the vanilla game. This is necessary for most mods that need all players to install it. |
### Compatibility
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>11</LangVersion>
<VersionPrefix>1.10.3</VersionPrefix>
<VersionPrefix>1.10.6</VersionPrefix>
<VersionSuffix>dev</VersionSuffix>
<EnforceCodeStyleInBuild Condition="$(MSBuildProjectName)!='Hazel'">true</EnforceCodeStyleInBuild>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
+3
View File
@@ -5,6 +5,9 @@ public enum CheatCategory
/// <summary>A packet used a part of the network protocol that is unknown to Impostor, like a custom RPC.</summary>
ProtocolExtension,
/// <summary>A host-only mod extension is used outside of host-authoritive mode.</summary>
HostOnlyExtension,
/// <summary>A packet was sent at an inappropriate moment.</summary>
GameFlow,
@@ -10,6 +10,8 @@ namespace Impostor.Api.Config
public CheatingHostMode AllowCheatingHosts { get; set; } = CheatingHostMode.Never;
public CheatingHostMode AllowHostOnlyExtensions { get; set; } = CheatingHostMode.IfRequested;
public bool EnableGameFlowChecks { get; set; } = true;
public bool EnableMustBeHostChecks { get; set; } = true;
@@ -1,4 +1,4 @@
namespace Impostor.Api.Events.Player
namespace Impostor.Api.Events.Player
{
public interface IPlayerChatEvent : IPlayerEvent, IEventCancelable
{
@@ -6,5 +6,12 @@
/// Gets the message sent by the player.
/// </summary>
string Message { get; }
/// <summary>
/// Gets or sets a value indicating whether the message is sent to
/// all players (true) or only to the host (false).
/// To not send this message at all, cancel this event instead.
/// </summary>
bool SendToAllPlayers { get; set; }
}
}
@@ -5,7 +5,7 @@
"4": "PlayerControl",
"5": "MiraShipStatus",
"6": "PolusShipStatus",
"7": "ShipStatus",
"7": "SkeldShipStatus",
"8": "AirshipStatus",
"9": "HideAndSeekManager",
"10": "NormalGameManager",
@@ -1,11 +1,11 @@
{
"HumansByVote": 0,
"HumansByTask": 1,
"ImpostorByVote": 2,
"ImpostorByKill": 3,
"ImpostorBySabotage": 4,
"CrewmatesByVote": 0,
"CrewmatesByTask": 1,
"ImpostorsByVote": 2,
"ImpostorsByKill": 3,
"ImpostorsBySabotage": 4,
"ImpostorDisconnect": 5,
"HumansDisconnect": 6,
"HideAndSeek_ByTimer": 7,
"HideAndSeek_ByKills": 8
"CrewmateDisconnect": 6,
"HideAndSeek_CrewmatesByTimer": 7,
"HideAndSeek_ImpostorsByKills": 8
}
@@ -9,5 +9,7 @@
"ImpostorGhost": 7,
"Noisemaker": 8,
"Phantom": 9,
"Tracker": 10
"Tracker": 10,
"Detective": 12,
"Viper": 18
}
@@ -8,15 +8,15 @@
"SetName": 6,
"CheckColor": 7,
"SetColor": 8,
"SetHat": 9,
"SetSkin": 10,
"SetHat_Deprecated": 9,
"SetSkin_Deprecated": 10,
"ReportDeadBody": 11,
"MurderPlayer": 12,
"SendChat": 13,
"StartMeeting": 14,
"SetScanner": 15,
"SendChatNote": 16,
"SetPet": 17,
"SetPet_Deprecated": 17,
"SetStartCounter": 18,
"EnterVent": 19,
"ExitVent": 20,
@@ -33,8 +33,8 @@
"SendQuickChat": 33,
"BootFromVent": 34,
"UpdateSystem": 35,
"SetVisor": 36,
"SetNamePlate": 37,
"SetVisor_Deprecated": 36,
"SetNamePlate_Deprecated": 37,
"SetLevel": 38,
"SetHatStr": 39,
"SetSkinStr": 40,
@@ -1379,6 +1379,9 @@
"MissingGuardianEmailText": 3325,
"AprilFoolsModeToggle": 3326,
"LobbyChangeSettingNotification": 3327,
"LoadingBarLoading": 3328,
"LoadingBarGameStart": 3329,
"LoadingBarGameStartWaitingPlayers": 3330,
"ImpostorsCategory": 3350,
"RolesCategory": 3351,
"MeetingsCategory": 3352,
@@ -1405,6 +1408,10 @@
"StandardRulesPresetDescriptionHideAndSeek": 3373,
"GameModeStandardSeek": 3374,
"HostYouLabel": 3375,
"GamePresetsPopupTitle": 3376,
"GamePresetsPopupText": 3377,
"GamePresetsPopupContinue": 3378,
"GamePresetsPopupBack": 3379,
"MiningPit": 3400,
"Jungle": 3401,
"BuildSandcastle": 3402,
@@ -1492,5 +1499,129 @@
"QCLobbyClosing": 3547,
"QCChangeCosmetics": 3548,
"QCWaitingPlayers": 3549,
"QCLetsWaitPlayers": 3550
"QCLetsWaitPlayers": 3550,
"ServerLabel": 3551,
"JoinLobby": 3552,
"ChatLabel": 3553,
"ToolTipDefault": 3554,
"LevelLabel": 3555,
"NoneLowercaseLabel": 3556,
"ToolTipClassic": 3557,
"ToolTipHide": 3558,
"ToolTipMap": 3559,
"ToolTipCapacity": 3560,
"ToolTipLevel": 3561,
"ToolTipServer": 3562,
"ToolTipCrossplay": 3563,
"ToolTipNoCrossplay": 3564,
"ToolTipLanguage": 3565,
"ConfirmSettings": 3566,
"ConfirmSettingsTooltip": 3567,
"EnterCodeElipsis": 3568,
"ToolTipChatTab": 3569,
"DropshipsLabel": 3570,
"FiltersActive": 3571,
"ClearFilters": 3572,
"MoreLabel": 3573,
"HostNounEmpty": 3574,
"ToolTipSkeld": 3575,
"ToolTipMIRA": 3576,
"ToolTipPolus": 3577,
"ToolTipAirship": 3578,
"ToolTipFungle": 3579,
"FilterLow": 3580,
"FilterMed": 3581,
"FilterHigh": 3582,
"FilterVeryHigh": 3583,
"FilterLong": 3584,
"FilterNone": 3585,
"FilterPlayerLevel": 3586,
"RefreshLabel": 3587,
"JoinGameLabel": 3588,
"FilterClearText": 3589,
"MatchesFoundLabel": 3590,
"FilterGameTooltip": 3591,
"FilterMapTooltip": 3592,
"FilterImpostorTooltip": 3593,
"FilterRoleTooltip": 3594,
"FilterSpeedTooltip": 3595,
"FilterKillCDTooltip": 3596,
"FilterVotingTooltip": 3597,
"FilterVisualTaskTooltip": 3598,
"FilterAnonVotesTooltip": 3599,
"FilterConfirmEjectTooltip": 3600,
"FilterLevelTooltip": 3601,
"FilterCrossplayTooltip": 3602,
"FilterDefaultTooltip": 3603,
"FilterFlashlightTooltip": 3604,
"FilterHidingTimeTooltip": 3605,
"FilterFinalTimeTooltip": 3606,
"FilterMaxVentTooltip": 3607,
"FilterBeginner": 3608,
"FilterIntermediate": 3609,
"FilterExpert": 3610,
"FilterTag": 3611,
"FilterTagTooltip": 3612,
"TooltipTag": 3613,
"SelectedLabel": 3614,
"TooltipSpeedInfo": 3615,
"TooltipKillCDInfo": 3616,
"TooltipVotingInfo": 3617,
"TooptipHidingTimeInfo": 3618,
"TooltipFinalTimeInfo": 3619,
"FilterNoMaps": 3620,
"MaxFilters": 3621,
"XboxCommsMultiplayerError": 3700,
"XboxCommsUGError": 3701,
"XboxCommsCreateGameError": 3702,
"XboxCommsSearchError": 3703,
"XboxCommsJoinError": 3704,
"DetectiveRole": 4000,
"DetectiveAbility": 4001,
"DetectiveAbilityNotes": 4002,
"DetectiveBlurb": 4003,
"DetectiveBlurbMed": 4004,
"DetectiveBlurbLong": 4005,
"DetectiveNotesEmpty": 4006,
"DetectiveNotesFoundDead": 4007,
"DetectiveNotesSuspectInfo": 4008,
"DetectiveNearLocation": 4009,
"DetectiveNotesKiller": 4010,
"StatsDetectiveQuestioned": 4011,
"StatsDetectiveCasesFilled": 4012,
"DetectiveSuspectLimit": 4013,
"RolesHelp_Detective_01": 4014,
"RolesHelp_Detective_02": 4015,
"ViperRole": 4037,
"ViperBlurb": 4038,
"ViperBlurbMed": 4039,
"ViperBlurbLong": 4040,
"ViperDissolveTime": 4041,
"ViperAbility": 4042,
"StatsViperBodiesDissolved": 4043,
"RolesHelp_Viper_01": 4044,
"RolesHelp_Viper_02": 4045,
"QCWhereWasDead": 4060,
"QCInterrogateCrew": 4061,
"QCInterrogated": 4062,
"QCBodyDissolved": 4063,
"QCBodyVeryDissolved": 4064,
"QCBodyAlmostDissolved": 4065,
"QCDetectives": 4066,
"QCVipers": 4067,
"DetectiveNotesTitleVictim": 4068,
"DetectiveNotesTitleFoundDead": 4069,
"DetectiveNotesTitleKiller": 4070,
"DetectiveNotesTitleSuspects": 4071,
"DetectiveNotesTitleLocationsAtTimeOfDeath": 4072,
"DetectiveNotesPromptPreposition": 4073,
"DetectiveNotesPromptLocation": 4074,
"DetectiveNotesPromptImpostor": 4075,
"DetectiveNotesPromptSuspect": 4076,
"DetectiveNotesPrepositionIn": 4077,
"DetectiveNotesPrepositionBy": 4078,
"DetectiveNotesPrepositionMaybe": 4079,
"DetectiveNotesTitlePostIt": 4080,
"DetectiveNotesPostIt": 4081,
"DetectiveNotesSuspectNumber": 4082
}
+2 -2
View File
@@ -1,5 +1,5 @@
{
"dumpostorVersion": "1.0.1",
"gameVersion": "2024.10.29",
"dumpostorVersion": "1.0.1-dev",
"gameVersion": "2025.10.14",
"platformType": "StandaloneItch"
}
@@ -1,93 +1,93 @@
{
"0": {
"room": "Cafeteria",
"position": {
"x": 6.3936,
"y": 1.33848
}
},
"1": {
"room": "Storage",
"position": {
"x": 5.268,
"y": -14.2884
}
},
"2": {
"room": "UpperEngine",
"position": {
"x": 16.930801,
"y": -2.1276002
}
},
"3": {
"room": "Cafeteria",
"position": {
"x": 0.708,
"y": -4.992
}
},
"4": {
"room": "LowerEngine",
"position": {
"x": 14.6808,
"y": -11.472
}
},
"5": {
"room": "UpperEngine",
"position": {
"x": 14.676002,
"y": 1.3406401
}
},
"6": {
"room": "Security",
"position": {
"x": 14.734801,
"y": -5.1417603
}
},
"7": {
"room": "Storage",
"position": {
"x": -1.1316001,
"y": -11.98128
}
},
"8": {
"room": "Cafeteria",
"position": {
"x": -5.1432004,
"y": 1.3355999
}
},
"9": {
"1": {
"room": "Cafeteria",
"position": {
"x": 0.708,
"y": -4.992
}
},
"2": {
"room": "Cafeteria",
"position": {
"x": 6.3936,
"y": 1.33848
}
},
"3": {
"room": "Electrical",
"position": {
"x": 9.53616,
"y": -13.416001
}
},
"10": {
"room": "MedBay",
"4": {
"room": "Storage",
"position": {
"x": 9.1452,
"y": -0.4439999
"x": -1.1316001,
"y": -11.98128
}
},
"11": {
"5": {
"room": "Storage",
"position": {
"x": 0.70919997,
"y": -8.560801
}
},
"6": {
"room": "Storage",
"position": {
"x": 5.268,
"y": -14.2884
}
},
"7": {
"room": "LowerEngine",
"position": {
"x": 14.6808,
"y": -11.472
}
},
"8": {
"room": "LowerEngine",
"position": {
"x": 16.930801,
"y": -8.9664
}
},
"12": {
"room": "Storage",
"9": {
"room": "UpperEngine",
"position": {
"x": 0.70919997,
"y": -8.560801
"x": 14.676002,
"y": 1.3406401
}
},
"10": {
"room": "UpperEngine",
"position": {
"x": 16.930801,
"y": -2.1276002
}
},
"11": {
"room": "Security",
"position": {
"x": 14.734801,
"y": -5.1417603
}
},
"12": {
"room": "MedBay",
"position": {
"x": 9.1452,
"y": -0.4439999
}
}
}
@@ -1,11 +1,11 @@
{
"initialSpawnCenter": {
"x": -0.72,
"y": 0.62
"x": 0.87,
"y": 0.69
},
"meetingSpawnCenter": {
"x": -0.72,
"y": 0.62
"x": 0.87,
"y": 0.69
},
"meetingSpawnCenter2": {
"x": 0,
@@ -476,5 +476,138 @@
"usableDistance": 1
}
]
},
"29": {
"type": "NormalPlayerTask",
"taskType": "VentCleaning",
"length": "Short",
"consoles": [
{
"id": 0,
"room": "Admin",
"position": {
"x": -2.544,
"y": -9.955201
},
"usableDistance": 1
},
{
"id": 2,
"room": "Cafeteria",
"position": {
"x": -4.2588,
"y": -0.27600002
},
"usableDistance": 1
},
{
"id": 13,
"room": "Nav",
"position": {
"x": -16.008001,
"y": -6.3840003
},
"usableDistance": 1
},
{
"id": 12,
"room": "Nav",
"position": {
"x": -16.008001,
"y": -3.1680002
},
"usableDistance": 1
},
{
"id": 7,
"room": "Weapons",
"position": {
"x": -8.820001,
"y": 3.3240001
},
"usableDistance": 1
},
{
"id": 10,
"room": "Shields",
"position": {
"x": -9.5232,
"y": -14.337601
},
"usableDistance": 1
},
{
"id": 1,
"room": "Hallway",
"position": {
"x": -9.384,
"y": -6.438
},
"usableDistance": 1
},
{
"id": 3,
"room": "Electrical",
"position": {
"x": 9.7764,
"y": -8.034
},
"usableDistance": 1
},
{
"id": 8,
"room": "Reactor",
"position": {
"x": 20.796001,
"y": -6.9528003
},
"usableDistance": 1
},
{
"id": 11,
"room": "Reactor",
"position": {
"x": 21.876,
"y": -3.0516002
},
"usableDistance": 1
},
{
"id": 9,
"room": "LowerEngine",
"position": {
"x": 15.2508,
"y": -13.656001
},
"usableDistance": 1
},
{
"id": 4,
"room": "UpperEngine",
"position": {
"x": 15.288,
"y": 2.52
},
"usableDistance": 1
},
{
"id": 5,
"room": "Security",
"position": {
"x": 12.534,
"y": -6.9492
},
"usableDistance": 1
},
{
"id": 6,
"room": "MedBay",
"position": {
"x": 10.608001,
"y": -4.176
},
"usableDistance": 1
}
]
}
}
@@ -1,6 +1,6 @@
{
"0": {
"name": "AdminVent",
"name": "AdminVent (1)",
"position": {
"x": -2.544,
"y": -9.955201
@@ -10,7 +10,7 @@
"right": 1
},
"1": {
"name": "BigYVent",
"name": "BigYVent (1)",
"position": {
"x": -9.384,
"y": -6.438
@@ -20,7 +20,7 @@
"right": 2
},
"2": {
"name": "CafeVent",
"name": "CafeVent (1)",
"position": {
"x": -4.2588,
"y": -0.27600002
@@ -30,7 +30,7 @@
"right": 1
},
"3": {
"name": "ElecVent",
"name": "ElecVent (1)",
"position": {
"x": 9.7764,
"y": -8.034
@@ -40,7 +40,7 @@
"right": 6
},
"4": {
"name": "LEngineVent",
"name": "LEngineVent (1)",
"position": {
"x": 15.288,
"y": 2.52
@@ -50,7 +50,7 @@
"right": null
},
"5": {
"name": "LifeSuppVent",
"name": "SecurityVent",
"position": {
"x": 12.534,
"y": -6.9492
@@ -60,7 +60,7 @@
"right": 3
},
"6": {
"name": "MedVent",
"name": "MedVent (1)",
"position": {
"x": 10.608001,
"y": -4.176
@@ -70,7 +70,7 @@
"right": 3
},
"7": {
"name": "WeaponsVent",
"name": "WeaponsVent (1)",
"position": {
"x": -8.820001,
"y": 3.3240001
@@ -80,7 +80,7 @@
"right": 12
},
"8": {
"name": "ReactorVent",
"name": "ReactorVent (1)",
"position": {
"x": 20.796001,
"y": -6.9528003
@@ -90,7 +90,7 @@
"right": null
},
"9": {
"name": "REngineVent",
"name": "REngineVent (1)",
"position": {
"x": 15.2508,
"y": -13.656001
@@ -100,7 +100,7 @@
"right": null
},
"10": {
"name": "ShieldsVent",
"name": "ShieldsVent (1)",
"position": {
"x": -9.5232,
"y": -14.337601
@@ -110,7 +110,7 @@
"right": null
},
"11": {
"name": "UpperReactorVent",
"name": "UpperReactorVent (1)",
"position": {
"x": 21.876,
"y": -3.0516002
@@ -120,7 +120,7 @@
"right": null
},
"12": {
"name": "NavVentNorth",
"name": "NavVentNorth (1)",
"position": {
"x": -16.008001,
"y": -3.1680002
@@ -130,7 +130,7 @@
"right": 7
},
"13": {
"name": "NavVentSouth",
"name": "NavVentSouth (1)",
"position": {
"x": -16.008001,
"y": -6.3840003
@@ -2,7 +2,7 @@ namespace Impostor.Api.Innersloth.GameOptions;
public class HideNSeekGameOptions : IGameOptions
{
public const int LatestVersion = 9;
public const int LatestVersion = 10;
public HideNSeekGameOptions(byte version = LatestVersion)
{
@@ -4,7 +4,7 @@ namespace Impostor.Api.Innersloth.GameOptions;
public class NormalGameOptions : IGameOptions
{
public const int LatestVersion = 9;
public const int LatestVersion = 10;
public NormalGameOptions(byte version = LatestVersion)
{
@@ -0,0 +1,29 @@
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
public class DetectiveRoleOptions : IRoleOptions
{
public DetectiveRoleOptions(byte version)
{
Version = version;
}
public byte Version { get; }
public RoleTypes Type => RoleTypes.Detective;
public byte DetectiveSuspectLimit { get; set; } = 3;
public static DetectiveRoleOptions Deserialize(IMessageReader reader, byte version)
{
var options = new DetectiveRoleOptions(version);
options.DetectiveSuspectLimit = reader.ReadByte();
return options;
}
public void Serialize(IMessageWriter writer)
{
writer.Write((byte)DetectiveSuspectLimit);
}
}
@@ -32,6 +32,8 @@ public class RoleOptionsCollection
RoleTypes.Noisemaker => NoisemakerRoleOptions.Deserialize(roleOptionsReader, Version),
RoleTypes.Phantom => PhantomRoleOptions.Deserialize(roleOptionsReader, Version),
RoleTypes.Tracker => TrackerRoleOptions.Deserialize(roleOptionsReader, Version),
RoleTypes.Detective => DetectiveRoleOptions.Deserialize(roleOptionsReader, Version),
RoleTypes.Viper => ViperRoleOptions.Deserialize(roleOptionsReader, Version),
_ => throw new ArgumentOutOfRangeException(nameof(roleType), roleType, null),
};
@@ -0,0 +1,29 @@
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
public class ViperRoleOptions : IRoleOptions
{
public ViperRoleOptions(byte version)
{
Version = version;
}
public byte Version { get; }
public RoleTypes Type => RoleTypes.Viper;
public byte ViperDissolveTime { get; set; } = 15;
public static ViperRoleOptions Deserialize(IMessageReader reader, byte version)
{
var options = new ViperRoleOptions(version);
options.ViperDissolveTime = reader.ReadByte();
return options;
}
public void Serialize(IMessageWriter writer)
{
writer.Write((byte)ViperDissolveTime);
}
}
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -29,6 +29,7 @@ namespace Impostor.Api.Net.Messages
public const byte QueryPlatformIds = 22;
public const byte QueryLobbyInfo = 23;
public const byte EndGameHostMigration = 24;
public const byte PackedGameDataTo = 26;
private static readonly Dictionary<byte, string> FlagCache;
@@ -40,6 +41,11 @@ namespace Impostor.Api.Net.Messages
.ToDictionary(x => (byte)x.GetValue(null)!, y => y.Name);
}
/// <summary>
/// Convert a MessageFlag to the corresponding string.
/// </summary>
/// <param name="flag">The MessageFlag to convert.</param>
/// <returns>A string corresponding with the value of flag.</returns>
public static string FlagToString(byte flag)
{
return FlagCache.TryGetValue(flag, out var res) ? res : $"Unknown Flag {flag}";
@@ -1,4 +1,4 @@
using Impostor.Api.Events.Player;
using Impostor.Api.Events.Player;
using Impostor.Api.Games;
using Impostor.Api.Net;
using Impostor.Api.Net.Inner.Objects;
@@ -24,5 +24,7 @@ namespace Impostor.Server.Events.Player
public string Message { get; }
public bool IsCancelled { get; set; }
public bool SendToAllPlayers { get; set; } = true;
}
}
+70 -8
View File
@@ -74,6 +74,12 @@ namespace Impostor.Server.Net
CheatCategory.Ownership => _antiCheatConfig.EnableOwnershipChecks,
CheatCategory.Role => _antiCheatConfig.EnableRoleChecks,
CheatCategory.Target => _antiCheatConfig.EnableTargetChecks,
CheatCategory.HostOnlyExtension => _antiCheatConfig.AllowHostOnlyExtensions switch {
CheatingHostMode.Always => false,
CheatingHostMode.IfRequested => !GameVersion.HasDisableServerAuthorityFlag,
CheatingHostMode.Never => true,
_ => true,
},
CheatCategory.Other => true,
_ => LogUnknownCategory(category),
};
@@ -194,7 +200,7 @@ namespace Impostor.Server.Net
case MessageFlags.StartGame:
{
if (!IsPacketAllowed(reader, true))
if (!IsPacketAllowed(reader, true, flag))
{
return;
}
@@ -209,7 +215,7 @@ namespace Impostor.Server.Net
case MessageFlags.RemovePlayer:
{
if (!IsPacketAllowed(reader, true))
if (!IsPacketAllowed(reader, true, flag))
{
return;
}
@@ -226,7 +232,7 @@ namespace Impostor.Server.Net
case MessageFlags.GameData:
case MessageFlags.GameDataTo:
{
if (!IsPacketAllowed(reader, false))
if (!IsPacketAllowed(reader, false, flag))
{
return;
}
@@ -259,9 +265,60 @@ namespace Impostor.Server.Net
break;
}
case MessageFlags.PackedGameDataTo:
{
// We're limiting this to hosts right now. If you have a use case for this for
// players to use this feature, we're open to changing this.
if (!IsPacketAllowed(reader, true, flag))
{
return;
}
if (await ReportCheatAsync(
new CheatContext(MessageFlags.FlagToString(flag)),
CheatCategory.HostOnlyExtension,
"Client sent a PackedGameDataTo message"))
{
return;
}
while (reader.Position < reader.Length)
{
using var packed = reader.ReadMessage();
if (packed.Tag != MessageFlags.GameDataTo)
{
_logger.LogWarning("PackedGameDataTo contained non-GameDataTo flag {0}.", packed.Tag);
return;
}
if (packed.ReadInt32() != Player!.Game.Code)
{
_logger.LogWarning("PackedGameDataTo contained GameDataTo for the wrong game.");
return;
}
var position = packed.Position;
var verified = await Player.Game.HandleGameDataAsync(packed, Player, true);
packed.Seek(position);
if (!verified || Player == null)
{
return;
}
using var writer = MessageWriter.Get(messageType);
var target = packed.ReadPackedInt32();
packed.CopyTo(writer);
await Player.Game.SendToAsync(writer, target);
}
break;
}
case MessageFlags.EndGame:
{
if (!IsPacketAllowed(reader, true))
if (!IsPacketAllowed(reader, true, flag))
{
return;
}
@@ -276,7 +333,7 @@ namespace Impostor.Server.Net
case MessageFlags.AlterGame:
{
if (!IsPacketAllowed(reader, true))
if (!IsPacketAllowed(reader, true, flag))
{
return;
}
@@ -297,7 +354,7 @@ namespace Impostor.Server.Net
case MessageFlags.KickPlayer:
{
if (!IsPacketAllowed(reader, true))
if (!IsPacketAllowed(reader, true, flag))
{
return;
}
@@ -344,6 +401,7 @@ namespace Impostor.Server.Net
#if DEBUG
if (flag != MessageFlags.GameData &&
flag != MessageFlags.GameDataTo &&
flag != MessageFlags.PackedGameDataTo &&
flag != MessageFlags.EndGame &&
reader.Position < reader.Length)
{
@@ -377,7 +435,7 @@ namespace Impostor.Server.Net
await _gameManager.OnClientDisconnectAsync(this);
}
private bool IsPacketAllowed(IMessageReader message, bool hostOnly)
private bool IsPacketAllowed(IMessageReader message, bool hostOnly, byte flag)
{
if (Player == null)
{
@@ -400,7 +458,11 @@ namespace Impostor.Server.Net
return true;
}
_logger.LogWarning("[{0}] Client sent packet only allowed by the host ({1}).", Id, game.HostId);
_logger.LogWarning(
"[{0}] Client sent packet {1} only allowed by the host ({2}).",
Id,
MessageFlags.FlagToString(flag),
game.HostId);
return false;
}
@@ -1183,9 +1183,35 @@ namespace Impostor.Server.Net.Inner.Objects
private async ValueTask<bool> HandleSendChat(ClientPlayer sender, string message)
{
var @event = new PlayerChatEvent(Game, sender, this, message);
// See https://github.com/Innersloth-LLC/AmongUsModdingInformation?tab=readme-ov-file#chat-commands
// Details not mentioned:
// - If the host sends a message that starts with /cmd, it is sent to all players
// - If the message starts with " /cmd" (note the space) it is sent to all players
if (Game.IsHostAuthoritive && !sender.IsHost && message.StartsWith("/cmd"))
{
@event.SendToAllPlayers = false;
}
await _eventManager.CallAsync(@event);
return !@event.IsCancelled;
if (@event.IsCancelled)
{
return false;
}
else if (@event.SendToAllPlayers == false)
{
if (Game.Host != null)
{
await SendChatToPlayerAsync(message, Game.Host.Character);
}
return false;
}
else
{
return true;
}
}
private async ValueTask HandleStartMeeting(byte targetId)
@@ -101,8 +101,8 @@ namespace Impostor.Server.Net.Manager
return;
}
// Warn when players connect using the +25 flag that disables server authority. The host authority version
// of 2024.6.18 contains various bugs that break the game, so print a message if this mode is in use
// Warn when players connect using the +25 flag that disables server authority.
// This changes game behaviour, so we'd like to know if it's in use.
if (clientVersion.HasDisableServerAuthorityFlag)
{
if (!_compatibilityConfig.AllowHostAuthority)
@@ -112,7 +112,7 @@ namespace Impostor.Server.Net.Manager
return;
}
_logger.LogWarning("Player {Name} connected with server authority disabled, this may cause issues as there are known bugs in this mode. Please mention that this mode is in use when asking for support.", name);
_logger.LogInformation("Player {Name} connected with server authority disabled, please mention that this mode is in use when asking for support.", name);
}
if (name.Length > 10)
@@ -28,7 +28,20 @@ internal class CompatibilityManager : ICompatibilityManager
},
new[]
{
new GameVersion(2025, 4, 15), // 16.0.5 (2025-05-20)
new GameVersion(2025, 4, 15), // 16.0.5 (2025-05-20) & 16.1.0 (2025-06-10)
},
new[]
{
new GameVersion(2025, 7, 15), // 17.0.0 (2025-09-09)
new GameVersion(2025, 9, 12), // 17.0.1 (2025-10-14)
new GameVersion(2025, 10, 9), // 17.1 (2025-11-18)
new GameVersion(2025, 11, 6), // 17.1.1 (2025-12-03, mobile only)
new GameVersion(2025, 12, 8), // 17.1.2 (2025-12-11, mobile only)
new GameVersion(2025, 11, 5), // 17.2 (2026-02-17, build 6630, not a typo, Innersloth went backwards)
new GameVersion(2026, 1, 22), // 17.2 (2026-02-19, build 6686, hotfix)
new GameVersion(2026, 2, 2), // 17.2.2 (2026-03-17, build 6768)
new GameVersion(2026, 1, 12), // 17.3 (2026-03-31, build 6803)
new GameVersion(2026, 3, 17), // 17.3.1 (2026-04-08, build 6841, mobile only)
},
};
+9 -23
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -60,16 +61,14 @@ namespace Impostor.Server.Net.State
private static readonly Dictionary<Type, uint> SpawnableObjectIds = SpawnableObjects.ToDictionary((i) => i.Value, (i) => i.Key);
private readonly List<InnerNetObject> _allObjects = new List<InnerNetObject>();
private readonly Dictionary<uint, InnerNetObject> _allObjectsFast = new Dictionary<uint, InnerNetObject>();
private readonly ConcurrentDictionary<uint, InnerNetObject> _allObjects = new ConcurrentDictionary<uint, InnerNetObject>();
private uint _nextNetId = MinServerNetId;
public T? FindObjectByNetId<T>(uint netId)
where T : IInnerNetObject
{
if (_allObjectsFast.TryGetValue(netId, out var obj))
if (_allObjects.TryGetValue(netId, out var obj))
{
return (T)(IInnerNetObject)obj;
}
@@ -104,7 +103,7 @@ namespace Impostor.Server.Net.State
case GameDataTag.DataFlag:
{
var netId = reader.ReadPackedUInt32();
if (_allObjectsFast.TryGetValue(netId, out var obj))
if (_allObjects.TryGetValue(netId, out var obj))
{
await obj.DeserializeAsync(sender, target, reader, false);
}
@@ -119,7 +118,7 @@ namespace Impostor.Server.Net.State
case GameDataTag.RpcFlag:
{
var netId = reader.ReadPackedUInt32();
if (_allObjectsFast.TryGetValue(netId, out var obj))
if (_allObjects.TryGetValue(netId, out var obj))
{
if (!await obj.HandleRpcAsync(sender, target, (RpcCalls)reader.ReadByte(), reader))
{
@@ -214,7 +213,7 @@ namespace Impostor.Server.Net.State
case GameDataTag.DespawnFlag:
{
var netId = reader.ReadPackedUInt32();
if (_allObjectsFast.TryGetValue(netId, out var obj))
if (_allObjects.TryGetValue(netId, out var obj))
{
if (sender.Client.Id != obj.OwnerId && !sender.IsHost)
{
@@ -468,7 +467,7 @@ namespace Impostor.Server.Net.State
private async ValueTask SyncServerObjectsAsync(ClientPlayer sender)
{
foreach (var obj in _allObjectsFast.Values)
foreach (var obj in _allObjects.Values)
{
if (obj.OwnerId == ServerOwned)
{
@@ -533,25 +532,12 @@ namespace Impostor.Server.Net.State
private bool AddNetObject(InnerNetObject obj)
{
if (_allObjectsFast.ContainsKey(obj.NetId))
{
return false;
}
_allObjects.Add(obj);
_allObjectsFast.Add(obj.NetId, obj);
return true;
return _allObjects.TryAdd(obj.NetId, obj);
}
private void RemoveNetObject(InnerNetObject obj)
{
var index = _allObjects.IndexOf(obj);
if (index > -1)
{
_allObjects.RemoveAt(index);
}
_allObjectsFast.Remove(obj.NetId);
_allObjects.TryRemove(obj.NetId, out _);
}
}
}
+1
View File
@@ -34,6 +34,7 @@ namespace Impostor.Tools.Proxy
{ 13, "Redirect" },
{ 14, "ReselectServer" },
{ 16, "GetGameListV2" },
{ 26, "PackedGameDataTo" },
};
private static IServiceProvider _serviceProvider;