mirror of
https://github.com/Impostor/Impostor.git
synced 2026-10-23 10:46:42 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9e8def90d | ||
|
|
dc530406c6 | ||
|
|
2de08da14d | ||
|
|
7a89e963dd | ||
|
|
8aaf75e381 | ||
|
|
59cb4a18e8 | ||
|
|
a0b5228e71 | ||
|
|
78351c1dbe | ||
|
|
45e0162c1a | ||
|
|
fcf8d66266 | ||
|
|
6b6fa08125 | ||
|
|
cea3d8980f | ||
|
|
d1ffdb95e1 | ||
|
|
4d11cf91ad | ||
|
|
84aba52198 | ||
|
|
6e4bb71289 | ||
|
|
8fec1a211e | ||
|
|
85a2fce6c1 | ||
|
|
224fdd1d5b | ||
|
|
380ba46f11 | ||
|
|
aeefc40ef1 | ||
|
|
743b8ed5cb | ||
|
|
ed008872f6 | ||
|
|
4797d899af | ||
|
|
c834013bd3 | ||
|
|
70c180fb19 | ||
|
|
729368d777 | ||
|
|
5c06d1dd4d | ||
|
|
446e5b8705 | ||
|
|
ae00ff9295 | ||
|
|
400592b99c | ||
|
|
9906c409da | ||
|
|
c26d03a8bc | ||
|
|
ca48d672d5 | ||
|
|
0b431dc5fa | ||
|
|
0b0c8274aa | ||
|
|
36f8255e26 | ||
|
|
919b094018 | ||
|
|
6125fd7006 | ||
|
|
a3c0c8cacf | ||
|
|
b252bf2ee7 | ||
|
|
9b5a63e030 | ||
|
|
6a8f089576 | ||
|
|
d994323083 | ||
|
|
3f374da44b | ||
|
|
bfd2efa716 | ||
|
|
6867dec7ee | ||
|
|
7132dc2d38 | ||
|
|
682bfac558 | ||
|
|
cc8d5d2a45 | ||
|
|
e6a35344c3 | ||
|
|
db52b48cd6 | ||
|
|
50a526a02d | ||
|
|
608414326d | ||
|
|
d8bcb52c90 | ||
|
|
d7d7547182 | ||
|
|
64e27c3e21 | ||
|
|
a0b433500c | ||
|
|
c51a1f9c1f | ||
|
|
e15ac51dcf | ||
|
|
bde3a22f6e | ||
|
|
6118e6b7b8 | ||
|
|
32ecfedfba | ||
|
|
b6fe79cc8b | ||
|
|
aeaffc849a | ||
|
|
a15f1b6a4c | ||
|
|
afb7051218 | ||
|
|
8a0e9e876e | ||
|
|
22f1d74cdf | ||
|
|
e6d38f4b72 | ||
|
|
93c80c1412 | ||
|
|
c3e0157209 | ||
|
|
0769752407 | ||
|
|
fba1a894cc | ||
|
|
4d1aec9070 | ||
|
|
e0c7086973 | ||
|
|
125da11d61 |
No files matched your search
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"cake.tool": {
|
||||
"version": "1.1.0",
|
||||
"version": "2.2.0",
|
||||
"commands": [
|
||||
"dotnet-cake"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci.yml'
|
||||
- 'src/**/**'
|
||||
- '.gitmodules'
|
||||
- 'build.cake'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/ci.yml'
|
||||
- 'src/**/**'
|
||||
- '.gitmodules'
|
||||
- 'build.cake'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nuget-
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: 6.x
|
||||
|
||||
- name: Run the Cake script
|
||||
uses: cake-build/cake-action@v1
|
||||
with:
|
||||
verbosity: Diagnostic
|
||||
|
||||
- uses: softprops/action-gh-release@v1
|
||||
if: github.ref_type == 'tag'
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
./build/*.zip
|
||||
./build/*.tar.gz
|
||||
./build/*.nupkg
|
||||
./build/*.snupkg
|
||||
|
||||
- name: Push NuGet package
|
||||
if: github.ref_type == 'tag'
|
||||
run: |
|
||||
dotnet nuget push ./build/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_IMPOSTOR }}
|
||||
+4
-3
@@ -1,4 +1,4 @@
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:5.0 AS build
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
|
||||
# See for all possible platforms
|
||||
# https://github.com/containerd/containerd/blob/master/platforms/platforms.go#L17
|
||||
@@ -12,6 +12,7 @@ WORKDIR /source
|
||||
COPY src/Impostor.Server/Impostor.Server.csproj ./src/Impostor.Server/Impostor.Server.csproj
|
||||
COPY src/Impostor.Api/Impostor.Api.csproj ./src/Impostor.Api/Impostor.Api.csproj
|
||||
COPY src/Impostor.Hazel/Hazel/Hazel.csproj ./src/Impostor.Hazel/Hazel/Hazel.csproj
|
||||
COPY src/Directory.Build.props ./src/Directory.Build.props
|
||||
|
||||
RUN case "$TARGETARCH" in \
|
||||
amd64) NETCORE_PLATFORM='linux-x64';; \
|
||||
@@ -35,8 +36,8 @@ RUN case "$TARGETARCH" in \
|
||||
dotnet publish -c release -o /app -r "$NETCORE_PLATFORM" -p:VersionSuffix="$VERSIONSUFFIX" --no-restore ./src/Impostor.Server/Impostor.Server.csproj
|
||||
|
||||
# Final image.
|
||||
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/runtime:5.0
|
||||
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/runtime:6.0
|
||||
WORKDIR /app
|
||||
COPY --from=build /app ./
|
||||
EXPOSE 22023/udp
|
||||
ENTRYPOINT ["./Impostor.Server"]
|
||||
ENTRYPOINT ["./Impostor.Server"]
|
||||
@@ -1,7 +1,7 @@
|
||||
# Impostor
|
||||
|
||||
[](https://discord.gg/Mk3w6Tb)
|
||||
[](https://ci.appveyor.com/project/Impostor/Impostor/branch/master)
|
||||
[](https://github.com/Impostor/Impostor/actions)
|
||||
|
||||
Impostor is the first working **Among Us** private server, written in C#.
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
environment:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
|
||||
branches:
|
||||
except:
|
||||
- gh-pages
|
||||
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
|
||||
assembly_info:
|
||||
patch: false
|
||||
|
||||
dotnet_csproj:
|
||||
patch: false
|
||||
|
||||
image: Ubuntu2004
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
- ps: dotnet tool restore
|
||||
|
||||
build_script:
|
||||
- ps: dotnet cake build.cake --bootstrap
|
||||
- ps: dotnet cake build.cake --pack
|
||||
|
||||
test: off
|
||||
|
||||
artifacts:
|
||||
- path: ./build/*.zip
|
||||
- path: ./build/*.tar.gz
|
||||
- path: ./build/*.nupkg
|
||||
- path: ./build/*.snupkg
|
||||
|
||||
# deploy:
|
||||
# - provider: NuGet
|
||||
# artifact: /.*(\.|\.s)nupkg/
|
||||
# on:
|
||||
# branch: dev
|
||||
# api_key:
|
||||
# secure: 4OHXl+m1KVi60hB1j54MpdP8tVv0UNfkdF4rVP+2AhAjN4a2MVT+Bl90gJZ96xHF
|
||||
|
||||
only_commits:
|
||||
files:
|
||||
- appveyor.yml
|
||||
- build.cake
|
||||
- src/**/*
|
||||
- .gitmodules
|
||||
+39
-28
@@ -1,25 +1,33 @@
|
||||
#addin "nuget:?package=SharpZipLib&Version=1.3.1"
|
||||
#addin "nuget:?package=Cake.Compression&Version=0.2.6"
|
||||
#addin "nuget:?package=Cake.FileHelpers&Version=4.0.1"
|
||||
#addin "nuget:?package=SharpZipLib&Version=1.3.3"
|
||||
#addin "nuget:?package=Cake.Compression&Version=0.3.0"
|
||||
#addin "nuget:?package=Cake.FileHelpers&Version=5.0.0"
|
||||
|
||||
var workflow = BuildSystem.GitHubActions.Environment.Workflow;
|
||||
var buildId = workflow.RunNumber;
|
||||
var tag = workflow.RefType == GitHubActionsRefType.Tag ? workflow.RefName : null;
|
||||
|
||||
var buildId = EnvironmentVariable("GITHUB_RUN_NUMBER") ?? EnvironmentVariable("APPVEYOR_BUILD_VERSION");
|
||||
var buildRelease = EnvironmentVariable("APPVEYOR_REPO_TAG") == "true";
|
||||
var buildVersion = FindRegexMatchGroupInFile("./src/Directory.Build.props", @"\<VersionPrefix\>(.*?)\<\/VersionPrefix\>", 1, System.Text.RegularExpressions.RegexOptions.None).Value;
|
||||
var buildDir = MakeAbsolute(Directory("./build"));
|
||||
|
||||
var target = Argument("target", "Deploy");
|
||||
var target = Argument("target", "Test");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
|
||||
var msbuildSettings = new DotNetCoreMSBuildSettings();
|
||||
var msbuildSettings = new DotNetMSBuildSettings();
|
||||
|
||||
if (buildRelease)
|
||||
if (tag != null)
|
||||
{
|
||||
msbuildSettings.Properties["Version"] = new[] { buildVersion };
|
||||
if (tag[1..] != buildVersion) throw new Exception("Tag version has to be the same as VersionPrefix in Directory.Build.props");
|
||||
msbuildSettings.Version = buildVersion;
|
||||
}
|
||||
else if (buildId != null)
|
||||
else if (buildId != 0)
|
||||
{
|
||||
msbuildSettings.Properties["VersionSuffix"] = new[] { "ci." + buildId };
|
||||
buildId += 500;
|
||||
msbuildSettings.VersionSuffix = "ci." + buildId;
|
||||
buildVersion += "-ci." + buildId;
|
||||
}
|
||||
else
|
||||
{
|
||||
buildVersion += "-dev";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -31,10 +39,9 @@ private void ImpostorPublish(string name, string project, string runtime, bool i
|
||||
var projBuildDir = buildDir.Combine(name + "_" + runtime);
|
||||
var projBuildName = name + "_" + buildVersion + "_" + runtime;
|
||||
|
||||
DotNetCorePublish(project, new DotNetCorePublishSettings {
|
||||
DotNetPublish(project, new DotNetPublishSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net5.0",
|
||||
Runtime = runtime,
|
||||
SelfContained = false,
|
||||
PublishSingleFile = true,
|
||||
@@ -57,6 +64,10 @@ private void ImpostorPublish(string name, string project, string runtime, bool i
|
||||
} else {
|
||||
GZipCompress(projBuildDir, buildDir.CombineWithFilePath(projBuildName + ".tar.gz"));
|
||||
}
|
||||
|
||||
if (BuildSystem.GitHubActions.IsRunningOnGitHubActions) {
|
||||
BuildSystem.GitHubActions.Commands.UploadArtifact(projBuildDir, projBuildName);
|
||||
}
|
||||
}
|
||||
|
||||
private void ImpostorPublishNF(string name, string project) {
|
||||
@@ -64,7 +75,7 @@ private void ImpostorPublishNF(string name, string project) {
|
||||
var projBuildDir = buildDir.Combine(name + "_" + runtime);
|
||||
var projBuildZip = buildDir.CombineWithFilePath(name + "_" + buildVersion + "_" + runtime + ".zip");
|
||||
|
||||
DotNetCorePublish(project, new DotNetCorePublishSettings {
|
||||
DotNetPublish(project, new DotNetPublishSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net472",
|
||||
@@ -90,18 +101,17 @@ Task("Clean")
|
||||
|
||||
Task("Restore")
|
||||
.Does(() => {
|
||||
DotNetCoreRestore("./src/Impostor.sln");
|
||||
DotNetRestore("./src/Impostor.sln");
|
||||
});
|
||||
|
||||
Task("Replay")
|
||||
.Does(() => {
|
||||
// D:\Projects\GitHub\Impostor\Impostor\src\Impostor.Tools.ServerReplay\sessions
|
||||
DotNetCoreRun(
|
||||
DotNetRun(
|
||||
"./src/Impostor.Tools.ServerReplay/Impostor.Tools.ServerReplay.csproj",
|
||||
"./src/Impostor.Tools.ServerReplay/sessions", new DotNetCoreRunSettings {
|
||||
"./src/Impostor.Tools.ServerReplay/sessions", new DotNetRunSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net5.0"
|
||||
});
|
||||
});
|
||||
|
||||
@@ -111,7 +121,7 @@ Task("Build")
|
||||
.IsDependentOn("Replay")
|
||||
.Does(() => {
|
||||
// Tests.
|
||||
DotNetCoreBuild("./src/Impostor.Tests/Impostor.Tests.csproj", new DotNetCoreBuildSettings {
|
||||
DotNetBuild("./src/Impostor.Tests/Impostor.Tests.csproj", new DotNetBuildSettings {
|
||||
Configuration = configuration,
|
||||
});
|
||||
|
||||
@@ -123,32 +133,33 @@ Task("Build")
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-arm64", true);
|
||||
|
||||
// API.
|
||||
DotNetCorePack("./src/Impostor.Api/Impostor.Api.csproj", new DotNetCorePackSettings {
|
||||
DotNetPack("./src/Impostor.Api/Impostor.Api.csproj", new DotNetPackSettings {
|
||||
Configuration = configuration,
|
||||
OutputDirectory = buildDir,
|
||||
IncludeSource = true,
|
||||
IncludeSymbols = true,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
|
||||
if (BuildSystem.GitHubActions.IsRunningOnGitHubActions) {
|
||||
foreach (var file in GetFiles(buildDir + "/*.{nupkg,snupkg}"))
|
||||
{
|
||||
BuildSystem.GitHubActions.Commands.UploadArtifact(file, "Impostor.Api");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Task("Test")
|
||||
.IsDependentOn("Build")
|
||||
.Does(() => {
|
||||
DotNetCoreTest("./src/Impostor.Tests/Impostor.Tests.csproj", new DotNetCoreTestSettings {
|
||||
DotNetTest("./src/Impostor.Tests/Impostor.Tests.csproj", new DotNetTestSettings {
|
||||
Configuration = configuration,
|
||||
NoBuild = true
|
||||
});
|
||||
});
|
||||
|
||||
Task("Deploy")
|
||||
.IsDependentOn("Test")
|
||||
.Does(() => {
|
||||
Information("Finished.");
|
||||
});
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// EXECUTION
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
RunTarget(target);
|
||||
RunTarget(target);
|
||||
@@ -1,6 +1,6 @@
|
||||
# Building from source
|
||||
|
||||
The solution contains the Impostor server and its dependencies, like Hazel and the plugin API. The server is built using [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0).
|
||||
The solution contains the Impostor server and its dependencies, like Hazel and the plugin API. The server is built using [.NET 6](https://dotnet.microsoft.com/download/dotnet/6.0).
|
||||
|
||||
## Cloning Impostor
|
||||
|
||||
@@ -14,7 +14,7 @@ git clone https://github.com/Impostor/Impostor.git
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0)
|
||||
- [.NET 6 SDK](https://dotnet.microsoft.com/download/dotnet/6.0)
|
||||
- [Rider](https://www.jetbrains.com/rider/) or [Visual Studio](https://visualstudio.microsoft.com/vs/) (Optional, only if you want the full IDE experience)
|
||||
|
||||
### Build using the CLI
|
||||
|
||||
@@ -6,13 +6,17 @@ There are currently two modes to run the Impostor server. The first way, Single
|
||||
|
||||
### Without Docker
|
||||
|
||||
1. Install the [.NET 5.0 runtime](https://dotnet.microsoft.com/download). Installing the SDK also works, but is not necessary unless you plan on developing Impostor or Impostor plugins. If you're asked to pick between a console, desktop or server runtime, the console runtime is enough.
|
||||
2. Find the [latest release](https://github.com/Impostor/Impostor/releases) or the [latest CI build](https://ci.appveyor.com/project/Impostor/Impostor/branch/master/artifacts).
|
||||
1. Install the [.NET 6.0 runtime](https://dotnet.microsoft.com/download/dotnet/6.0). Installing the SDK also works, but is not necessary unless you plan on developing Impostor or Impostor plugins. If you're asked to pick between the normal, desktop or server runtime, the normal runtime is enough, but some plugins may require the ASP.NET Core Runtime as well.
|
||||
2. Find the [latest release](https://github.com/Impostor/Impostor/releases) or the [latest CI build](https://nightly.link/Impostor/Impostor/workflows/ci/master).
|
||||
3. Download the version for your OS (linux/win/osx). Impostor is built for multiple CPU-architectures, you most likely want the x64 version, unless you are running on a Raspberry Pi or another device with an ARM processor.
|
||||
4. Extract the zip.
|
||||
5. Modify `config.json` to your liking. Documentation can be found [here](Server-configuration.md) *(this step is mandatory if you want to expose this server to other devices)*
|
||||
5. Modify `config.json` to your liking. Documentation can be found [here](Server-configuration.md) _(this step is mandatory if you want to expose this server to other devices)_
|
||||
6. Run `Impostor.Server` (Linux/macOS) or `Impostor.Server.exe` (Windows)
|
||||
|
||||
Depending on your host you may also need to port forward Impostor to the internet. By default Impostor uses port **22023** and the **UDP** protocol. As port forwarding changes per host or router configuration, port forwarding is not covered by this guide.
|
||||
|
||||
To connect to the server, you need to configure a region file on https://impostor.github.io/Impostor/
|
||||
|
||||
### Using Docker
|
||||
|
||||
[](https://hub.docker.com/r/aeonlucid/impostor)
|
||||
|
||||
@@ -22,29 +22,14 @@ Impostor has an Anticheat that makes it possible to kick cheaters from games aut
|
||||
| **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. |
|
||||
|
||||
### AnnouncementsServer
|
||||
### Compatibility
|
||||
|
||||
The Announcement Server is used to show update announcements to clients. Using the Plugin API you can create a plugin that serves custom announcements.
|
||||
Impostor has two compatibility options which allow some extra flexibility but may not work properly. Enabling either of these options is not recommended.
|
||||
|
||||
| Key | Default | Value |
|
||||
| -------------- | --------- | --------------------------------------------------- |
|
||||
| **Enabled** | `false` | Whether the announcements server should be enabled. |
|
||||
| **ListenIp** | `0.0.0.0` | See Required Server Configuration. |
|
||||
| **ListenPort** | `22025` | See Required Server Configuration. |
|
||||
|
||||
### AuthServer
|
||||
|
||||
The Authentication Server is used since Among Us version 2021.3.31 and is used by clients to identify themselves. If you're playing with modded Among Us clients, you can enable this server to skip the 5 second wait to join.
|
||||
|
||||
| Key | Default | Value |
|
||||
| --------------- | ---------------------- | ---------------------------------------------------- |
|
||||
| **Enabled** | `false` | Whether the authentication server should be enabled. |
|
||||
| **ListenIp** | `0.0.0.0` | See Required Server Configuration. |
|
||||
| **ListenPort** | `22025` | See Required Server Configuration. |
|
||||
| **Certificate** | `dtls/certificate.pem` | The public certificate used to authenticate with. |
|
||||
| **PrivateKey** | `dtls/key.pem` | The corresponding private key. |
|
||||
|
||||
On Linux you can generate a certificate by running `openssl req -x509 -newkey rsa:2048 -keyout dtls/key.pem -out dtls/certificate.pem -days 3650 -nodes`. It does not need to be signed.
|
||||
| Key | Default | Value |
|
||||
| ------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **AllowNewGameVersions** | `false` | Warning: Setting this option to `true` is unsupported and may cause issues when large updates to Among Us are released. Allow future versions of Among Us to join your server. |
|
||||
| **AllowVersionMixing** | `false` | Allow players using different game versions to play in one lobby. |
|
||||
|
||||
### Debug
|
||||
|
||||
@@ -53,7 +38,7 @@ The Debug configuration is used to enable the game recorder. This is mostly usef
|
||||
| Key | Default | Value |
|
||||
| ----------------------- | ------- | -------------------------------------------- |
|
||||
| **GameRecorderEnabled** | `false` | Enables the Game Recorder. |
|
||||
| **GameRecorderPath** | *empty* | Path where the recorded games will be saved. |
|
||||
| **GameRecorderPath** | _empty_ | Path where the recorded games will be saved. |
|
||||
|
||||
### ServerRedirector
|
||||
|
||||
@@ -68,6 +53,41 @@ In a multi-node setup these values need to be specified. Note that most people d
|
||||
| **>UdpMasterEndpoint** | | On the master, this value acts as a listen ip and port. On a node, this should be the public ip and port of the master. Format `127.0.0.1:32320`. |
|
||||
| **Nodes** | | An array containing public ips and ports of nodes. Only needs to be set on the master. See above for an example. |
|
||||
|
||||
### Serilog (Logging)
|
||||
|
||||
Impostor's log framework, Serilog, can be configured in the config file. You can change its default log level and you can add additional sinks.
|
||||
|
||||
| Key | Default | Value |
|
||||
| ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **MinimumLevel** | `Information` | Minimum log level for a message to be printed. If a log entry is as severe or more severe than this level, it will be printed. From most severe to least severe: `Fatal`,`Error`, `Warning`, `Information`, `Debug`, `Verbose` |
|
||||
| **Using** | `[]` | List of additional Serilog Sinks assemblies to load. |
|
||||
| **WriteTo** | `[]` | Additional logging sinks. See the Serilog documentation or the example in this section. Serilog |
|
||||
|
||||
For more information, check the [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration) documentation.
|
||||
|
||||
For example, to add logging to a file, you should add the following snippet to your configuration:
|
||||
|
||||
```json
|
||||
"Serilog": {
|
||||
"Using": [
|
||||
"Serilog.Sinks.File"
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "logs/log.txt",
|
||||
"rollingInterval": "Day"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Next to that, you also need to copy over Serilog.Sinks.File.dll from [NuGet](https://www.nuget.org/packages/Serilog.Sinks.File/). See the [Serilog.Sinks.File documentation](https://github.com/serilog/serilog-sinks-file#json-appsettingsjson-configuration) for a list of parameters that can be configured.
|
||||
|
||||
Other Serilog sinks are also supported, but are out of scope for this documentation.
|
||||
|
||||
## Config providers
|
||||
|
||||
### File
|
||||
|
||||
@@ -22,7 +22,7 @@ You can solve this by doing: `chmod +x Impostor.Server`
|
||||
|
||||
This happens when your game is too new for your copy of Impostor to support.
|
||||
|
||||
If you're using an Impostor release, check if there is a newer release available that supports your version. If this doesn't exist, you can try the [latest build from Appveyor](https://ci.appveyor.com/project/Impostor/Impostor/branch/master).
|
||||
If you're using an Impostor release, check if there is a newer release available that supports your version. If this doesn't exist, you can try the [latest build from CI](https://nightly.link/Impostor/Impostor/workflows/ci/master).
|
||||
|
||||
If even that build doesn't work, you can try looking through the Pull Requests to see if there is a pending pull request that aims to update it to the next version, but note these may be unstable and may contain malicious code, as they haven't been vetted by the Impostor development team yet.
|
||||
|
||||
@@ -34,7 +34,7 @@ This happens when you're using a version of Impostor that is too new for your ga
|
||||
|
||||
You are using a version of Impostor that is not designed for the version of the game you're playing. The game does not really check who is outdated and blames it on the user. Newer versions (v1.5.0+) do warn correctly and send the correct message.
|
||||
|
||||
Look at which version of the game you're playing, which you can see in the top left corner of the main menu, then download an Impostor version for that game. Every [release on the release page](https://github.com/Impostor/Impostor/releases) shows which version of the game it is compatible with. If your game version is newer than the latest release, check if the [latest build from AppVeyor works](https://ci.appveyor.com/project/Impostor/Impostor/branch/master).
|
||||
Look at which version of the game you're playing, which you can see in the top left corner of the main menu, then download an Impostor version for that game. Every [release on the release page](https://github.com/Impostor/Impostor/releases) shows which version of the game it is compatible with. If your game version is newer than the latest release, check if the [latest build from CI works](https://nightly.link/Impostor/Impostor/workflows/ci/master).
|
||||
|
||||
## Disconnected with `You disconnected from the server. Reliable Packet 1 ...`
|
||||
|
||||
|
||||
@@ -19,23 +19,24 @@ Impostor has support for plugins. This document will help you to setup a develop
|
||||
- [Impostor versions](#impostor-versions)
|
||||
- [9. Missing/invalid data or want more functions?](#9-missinginvalid-data-or-want-more-functions)
|
||||
|
||||
## 1. Install .NET Core SDK
|
||||
## 1. Install .NET SDK
|
||||
|
||||
Download and install the latest .NET Core SDK.
|
||||
Download and install the latest .NET SDK.
|
||||
|
||||
https://dotnet.microsoft.com/download
|
||||
|
||||
## 2. Create a C# project
|
||||
|
||||
The first step is creating a new C# project, it must be a **Class Library (.NET Standard)**. The target framework can be any of those compatible with .NET 5, which includes:
|
||||
The first step is creating a new C# project, it must be a **Class Library (.NET Standard)**. The target framework can be any of those compatible with .NET 6, which includes:
|
||||
|
||||
- .NET Standard 2.0
|
||||
- .NET Standard 2.1
|
||||
- .NET 5
|
||||
- .NET 6
|
||||
|
||||
For more information about compatibility, see https://docs.microsoft.com/en-us/dotnet/standard/net-standard.
|
||||
|
||||
> At the moment of writing this document, I recommend you to use **.NET Standard 2.1**. This should give you enough functionality. If not, upgrade to .NET 5.
|
||||
> At the moment of writing this document, I recommend you to use **.NET Standard 2.1**. This should give you enough functionality. If not, upgrade to .NET 6.
|
||||
|
||||
When the project has been created, you should have `Class.cs` and `Project.csproj` files. Your `Project.csproj` should look something like this.
|
||||
|
||||
@@ -336,4 +337,4 @@ Create an issue:
|
||||
- [Suggest a function](https://github.com/Impostor/Impostor/issues/new?template=3--api-suggestion.md)
|
||||
- [Data is invalid](https://github.com/Impostor/Impostor/issues/new?template=4--api-invalid.md)
|
||||
- [Data is unavailable](https://github.com/Impostor/Impostor/issues/new?template=5--api-missing.md)
|
||||
- [Other](https://github.com/Impostor/Impostor/issues/new?template=6--api-other.md)
|
||||
- [Other](https://github.com/Impostor/Impostor/issues/new?template=6--api-other.md)
|
||||
@@ -1,8 +1,10 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.6.0</VersionPrefix>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<VersionPrefix>1.7.2</VersionPrefix>
|
||||
<VersionSuffix>dev</VersionSuffix>
|
||||
<EnforceCodeStyleInBuild Condition="$(MSBuildProjectName)!='Hazel'">true</EnforceCodeStyleInBuild>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class AntiCheatConfig
|
||||
{
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class CompatibilityConfig
|
||||
{
|
||||
public const string Section = "Compatibility";
|
||||
|
||||
public bool AllowFutureGameVersions { get; set; } = false;
|
||||
|
||||
public bool AllowVersionMixing { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class DebugConfig
|
||||
{
|
||||
+6
-1
@@ -1,4 +1,4 @@
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public static class DisconnectMessages
|
||||
{
|
||||
@@ -6,6 +6,11 @@
|
||||
"Check the server console for more information. " +
|
||||
"Please report the issue on the Impostor GitHub if it keeps happening.";
|
||||
|
||||
public const string ClientOutdated = "Please update your game to play in this lobby.";
|
||||
|
||||
public const string ClientTooNew = "Your game version is too new for this lobby. " +
|
||||
"If you want to join this lobby you need to downgrade your client.";
|
||||
|
||||
public const string Destroyed = "The game you tried to join is being destroyed. " +
|
||||
"Please create a new game.";
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
using Impostor.Server.Utils;
|
||||
using Impostor.Api.Utils;
|
||||
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
internal class ServerConfig
|
||||
public class ServerConfig
|
||||
{
|
||||
public const string Section = "Server";
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class ServerRedirectorConfig
|
||||
{
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class ServerRedirectorNode
|
||||
{
|
||||
@@ -1,38 +0,0 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Events.Announcements
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired after client requests a announcement.
|
||||
/// </summary>
|
||||
public interface IAnnouncementRequestEvent : IEvent
|
||||
{
|
||||
public interface IResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether announcement should be loaded from client's cache, can save some bytes.
|
||||
/// </summary>
|
||||
public bool UseCached { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets announcement, should be null when <see cref="UseCached" /> is set to true.
|
||||
/// </summary>
|
||||
public Announcement? Announcement { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets client's last announcement id.
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets client's language.
|
||||
/// </summary>
|
||||
public Language Language { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets plugin made response.
|
||||
/// </summary>
|
||||
public IResponse Response { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,13 @@ namespace Impostor.Api
|
||||
return original[0];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static short ReadInt16(this ref ReadOnlySpan<byte> input)
|
||||
{
|
||||
var original = Advance<short>(ref input);
|
||||
return BinaryPrimitives.ReadInt16LittleEndian(original);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int ReadInt32(this ref ReadOnlySpan<byte> input)
|
||||
{
|
||||
|
||||
@@ -37,6 +37,16 @@
|
||||
/// </summary>
|
||||
GameDestroyed,
|
||||
|
||||
/// <summary>
|
||||
/// The host has a newer version of the game and the client should update.
|
||||
/// </summary>
|
||||
ClientOutdated,
|
||||
|
||||
/// <summary>
|
||||
/// The host has an older version of the game and the client should downgrade.
|
||||
/// </summary>
|
||||
ClientTooNew,
|
||||
|
||||
/// <summary>
|
||||
/// Custom error by a plugin.
|
||||
/// </summary>
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Nullable" Version="1.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public readonly struct Announcement
|
||||
{
|
||||
public readonly int Id;
|
||||
public readonly string Message;
|
||||
|
||||
public Announcement(int id, string message)
|
||||
{
|
||||
Id = id;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum HatType : uint
|
||||
{
|
||||
NoHat = 0,
|
||||
Astronaut = 1,
|
||||
BaseballCap = 2,
|
||||
BrainSlug = 3,
|
||||
BushHat = 4,
|
||||
CaptainsHat = 5,
|
||||
DoubleTopHat = 6,
|
||||
Flowerpot = 7,
|
||||
Goggles = 8,
|
||||
HardHat = 9,
|
||||
Military = 10,
|
||||
PaperHat = 11,
|
||||
PartyHat = 12,
|
||||
Police = 13,
|
||||
Stethescope = 14,
|
||||
TopHat = 15,
|
||||
TowelWizard = 16,
|
||||
Ushanka = 17,
|
||||
Viking = 18,
|
||||
WallCap = 19,
|
||||
Snowman = 20,
|
||||
Reindeer = 21,
|
||||
Lights = 22,
|
||||
Santa = 23,
|
||||
Tree = 24,
|
||||
Present = 25,
|
||||
Candycanes = 26,
|
||||
ElfHat = 27,
|
||||
NewYears2018 = 28,
|
||||
WhiteHat = 29,
|
||||
Crown = 30,
|
||||
Eyebrows = 31,
|
||||
HaloHat = 32,
|
||||
HeroCap = 33,
|
||||
PipCap = 34,
|
||||
PlungerHat = 35,
|
||||
ScubaHat = 36,
|
||||
StickminHat = 37,
|
||||
StrawHat = 38,
|
||||
TenGallonHat = 39,
|
||||
ThirdEyeHat = 40,
|
||||
ToiletPaperHat = 41,
|
||||
Toppat = 42,
|
||||
BlackFedora = 43,
|
||||
SkiGoggles = 44,
|
||||
Headphones = 45,
|
||||
MaskHat = 46,
|
||||
PaperMask = 47,
|
||||
Security = 48,
|
||||
StrapHat = 49,
|
||||
Banana = 50,
|
||||
Beanie = 51,
|
||||
Bear = 52,
|
||||
Cheese = 53,
|
||||
Cherry = 54,
|
||||
Egg = 55,
|
||||
GreenFedora = 56,
|
||||
Flamingo = 57,
|
||||
FlowerPin = 58,
|
||||
Helmet = 59,
|
||||
Plant = 60,
|
||||
BatEyes = 61,
|
||||
BatWings = 62,
|
||||
Horns = 63,
|
||||
Mohawk = 64,
|
||||
Pumpkin = 65,
|
||||
ScaryBag = 66,
|
||||
Witch = 67,
|
||||
Wolf = 68,
|
||||
Pirate = 69,
|
||||
Plague = 70,
|
||||
Machete = 71,
|
||||
Fred = 72,
|
||||
MinerCap = 73,
|
||||
WinterHat = 74,
|
||||
Archae = 75,
|
||||
Antenna = 76,
|
||||
Balloon = 77,
|
||||
BirdNest = 78,
|
||||
BlackBelt = 79,
|
||||
Caution = 80,
|
||||
Chef = 81,
|
||||
CopHat = 82,
|
||||
DoRag = 83,
|
||||
DumSticker = 84,
|
||||
Fez = 85,
|
||||
GeneralHat = 86,
|
||||
GreyThing = 87,
|
||||
HunterCap = 88,
|
||||
JungleHat = 89,
|
||||
MiniCrewmate = 90,
|
||||
NinjaMask = 91,
|
||||
RamHorns = 92,
|
||||
SnowCrewmate = 93,
|
||||
GeoffHat = 94,
|
||||
DaveCap = 95,
|
||||
EllieRose = 96,
|
||||
SvenHat = 97,
|
||||
BurtHat = 98,
|
||||
EllryMohawk = 99,
|
||||
ThomasMonoc = 100,
|
||||
Wizard = 101,
|
||||
Fredrick = 102,
|
||||
MrMacbeth = 103,
|
||||
ToppatHenry = 104,
|
||||
ToppatEllie = 105,
|
||||
GeoffreyPlumb = 106,
|
||||
RightHandMan = 107,
|
||||
AngryEyebrows = 108,
|
||||
ChocolateIce = 109,
|
||||
HeartPin = 110,
|
||||
Ponytail = 111,
|
||||
RubberGlove = 112,
|
||||
UnicornHorn = 113,
|
||||
Zipper = 114,
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum PetType : uint
|
||||
{
|
||||
NoPet = 0,
|
||||
Alien = 1,
|
||||
Crewmate = 2,
|
||||
Doggy = 3,
|
||||
Stickmin = 4,
|
||||
Hamster = 5,
|
||||
Robot = 6,
|
||||
Ufo = 7,
|
||||
Ellie = 8,
|
||||
Squig = 9,
|
||||
Bedcrab = 10,
|
||||
Glitch = 11,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public class PlayerOutfit
|
||||
{
|
||||
public ColorType Color { get; internal set; } = (ColorType)(-1);
|
||||
|
||||
public string HatId { get; internal set; } = "missing";
|
||||
|
||||
public string PetId { get; internal set; } = "missing";
|
||||
|
||||
public string SkinId { get; internal set; } = "missing";
|
||||
|
||||
public string VisorId { get; internal set; } = "missing";
|
||||
|
||||
public string NamePlateId { get; internal set; } = "missing";
|
||||
|
||||
public string PlayerName { get; internal set; } = "missing";
|
||||
|
||||
public bool IsIncomplete
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(PlayerName) && Color != (ColorType)(-1) && HatId != "missing" && PetId != "missing" && SkinId != "missing" && VisorId != "missing")
|
||||
{
|
||||
return NamePlateId == "missing";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(PlayerName);
|
||||
writer.WritePacked((int)Color);
|
||||
writer.Write(HatId);
|
||||
writer.Write(PetId);
|
||||
writer.Write(SkinId);
|
||||
writer.Write(VisorId);
|
||||
writer.Write(NamePlateId);
|
||||
}
|
||||
|
||||
public void Deserialize(IMessageReader reader)
|
||||
{
|
||||
PlayerName = reader.ReadString();
|
||||
Color = (ColorType)reader.ReadPackedInt32();
|
||||
HatId = reader.ReadString();
|
||||
PetId = reader.ReadString();
|
||||
SkinId = reader.ReadString();
|
||||
VisorId = reader.ReadString();
|
||||
NamePlateId = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum PlayerOutfitType
|
||||
{
|
||||
Default,
|
||||
Shapeshifted,
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum SkinType : uint
|
||||
{
|
||||
None = 0,
|
||||
Astro = 1,
|
||||
Capt = 2,
|
||||
Mech = 3,
|
||||
Military = 4,
|
||||
Police = 5,
|
||||
Science = 6,
|
||||
SuitB = 7,
|
||||
SuitW = 8,
|
||||
Wall = 9,
|
||||
Hazmat = 10,
|
||||
Security = 11,
|
||||
Tarmac = 12,
|
||||
Miner = 13,
|
||||
Winter = 14,
|
||||
Archae = 15,
|
||||
Prisoner = 16,
|
||||
CCC = 17,
|
||||
RightHandMan = 18,
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Impostor.Api.Innersloth
|
||||
/// <summary>
|
||||
/// The latest major version of the game client.
|
||||
/// </summary>
|
||||
public const int LatestVersion = 4;
|
||||
public const int LatestVersion = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets host's version of the game.
|
||||
@@ -124,6 +124,11 @@ namespace Impostor.Api.Innersloth
|
||||
/// </summary>
|
||||
public TaskBarUpdate TaskBarUpdate { get; set; } = TaskBarUpdate.Always;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets role options.
|
||||
/// </summary>
|
||||
public RoleOptionsData RoleOptions { get; set; } = new RoleOptionsData();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the GameOptions are the default ones.
|
||||
/// </summary>
|
||||
@@ -166,24 +171,34 @@ namespace Impostor.Api.Innersloth
|
||||
writer.Write((uint)VotingTime);
|
||||
writer.Write((bool)IsDefaults);
|
||||
|
||||
if (version > 1)
|
||||
if (version >= 2)
|
||||
{
|
||||
writer.Write((byte)EmergencyCooldown);
|
||||
}
|
||||
|
||||
if (version > 2)
|
||||
if (version >= 3)
|
||||
{
|
||||
writer.Write((bool)ConfirmImpostor);
|
||||
writer.Write((bool)VisualTasks);
|
||||
}
|
||||
|
||||
if (version > 3)
|
||||
if (version >= 4)
|
||||
{
|
||||
writer.Write((bool)AnonymousVotes);
|
||||
writer.Write((byte)TaskBarUpdate);
|
||||
}
|
||||
|
||||
if (version > 4)
|
||||
if (version >= 5)
|
||||
{
|
||||
RoleOptions.Serialize(writer);
|
||||
}
|
||||
|
||||
if (version >= 6)
|
||||
{
|
||||
// Nothing was changed in V6
|
||||
}
|
||||
|
||||
if (version > 6)
|
||||
{
|
||||
throw new ImpostorException($"Unknown GameOptionsData version {Version}.");
|
||||
}
|
||||
@@ -228,24 +243,34 @@ namespace Impostor.Api.Innersloth
|
||||
|
||||
IsDefaults = bytes.ReadBoolean();
|
||||
|
||||
if (Version > 1)
|
||||
if (Version >= 2)
|
||||
{
|
||||
EmergencyCooldown = bytes.ReadByte();
|
||||
}
|
||||
|
||||
if (Version > 2)
|
||||
if (Version >= 3)
|
||||
{
|
||||
ConfirmImpostor = bytes.ReadBoolean();
|
||||
VisualTasks = bytes.ReadBoolean();
|
||||
}
|
||||
|
||||
if (Version > 3)
|
||||
if (Version >= 4)
|
||||
{
|
||||
AnonymousVotes = bytes.ReadBoolean();
|
||||
TaskBarUpdate = (TaskBarUpdate)bytes.ReadByte();
|
||||
}
|
||||
|
||||
if (Version > 4)
|
||||
if (Version >= 5)
|
||||
{
|
||||
RoleOptions = RoleOptionsData.Deserialize(bytes);
|
||||
}
|
||||
|
||||
if (Version >= 6)
|
||||
{
|
||||
// Nothing was changed in V6
|
||||
}
|
||||
|
||||
if (Version > 6)
|
||||
{
|
||||
throw new ImpostorException($"Unknown GameOptionsData version {Version}.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public class PlatformSpecificData
|
||||
{
|
||||
public PlatformSpecificData(Platforms platform, string platformName, ulong? xboxPlatformId = null, ulong? psnPlatformId = null)
|
||||
{
|
||||
Platform = platform;
|
||||
PlatformName = platformName;
|
||||
XboxPlatformId = xboxPlatformId;
|
||||
PsnPlatformId = psnPlatformId;
|
||||
}
|
||||
|
||||
public PlatformSpecificData(IMessageReader reader)
|
||||
{
|
||||
Platform = (Platforms)reader.Tag;
|
||||
PlatformName = reader.ReadString();
|
||||
|
||||
XboxPlatformId = Platform == Platforms.Xbox ? reader.ReadUInt64() : null;
|
||||
PsnPlatformId = Platform == Platforms.Playstation ? reader.ReadUInt64() : null;
|
||||
}
|
||||
|
||||
public Platforms Platform { get; }
|
||||
|
||||
public string PlatformName { get; }
|
||||
|
||||
public ulong? XboxPlatformId { get; }
|
||||
|
||||
public ulong? PsnPlatformId { get; }
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.StartMessage((byte)Platform);
|
||||
writer.Write(PlatformName);
|
||||
switch (Platform)
|
||||
{
|
||||
case Platforms.Xbox:
|
||||
writer.Write(XboxPlatformId ?? throw new NullReferenceException($"{nameof(XboxPlatformId)} shouldn't be null when {nameof(Platform)} is Xbox"));
|
||||
break;
|
||||
case Platforms.Playstation:
|
||||
writer.Write(PsnPlatformId ?? throw new NullReferenceException($"{nameof(PsnPlatformId)} shouldn't be null when {nameof(Platform)} is Playstation"));
|
||||
break;
|
||||
}
|
||||
|
||||
writer.EndMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,7 @@ namespace Impostor.Api.Innersloth
|
||||
IPhone = 6,
|
||||
Android = 7,
|
||||
Switch = 8,
|
||||
Xbox = 9,
|
||||
Playstation = 10,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public class RoleOptionsData
|
||||
{
|
||||
public bool ShapeshifterLeaveSkin { get; set; }
|
||||
|
||||
public byte ShapeshifterCooldown { get; set; } = 10;
|
||||
|
||||
public byte ShapeshifterDuration { get; set; } = 30;
|
||||
|
||||
public byte ScientistCooldown { get; set; } = 15;
|
||||
|
||||
public byte ScientistBatteryCharge { get; set; } = 5;
|
||||
|
||||
public byte GuardianAngelCooldown { get; set; } = 60;
|
||||
|
||||
public bool ImpostorsCanSeeProtect { get; set; }
|
||||
|
||||
public byte ProtectionDurationSeconds { get; set; } = 10;
|
||||
|
||||
public byte EngineerCooldown { get; set; } = 30;
|
||||
|
||||
public byte EngineerInVentMaxTime { get; set; } = 15;
|
||||
|
||||
public Dictionary<RoleTypes, RoleRate> RoleRates { get; } = new Dictionary<RoleTypes, RoleRate>();
|
||||
|
||||
public static RoleOptionsData Deserialize(ReadOnlySpan<byte> span)
|
||||
{
|
||||
var roleOptionsData = new RoleOptionsData();
|
||||
var num = span.ReadInt32();
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
var key = (RoleTypes)span.ReadInt16();
|
||||
var roleRate = new RoleRate(span.ReadByte(), span.ReadByte());
|
||||
roleOptionsData.RoleRates[key] = roleRate;
|
||||
}
|
||||
|
||||
roleOptionsData.ShapeshifterLeaveSkin = span.ReadBoolean();
|
||||
roleOptionsData.ShapeshifterCooldown = span.ReadByte();
|
||||
roleOptionsData.ShapeshifterDuration = span.ReadByte();
|
||||
roleOptionsData.ScientistCooldown = span.ReadByte();
|
||||
roleOptionsData.GuardianAngelCooldown = span.ReadByte();
|
||||
roleOptionsData.EngineerCooldown = span.ReadByte();
|
||||
roleOptionsData.EngineerInVentMaxTime = span.ReadByte();
|
||||
roleOptionsData.ScientistBatteryCharge = span.ReadByte();
|
||||
roleOptionsData.ProtectionDurationSeconds = span.ReadByte();
|
||||
roleOptionsData.ImpostorsCanSeeProtect = span.ReadBoolean();
|
||||
return roleOptionsData;
|
||||
}
|
||||
|
||||
public static RoleOptionsData Deserialize(IMessageReader reader)
|
||||
{
|
||||
var roleOptionsData = new RoleOptionsData();
|
||||
var num = reader.ReadPackedInt32();
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
var key = (RoleTypes)reader.ReadInt16();
|
||||
var roleRate = new RoleRate(reader.ReadByte(), reader.ReadByte());
|
||||
roleOptionsData.RoleRates[key] = roleRate;
|
||||
}
|
||||
|
||||
roleOptionsData.ShapeshifterLeaveSkin = reader.ReadBoolean();
|
||||
roleOptionsData.ShapeshifterCooldown = reader.ReadByte();
|
||||
roleOptionsData.ShapeshifterDuration = reader.ReadByte();
|
||||
roleOptionsData.ScientistCooldown = reader.ReadByte();
|
||||
roleOptionsData.GuardianAngelCooldown = reader.ReadByte();
|
||||
roleOptionsData.EngineerCooldown = reader.ReadByte();
|
||||
roleOptionsData.EngineerInVentMaxTime = reader.ReadByte();
|
||||
roleOptionsData.ScientistBatteryCharge = reader.ReadByte();
|
||||
roleOptionsData.ProtectionDurationSeconds = reader.ReadByte();
|
||||
roleOptionsData.ImpostorsCanSeeProtect = reader.ReadBoolean();
|
||||
return roleOptionsData;
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.WritePacked(RoleRates.Count);
|
||||
foreach (var roleRate in RoleRates)
|
||||
{
|
||||
writer.Write((ushort)roleRate.Key);
|
||||
writer.Write((byte)roleRate.Value.MaxCount);
|
||||
writer.Write((byte)roleRate.Value.Chance);
|
||||
}
|
||||
|
||||
writer.Write(ShapeshifterLeaveSkin);
|
||||
writer.Write(ShapeshifterCooldown);
|
||||
writer.Write(ShapeshifterDuration);
|
||||
writer.Write(ScientistCooldown);
|
||||
writer.Write(GuardianAngelCooldown);
|
||||
writer.Write(EngineerCooldown);
|
||||
writer.Write(EngineerInVentMaxTime);
|
||||
writer.Write(ScientistBatteryCharge);
|
||||
writer.Write(ProtectionDurationSeconds);
|
||||
writer.Write(ImpostorsCanSeeProtect);
|
||||
}
|
||||
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(RoleRates.Count);
|
||||
foreach (var roleRate in RoleRates)
|
||||
{
|
||||
writer.Write((ushort)roleRate.Key);
|
||||
writer.Write((byte)roleRate.Value.MaxCount);
|
||||
writer.Write((byte)roleRate.Value.Chance);
|
||||
}
|
||||
|
||||
writer.Write(ShapeshifterLeaveSkin);
|
||||
writer.Write(ShapeshifterCooldown);
|
||||
writer.Write(ShapeshifterDuration);
|
||||
writer.Write(ScientistCooldown);
|
||||
writer.Write(GuardianAngelCooldown);
|
||||
writer.Write(EngineerCooldown);
|
||||
writer.Write(EngineerInVentMaxTime);
|
||||
writer.Write(ScientistBatteryCharge);
|
||||
writer.Write(ProtectionDurationSeconds);
|
||||
writer.Write(ImpostorsCanSeeProtect);
|
||||
}
|
||||
|
||||
public readonly struct RoleRate
|
||||
{
|
||||
public readonly int MaxCount;
|
||||
public readonly int Chance;
|
||||
|
||||
public RoleRate(int maxCount, int chance)
|
||||
{
|
||||
MaxCount = maxCount;
|
||||
Chance = chance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public enum RoleTypes : ushort
|
||||
{
|
||||
Crewmate,
|
||||
Impostor,
|
||||
Scientist,
|
||||
Engineer,
|
||||
GuardianAngel,
|
||||
Shapeshifter,
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,19 @@
|
||||
{
|
||||
public static bool IsCharAllowed(char i)
|
||||
{
|
||||
return i == ' ' || (i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') || (i >= '0' && i <= '9') || (i >= 'À' && i <= 'ÿ') || (i >= 'Ѐ' && i <= 'џ') || (i >= 'ㄱ' && i <= 'ㆎ') || (i >= '가' && i <= '힣');
|
||||
return i == ' ' ||
|
||||
(i >= 'A' && i <= 'Z') ||
|
||||
(i >= 'a' && i <= 'z') ||
|
||||
(i >= '0' && i <= '9') ||
|
||||
|
||||
// U+00C0 to U+00FF (Latin-1 Supplement)
|
||||
(i >= 'À' && i <= 'ÿ') ||
|
||||
|
||||
// U+0400 to U+045F (Cyrillic)
|
||||
(i >= 'Ѐ' && i <= 'џ') ||
|
||||
|
||||
// U+2C61 to U+D7A3 (CJK)
|
||||
(i >= 'ⱡ' && i <= '힣');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net.Messages;
|
||||
@@ -65,6 +65,16 @@ namespace Impostor.Api.Net
|
||||
/// </summary>
|
||||
IClientPlayer? Player { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of the game the client is using.
|
||||
/// </summary>
|
||||
int GameVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets platform specific data of the <see cref="IClient" />.
|
||||
/// </summary>
|
||||
PlatformSpecificData PlatformSpecificData { get; }
|
||||
|
||||
ValueTask<bool> ReportCheatAsync(CheatContext context, string message);
|
||||
|
||||
ValueTask HandleMessageAsync(IMessageReader message, MessageType messageType);
|
||||
|
||||
@@ -49,25 +49,25 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
/// Sets the hat of the current <see cref="IInnerPlayerControl" />.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="hatType">An hat for the player.</param>
|
||||
/// <param name="hatId">An hat for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetHatAsync(HatType hatType);
|
||||
ValueTask SetHatAsync(string hatId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pet of the current <see cref="IInnerPlayerControl" />.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="petType">A pet for the player.</param>
|
||||
/// <param name="petId">A pet for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetPetAsync(PetType petType);
|
||||
ValueTask SetPetAsync(string petId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the skin of the current <see cref="IInnerPlayerControl" />.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="skinType">A skin for the player.</param>
|
||||
/// <param name="skinId">A skin for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetSkinAsync(SkinType skinType);
|
||||
ValueTask SetSkinAsync(string skinId);
|
||||
|
||||
/// <summary>
|
||||
/// Send a chat message as the current <see cref="IInnerPlayerControl" />.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
@@ -12,26 +12,6 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
/// </summary>
|
||||
string PlayerName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color of the player.
|
||||
/// </summary>
|
||||
ColorType Color { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hat of the player.
|
||||
/// </summary>
|
||||
HatType Hat { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pet of the player.
|
||||
/// </summary>
|
||||
PetType Pet { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the skin of the player.
|
||||
/// </summary>
|
||||
SkinType Skin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the player is an impostor.
|
||||
/// </summary>
|
||||
@@ -42,6 +22,12 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
/// </summary>
|
||||
bool IsDead { get; }
|
||||
|
||||
Dictionary<PlayerOutfitType, PlayerOutfit> Outfits { get; }
|
||||
|
||||
PlayerOutfitType CurrentOutfitType { get; set; }
|
||||
|
||||
PlayerOutfit CurrentOutfit { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason why the player is dead in the current game.
|
||||
/// </summary>
|
||||
@@ -50,5 +36,7 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
IEnumerable<ITaskInfo> Tasks { get; }
|
||||
|
||||
DateTimeOffset LastMurder { get; }
|
||||
|
||||
uint PlayerLevel { get; }
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
{
|
||||
uint Id { get; }
|
||||
|
||||
ITask Task { get; }
|
||||
ITask? Task { get; }
|
||||
|
||||
bool Complete { get; }
|
||||
|
||||
|
||||
@@ -11,15 +11,12 @@
|
||||
SetName = 6,
|
||||
CheckColor = 7,
|
||||
SetColor = 8,
|
||||
SetHat = 9,
|
||||
SetSkin = 10,
|
||||
ReportDeadBody = 11,
|
||||
MurderPlayer = 12,
|
||||
SendChat = 13,
|
||||
StartMeeting = 14,
|
||||
SetScanner = 15,
|
||||
SendChatNote = 16,
|
||||
SetPet = 17,
|
||||
SetStartCounter = 18,
|
||||
EnterVent = 19,
|
||||
ExitVent = 20,
|
||||
@@ -37,5 +34,16 @@
|
||||
SendQuickChat = 33,
|
||||
BootFromVent = 34,
|
||||
UpdateSystem = 35,
|
||||
SetLevel = 38,
|
||||
SetHat = 39,
|
||||
SetSkin = 40,
|
||||
SetPet = 41,
|
||||
SetVisor = 42,
|
||||
SetNamePlate = 43,
|
||||
SetRole = 44,
|
||||
ProtectPlayer = 45,
|
||||
Shapeshift = 46,
|
||||
CheckMurder = 47,
|
||||
CheckProtect = 48,
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public static class Message00UseCache
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.StartMessage(AnnouncementsMessageFlags.UseCache);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public static class Message01Update
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, int id, string message)
|
||||
{
|
||||
writer.StartMessage(AnnouncementsMessageFlags.SetUpdate);
|
||||
writer.WritePacked(id);
|
||||
writer.Write(message);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out int id, out string message)
|
||||
{
|
||||
id = reader.ReadPackedInt32();
|
||||
message = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public static class Message04AddLanguages
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, Dictionary<string, uint> languages)
|
||||
{
|
||||
writer.StartMessage(AnnouncementsMessageFlags.AddLanguages);
|
||||
|
||||
writer.Write((byte)languages.Count);
|
||||
foreach (var (name, id) in languages)
|
||||
{
|
||||
writer.Write(name);
|
||||
writer.Write(id);
|
||||
}
|
||||
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out Dictionary<string, uint> languages)
|
||||
{
|
||||
var length = reader.ReadByte();
|
||||
languages = new Dictionary<string, uint>(length);
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
languages[reader.ReadString()] = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public class MessageHello
|
||||
{
|
||||
public static void Deserialize(IMessageReader reader, out int announcementVersion, out int id, out Language language)
|
||||
{
|
||||
reader.ReadByte(); // SendOption header, probably added by accident
|
||||
announcementVersion = reader.ReadPackedInt32();
|
||||
id = reader.ReadPackedInt32();
|
||||
language = (Language)reader.ReadPackedInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Impostor.Api.Net.Messages
|
||||
{
|
||||
public class AnnouncementsMessageFlags
|
||||
{
|
||||
public const byte UseCache = 0;
|
||||
public const byte SetUpdate = 1;
|
||||
public const byte AddLanguages = 4;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Impostor.Api.Net.Messages.Auth
|
||||
{
|
||||
public static class Message01Complete
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, uint nonce)
|
||||
{
|
||||
writer.WritePacked(nonce);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out uint nonce)
|
||||
{
|
||||
nonce = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Auth
|
||||
{
|
||||
public static class MessageHandshake
|
||||
{
|
||||
public static void Deserialize(IMessageReader reader, out int clientVersion, out Platforms platform, out string clientId)
|
||||
{
|
||||
clientVersion = reader.ReadInt32();
|
||||
platform = (Platforms)reader.ReadByte();
|
||||
clientId = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,14 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
{
|
||||
public static class HandshakeC2S
|
||||
{
|
||||
public static void Deserialize(IMessageReader reader, out int clientVersion, out string name, out uint? lastNonceReceived, out Language language, out QuickChatModes chatMode)
|
||||
public static void Deserialize(IMessageReader reader, out int clientVersion, out string name, out Language language, out QuickChatModes chatMode, out PlatformSpecificData? platformSpecificData)
|
||||
{
|
||||
clientVersion = reader.ReadInt32();
|
||||
name = reader.ReadString();
|
||||
|
||||
if (clientVersion >= Version.V1)
|
||||
{
|
||||
lastNonceReceived = reader.ReadUInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
lastNonceReceived = null;
|
||||
reader.ReadUInt32(); // lastNonceReceived, always 0 since 2021.11.9
|
||||
}
|
||||
|
||||
if (clientVersion >= Version.V2)
|
||||
@@ -28,6 +24,22 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
language = Language.English;
|
||||
chatMode = QuickChatModes.FreeChatOrQuickChat;
|
||||
}
|
||||
|
||||
if (clientVersion >= Version.V3)
|
||||
{
|
||||
using var platformReader = reader.ReadMessage();
|
||||
platformSpecificData = new PlatformSpecificData(platformReader);
|
||||
reader.ReadInt32(); // crossplayFlags, not used yet
|
||||
}
|
||||
else
|
||||
{
|
||||
platformSpecificData = null;
|
||||
}
|
||||
|
||||
if (clientVersion >= Version.V4)
|
||||
{
|
||||
reader.ReadByte(); // purpose unknown, seems hardcoded to 0
|
||||
}
|
||||
}
|
||||
|
||||
private static class Version
|
||||
@@ -35,6 +47,10 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
public static readonly int V1 = GameVersion.GetVersion(2021, 4, 25);
|
||||
|
||||
public static readonly int V2 = GameVersion.GetVersion(2021, 6, 30);
|
||||
|
||||
public static readonly int V3 = GameVersion.GetVersion(2021, 11, 9);
|
||||
|
||||
public static readonly int V4 = GameVersion.GetVersion(2021, 12, 14);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
{
|
||||
writer.StartMessage(MessageFlags.HostGame);
|
||||
gameOptionsData.Serialize(writer);
|
||||
writer.Write(int.MaxValue); // crossplayFlags
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
@@ -15,12 +16,11 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
/// Deserialize a packet.
|
||||
/// </summary>
|
||||
/// <param name="reader"><see cref="IMessageReader" /> with <see cref="IMessageReader.Tag" /> 0.</param>
|
||||
/// <param name="chatMode">The chat type selected in the client of the player.</param>
|
||||
/// <returns>Deserialized <see cref="GameOptionsData" />.</returns>
|
||||
public static GameOptionsData Deserialize(IMessageReader reader, out QuickChatModes chatMode)
|
||||
public static GameOptionsData Deserialize(IMessageReader reader)
|
||||
{
|
||||
var gameOptionsData = GameOptionsData.DeserializeCreate(reader);
|
||||
chatMode = (QuickChatModes)reader.ReadByte();
|
||||
reader.ReadInt32(); // crossplayFlags, not used yet
|
||||
|
||||
return gameOptionsData;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
public static void Deserialize(IMessageReader reader, out GameCode gameCode)
|
||||
{
|
||||
gameCode = reader.ReadInt32();
|
||||
reader.ReadBoolean(); // no crossplay
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,15 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out GameOptionsData options, out QuickChatModes chatMode)
|
||||
{
|
||||
reader.ReadPackedInt32(); // Hardcoded 0.
|
||||
var version = reader.ReadPackedInt32();
|
||||
if (version != 2)
|
||||
{
|
||||
throw new NotSupportedException($"Version {version} of {nameof(Message16GetGameListC2S)} is not supported");
|
||||
}
|
||||
|
||||
options = GameOptionsData.DeserializeCreate(reader);
|
||||
chatMode = (QuickChatModes)reader.ReadByte();
|
||||
reader.ReadInt32(); // crossplayFlags, not used yet
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.C2S
|
||||
{
|
||||
public class Message21SetActivePodType
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string podType)
|
||||
{
|
||||
podType = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Impostor.Api.Games;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.C2S
|
||||
{
|
||||
public class Message22QueryPlatformIdsC2S
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out GameCode gameCode)
|
||||
{
|
||||
gameCode = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,10 @@ namespace Impostor.Api.Net.Messages
|
||||
|
||||
int ReadInt32();
|
||||
|
||||
ulong ReadUInt64();
|
||||
|
||||
long ReadInt64();
|
||||
|
||||
float ReadSingle();
|
||||
|
||||
string ReadString(int length);
|
||||
|
||||
@@ -68,6 +68,18 @@ namespace Impostor.Api.Net.Messages
|
||||
/// <param name="value">Value to write.</param>
|
||||
void Write(int value);
|
||||
|
||||
/// <summary>
|
||||
/// Writes an ulong to the message.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
void Write(ulong value);
|
||||
|
||||
/// <summary>
|
||||
/// Writes an ulong to the message.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
void Write(long value);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a float to the message.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,7 +16,13 @@
|
||||
public const byte WaitForHost = 12;
|
||||
public const byte Redirect = 13;
|
||||
public const byte ReselectServer = 14;
|
||||
public const byte GetGameList = 9;
|
||||
public const byte GetGameListV2 = 16;
|
||||
public const byte ReportPlayer = 17;
|
||||
public const byte QuickMatch = 18;
|
||||
public const byte QuickMatchHost = 19;
|
||||
public const byte SetGameSession = 20;
|
||||
public const byte SetActivePodType = 21;
|
||||
public const byte QueryPlatformIds = 22;
|
||||
public const byte QueryLobbyInfo = 23;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc09SetHat
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, HatType hat)
|
||||
{
|
||||
writer.WritePacked((uint)hat);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out HatType hat)
|
||||
{
|
||||
hat = (HatType)reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc10SetSkin
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, SkinType skin)
|
||||
{
|
||||
writer.WritePacked((uint)skin);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out SkinType skin)
|
||||
{
|
||||
skin = (SkinType)reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc17SetPet
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, PetType pet)
|
||||
{
|
||||
writer.WritePacked((uint)pet);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out PetType pet)
|
||||
{
|
||||
pet = (PetType)reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc39SetHat
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string hat)
|
||||
{
|
||||
writer.Write(hat);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string hat)
|
||||
{
|
||||
hat = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc40SetSkin
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string skin)
|
||||
{
|
||||
writer.Write(skin);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string skin)
|
||||
{
|
||||
skin = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc41SetPet
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string pet)
|
||||
{
|
||||
writer.Write(pet);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string pet)
|
||||
{
|
||||
pet = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc44SetRole
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, RoleTypes role)
|
||||
{
|
||||
writer.Write((ushort)role);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out RoleTypes role)
|
||||
{
|
||||
role = (RoleTypes)reader.ReadUInt16();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc45ProtectPlayer
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, IInnerPlayerControl playerControl, ColorType color)
|
||||
{
|
||||
writer.Write(playerControl.NetId);
|
||||
writer.Write((byte)color);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IGame game, out IInnerPlayerControl? playerControl, out ColorType color)
|
||||
{
|
||||
playerControl = reader.ReadNetObject<IInnerPlayerControl>(game);
|
||||
color = (ColorType)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc46Shapeshift
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, IInnerPlayerControl playerControl, bool shouldAnimate)
|
||||
{
|
||||
writer.Write(playerControl.NetId);
|
||||
writer.Write(shouldAnimate);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IGame game, out IInnerPlayerControl? playerControl, out bool shouldAnimate)
|
||||
{
|
||||
playerControl = reader.ReadNetObject<IInnerPlayerControl>(game);
|
||||
shouldAnimate = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc47CheckMurder
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, IInnerPlayerControl playerControl)
|
||||
{
|
||||
writer.Write(playerControl.NetId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IGame game, out IInnerPlayerControl? playerControl)
|
||||
{
|
||||
playerControl = reader.ReadNetObject<IInnerPlayerControl>(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc48CheckProtect
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, IInnerPlayerControl playerControl)
|
||||
{
|
||||
writer.Write(playerControl.NetId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IGame game, out IInnerPlayerControl? playerControl)
|
||||
{
|
||||
playerControl = reader.ReadNetObject<IInnerPlayerControl>(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.S2C
|
||||
{
|
||||
public class Message01JoinGameS2C
|
||||
{
|
||||
public static void SerializeJoin(IMessageWriter writer, bool clear, int gameCode, int playerId, int hostId)
|
||||
public static void SerializeJoin(IMessageWriter writer, bool clear, int gameCode, IClientPlayer player, int hostId)
|
||||
{
|
||||
if (clear)
|
||||
{
|
||||
@@ -14,11 +14,19 @@ namespace Impostor.Api.Net.Messages.S2C
|
||||
|
||||
writer.StartMessage(MessageFlags.JoinGame);
|
||||
writer.Write(gameCode);
|
||||
writer.Write(playerId);
|
||||
writer.Write(player.Client.Id);
|
||||
writer.Write(hostId);
|
||||
writer.Write(player.Client.Name);
|
||||
player.Client.PlatformSpecificData.Serialize(writer);
|
||||
writer.WritePacked(player.Character?.PlayerInfo.PlayerLevel ?? 1);
|
||||
|
||||
// ProductUserId and FriendCode are not yet known, so set them to an empty string
|
||||
writer.Write(string.Empty);
|
||||
writer.Write(string.Empty);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
[Obsolete("JoinGame errors are no longer used by 2021.11.9 and up, disconnect clients instead.")]
|
||||
public static void SerializeError(IMessageWriter writer, bool clear, DisconnectReason reason, string? message = null)
|
||||
{
|
||||
if (clear)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.S2C
|
||||
{
|
||||
public static class Message07JoinedGameS2C
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, bool clear, int gameCode, int playerId, int hostId, int[] otherPlayerIds)
|
||||
public static void Serialize(IMessageWriter writer, bool clear, int gameCode, int playerId, int hostId, IClientPlayer[] otherPlayers, bool post20220202 = true)
|
||||
{
|
||||
if (clear)
|
||||
{
|
||||
@@ -15,11 +15,21 @@ namespace Impostor.Api.Net.Messages.S2C
|
||||
writer.Write(gameCode);
|
||||
writer.Write(playerId);
|
||||
writer.Write(hostId);
|
||||
writer.WritePacked(otherPlayerIds.Length);
|
||||
writer.WritePacked(otherPlayers.Length);
|
||||
|
||||
foreach (var id in otherPlayerIds)
|
||||
foreach (var ply in otherPlayers)
|
||||
{
|
||||
writer.WritePacked(id);
|
||||
writer.WritePacked(ply.Client.Id);
|
||||
writer.Write(ply.Client.Name);
|
||||
ply.Client.PlatformSpecificData.Serialize(writer);
|
||||
writer.WritePacked(ply.Character?.PlayerInfo.PlayerLevel ?? 1);
|
||||
|
||||
if (post20220202)
|
||||
{
|
||||
// ProductUserId and FriendCode are not yet known, so set them to an empty string
|
||||
writer.Write(string.Empty);
|
||||
writer.Write(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
writer.EndMessage();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Games;
|
||||
|
||||
@@ -25,6 +25,10 @@ namespace Impostor.Api.Net.Messages.S2C
|
||||
writer.Write((byte)game.Options.Map);
|
||||
writer.Write((byte)game.Options.NumImpostors);
|
||||
writer.Write((byte)game.Options.MaxPlayers);
|
||||
var platform = game.Host?.Client.PlatformSpecificData;
|
||||
writer.Write((byte)(platform?.Platform ?? 0));
|
||||
writer.Write(platform?.PlatformName ?? string.Empty);
|
||||
writer.Write((uint)game.Options.Keywords);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.S2C
|
||||
{
|
||||
public class Message22QueryPlatformIdsS2C
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, GameCode gameCode, IEnumerable<PlatformSpecificData> playerSpecificDatas)
|
||||
{
|
||||
writer.StartMessage(MessageFlags.QueryPlatformIds);
|
||||
writer.Write(gameCode);
|
||||
foreach (var playerSpecificData in playerSpecificDatas)
|
||||
{
|
||||
playerSpecificData.Serialize(writer);
|
||||
}
|
||||
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace Impostor.Api.Net.Messages.S2C
|
||||
|
||||
if (hasReason)
|
||||
{
|
||||
var inner = reader.ReadMessage();
|
||||
using var inner = reader.ReadMessage();
|
||||
reason = (DisconnectReason)inner.ReadByte();
|
||||
message = reason == DisconnectReason.Custom ? inner.ReadString() : null;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Impostor.Api;
|
||||
|
||||
namespace Impostor.Server.Utils
|
||||
namespace Impostor.Api.Utils
|
||||
{
|
||||
internal static class IpUtils
|
||||
{
|
||||
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
".NETStandard,Version=v2.1": {
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[6.0.1, )",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Nullable": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.3.0, )",
|
||||
"resolved": "1.3.0",
|
||||
"contentHash": "xHAviTdTY3n+t1nEPN4JPRQR5lI124qRKVw+U9H7dO5sDNPpzoWeo/MQy7dSUmv9eD3k/CJVKokz1tFK+JOzRw=="
|
||||
},
|
||||
"StyleCop.Analyzers": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.1.118, )",
|
||||
"resolved": "1.1.118",
|
||||
"contentHash": "Onx6ovGSqXSK07n/0eM3ZusiNdB6cIlJdabQhWGgJp3Vooy9AaLS/tigeybOJAobqbtggTamoWndz72JscZBvw=="
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.4",
|
||||
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,11 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,7 +2,6 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -10,7 +9,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net6.0": {
|
||||
"Serilog.Sinks.Console": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.0.1, )",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==",
|
||||
"dependencies": {
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg=="
|
||||
},
|
||||
"Microsoft.Extensions.ObjectPool": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "mOhbL7mbV9sEMQ0G+MUOR9mx+cLTL25jcTXaFYe14hX/4+VuchVgNi7FqSQyLYLPNuGJOm/Puc1ZsSgjr+0LVA=="
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.10.0",
|
||||
"contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"hazel": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Api": "1.7.1-dev",
|
||||
"Microsoft.Extensions.ObjectPool": "5.0.0",
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "6.0.1"
|
||||
}
|
||||
},
|
||||
"impostor.client": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Hazel": "1.7.1-dev",
|
||||
"Impostor.Api": "1.7.1-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
|
||||
<ProjectReference Include="..\Impostor.Hazel\Hazel\Hazel.csproj" />
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net6.0": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg=="
|
||||
},
|
||||
"Microsoft.Extensions.ObjectPool": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "mOhbL7mbV9sEMQ0G+MUOR9mx+cLTL25jcTXaFYe14hX/4+VuchVgNi7FqSQyLYLPNuGJOm/Puc1ZsSgjr+0LVA=="
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.10.0",
|
||||
"contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"hazel": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Impostor.Api": "1.7.1-dev",
|
||||
"Microsoft.Extensions.ObjectPool": "5.0.0",
|
||||
"Serilog": "2.10.0"
|
||||
}
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "6.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
Submodule src/Impostor.Hazel updated: 8de027461e...74070b8c07.
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
<Version>1.0.0</Version>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net6.0": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg=="
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "6.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ namespace Impostor.Plugins.Example
|
||||
services.AddSingleton<IEventListener, ClientEventListener>();
|
||||
services.AddSingleton<IEventListener, PlayerEventListener>();
|
||||
services.AddSingleton<IEventListener, MeetingEventListener>();
|
||||
services.AddSingleton<IEventListener, AnnouncementsListener>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using Impostor.Api.Events;
|
||||
using Impostor.Api.Events.Announcements;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Plugins.Example.Handlers
|
||||
{
|
||||
public class AnnouncementsListener : IEventListener
|
||||
{
|
||||
private const int Id = 50;
|
||||
|
||||
[EventListener]
|
||||
public void OnAnnouncementRequestEvent(IAnnouncementRequestEvent e)
|
||||
{
|
||||
if (e.Id == Id)
|
||||
{
|
||||
// Client already has announcement cached, lets just use that
|
||||
e.Response.UseCached = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Client is receiving this announcement for the first time, window will popup
|
||||
e.Response.Announcement = new Announcement(Id, "Hello!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,9 +40,10 @@ namespace Impostor.Plugins.Example.Handlers
|
||||
{
|
||||
// Modify player properties.
|
||||
await playerControl.SetColorAsync((ColorType)_random.Next(1, 9));
|
||||
await playerControl.SetHatAsync((HatType)_random.Next(1, 9));
|
||||
await playerControl.SetSkinAsync((SkinType)_random.Next(1, 9));
|
||||
await playerControl.SetPetAsync((PetType)_random.Next(1, 9));
|
||||
// TODO Rewrite using cosmetics source generator
|
||||
// await playerControl.SetHatAsync((HatType)_random.Next(1, 9));
|
||||
// await playerControl.SetSkinAsync((SkinType)_random.Next(1, 9));
|
||||
// await playerControl.SetPetAsync((PetType)_random.Next(1, 9));
|
||||
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(5000));
|
||||
}
|
||||
@@ -74,9 +75,9 @@ namespace Impostor.Plugins.Example.Handlers
|
||||
if (e.Message == "look")
|
||||
{
|
||||
await e.PlayerControl.SetColorAsync(ColorType.Pink);
|
||||
await e.PlayerControl.SetHatAsync(HatType.Cheese);
|
||||
await e.PlayerControl.SetSkinAsync(SkinType.Police);
|
||||
await e.PlayerControl.SetPetAsync(PetType.Ufo);
|
||||
await e.PlayerControl.SetHatAsync("hat_pk05_Cheese");
|
||||
await e.PlayerControl.SetSkinAsync("skin_Police");
|
||||
await e.PlayerControl.SetPetAsync("pet_alien1");
|
||||
}
|
||||
|
||||
if (e.Message == "snap")
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
".NETStandard,Version=v2.1": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.4",
|
||||
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"impostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "6.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Impostor.Server.Utils;
|
||||
|
||||
namespace Impostor.Server.Config
|
||||
{
|
||||
internal class AnnouncementsServerConfig
|
||||
{
|
||||
public const string Section = "AnnouncementsServer";
|
||||
|
||||
private string? _resolvedListenIp;
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public string ListenIp { get; set; } = "0.0.0.0";
|
||||
|
||||
public ushort ListenPort { get; set; } = 22024;
|
||||
|
||||
public string ResolveListenIp()
|
||||
{
|
||||
return _resolvedListenIp ??= IpUtils.ResolveIp(ListenIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.IO;
|
||||
using Impostor.Server.Utils;
|
||||
|
||||
namespace Impostor.Server.Config
|
||||
{
|
||||
internal class AuthServerConfig
|
||||
{
|
||||
public const string Section = "AuthServer";
|
||||
|
||||
private string? _resolvedListenIp;
|
||||
|
||||
public bool Enabled { get; set; } = false;
|
||||
|
||||
public string ListenIp { get; set; } = "0.0.0.0";
|
||||
|
||||
public ushort ListenPort { get; set; } = 22025;
|
||||
|
||||
public string Certificate { get; set; } = Path.Combine("dtls", "certificate.pem");
|
||||
|
||||
public string PrivateKey { get; set; } = Path.Combine("dtls", "key.pem");
|
||||
|
||||
public string ResolveListenIp()
|
||||
{
|
||||
return _resolvedListenIp ??= IpUtils.ResolveIp(ListenIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using Impostor.Api.Events.Announcements;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Server.Events.Announcements
|
||||
{
|
||||
public class AnnouncementRequestEvent : IAnnouncementRequestEvent
|
||||
{
|
||||
public AnnouncementRequestEvent(int id, Language language)
|
||||
{
|
||||
Id = id;
|
||||
Language = language;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
|
||||
public Language Language { get; }
|
||||
|
||||
public IAnnouncementRequestEvent.IResponse Response { get; set; } = new AnnouncementResponse();
|
||||
|
||||
public class AnnouncementResponse : IAnnouncementRequestEvent.IResponse
|
||||
{
|
||||
public bool UseCached { get; set; } = false;
|
||||
|
||||
public Announcement? Announcement { get; set; } = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages.S2C;
|
||||
using Impostor.Hazel;
|
||||
|
||||
namespace Impostor.Server
|
||||
{
|
||||
public static class IHazelConnectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Disconnect a connection using a custom message.
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection to disconnect.</param>
|
||||
/// <param name="reason">The reason to disconnect with.</param>
|
||||
/// <param name="message">The custom message to disconnect with if <paramref name="reason"/> is <see cref="DisconnectReason.Custom"/>.</param>
|
||||
/// <returns>Task that should be awaited to ensure disconnection.</returns>
|
||||
public static async ValueTask CustomDisconnectAsync(this IHazelConnection connection, DisconnectReason reason, string? message = null)
|
||||
{
|
||||
if (!connection.IsConnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var writer = MessageWriter.Get();
|
||||
MessageDisconnect.Serialize(writer, true, reason, message);
|
||||
|
||||
await connection.DisconnectAsync(reason.ToString(), writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
@@ -25,18 +24,19 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.4" />
|
||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.333">
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="6.0.5" />
|
||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.2.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.435">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!-- HACK: Some plugins depend on System.IO.Pipelines and expect the version to be 5.0.0.0, but .NET 5 only ships version 5.0.0.1. It is pretty hard to convince MSBuild to build against the correct DLL, so we special case it here. Remove once we move past .NET 5 -->
|
||||
<PackageReference Include="System.IO.Pipelines" Version="5.0.0" />
|
||||
<!-- HACK: Some plugins depend on System.IO.Pipelines and expect the version to be 6.0.0.0, but Hazel still depends on version 5.0.0.0. Figure out why this happens. -->
|
||||
<PackageReference Include="System.IO.Pipelines" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Events.Managers;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.Announcements;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Hazel.Udp;
|
||||
using Impostor.Server.Config;
|
||||
using Impostor.Server.Events.Announcements;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Impostor.Server.Net
|
||||
{
|
||||
internal class AnnouncementsService : IHostedService
|
||||
{
|
||||
private readonly ILogger<AnnouncementsService> _logger;
|
||||
private readonly AnnouncementsServerConfig _config;
|
||||
private readonly ObjectPool<MessageReader> _readerPool;
|
||||
private readonly IEventManager _eventManager;
|
||||
private UdpConnectionListener? _connection;
|
||||
|
||||
public AnnouncementsService(ILogger<AnnouncementsService> logger, IOptions<AnnouncementsServerConfig> config, ObjectPool<MessageReader> readerPool, IEventManager eventManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config.Value;
|
||||
_readerPool = readerPool;
|
||||
_eventManager = eventManager;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var endpoint = new IPEndPoint(IPAddress.Parse(_config.ResolveListenIp()), _config.ListenPort);
|
||||
|
||||
var mode = endpoint.AddressFamily switch
|
||||
{
|
||||
AddressFamily.InterNetwork => IPMode.IPv4,
|
||||
AddressFamily.InterNetworkV6 => IPMode.IPv6,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
|
||||
_connection = new UdpConnectionListener(endpoint, _readerPool, mode)
|
||||
{
|
||||
NewConnection = OnNewConnection,
|
||||
};
|
||||
|
||||
await _connection.StartAsync();
|
||||
|
||||
_logger.LogInformation("Announcements server is listening on {Address}:{Port}", endpoint.Address, endpoint.Port);
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogWarning("Announcements server is shutting down!");
|
||||
|
||||
if (_connection != null)
|
||||
{
|
||||
await _connection.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask OnNewConnection(NewConnectionEventArgs e)
|
||||
{
|
||||
MessageHello.Deserialize(e.HandshakeData, out var announcementVersion, out var id, out var language);
|
||||
|
||||
_logger.LogDebug("Client requested announcement (version: {Version}, id: {Id}, language: {Language})", announcementVersion, id, language);
|
||||
|
||||
if (announcementVersion != 2)
|
||||
{
|
||||
await e.Connection.Disconnect("Unsupported announcement version");
|
||||
return;
|
||||
}
|
||||
|
||||
var @event = new AnnouncementRequestEvent(id, language);
|
||||
await _eventManager.CallAsync(@event);
|
||||
|
||||
var response = @event.Response;
|
||||
|
||||
if (response.UseCached)
|
||||
{
|
||||
using var writer = MessageWriter.Get(MessageType.Reliable);
|
||||
Message00UseCache.Serialize(writer);
|
||||
await e.Connection.SendAsync(writer);
|
||||
|
||||
_logger.LogDebug("Sent UseCache response");
|
||||
}
|
||||
|
||||
if (response.Announcement != null)
|
||||
{
|
||||
using var writer = MessageWriter.Get(MessageType.Reliable);
|
||||
var announcement = response.Announcement.Value;
|
||||
Message01Update.Serialize(writer, announcement.Id, announcement.Message);
|
||||
await e.Connection.SendAsync(writer);
|
||||
|
||||
_logger.LogDebug("Sent ({Id}) {Message}", announcement.Id, announcement.Message);
|
||||
}
|
||||
|
||||
await e.Connection.Disconnect(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Events.Managers;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.Auth;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Hazel.Dtls;
|
||||
using Impostor.Server.Config;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Impostor.Server.Net
|
||||
{
|
||||
internal class AuthService : IHostedService
|
||||
{
|
||||
private readonly ILogger<AuthService> _logger;
|
||||
private readonly AuthServerConfig _config;
|
||||
private readonly ObjectPool<MessageReader> _readerPool;
|
||||
private readonly IEventManager _eventManager;
|
||||
private DtlsConnectionListener? _connection;
|
||||
|
||||
public AuthService(ILogger<AuthService> logger, IOptions<AuthServerConfig> config, ObjectPool<MessageReader> readerPool, IEventManager eventManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config.Value;
|
||||
_readerPool = readerPool;
|
||||
_eventManager = eventManager;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var endpoint = new IPEndPoint(IPAddress.Parse(_config.ResolveListenIp()), _config.ListenPort);
|
||||
|
||||
var mode = endpoint.AddressFamily switch
|
||||
{
|
||||
AddressFamily.InterNetwork => IPMode.IPv4,
|
||||
AddressFamily.InterNetworkV6 => IPMode.IPv6,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
|
||||
var rsa = RSA.Create();
|
||||
rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(string.Join(string.Empty, (await File.ReadAllLinesAsync(_config.PrivateKey, cancellationToken)).Where(x => !x.StartsWith("-----")))), out _);
|
||||
var cert = new X509Certificate2(_config.Certificate).CopyWithPrivateKey(rsa);
|
||||
|
||||
_connection = new DtlsConnectionListener(endpoint, _readerPool, mode);
|
||||
_connection.SetCertificate(cert);
|
||||
_connection.NewConnection = ConnectionOnNewConnection;
|
||||
|
||||
await _connection.StartAsync();
|
||||
|
||||
_logger.LogInformation("Auth server is listening on {Address}:{Port}", endpoint.Address, endpoint.Port);
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogWarning("Auth server is shutting down!");
|
||||
|
||||
if (_connection != null)
|
||||
{
|
||||
await _connection.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private ValueTask ConnectionOnNewConnection(NewConnectionEventArgs e)
|
||||
{
|
||||
MessageHandshake.Deserialize(e.HandshakeData, out var clientVersion, out var platform, out var clientId);
|
||||
|
||||
_logger.LogTrace("New authentication request: {clientVersion}, {platform}, {clientId}", clientVersion, platform, clientId);
|
||||
|
||||
using var writer = MessageWriter.Get(MessageType.Reliable);
|
||||
|
||||
writer.StartMessage(1);
|
||||
Message01Complete.Serialize(writer, (uint)RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue));
|
||||
writer.EndMessage();
|
||||
|
||||
return e.Connection.SendAsync(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Config;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
@@ -9,7 +11,6 @@ using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.C2S;
|
||||
using Impostor.Api.Net.Messages.S2C;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Server.Config;
|
||||
using Impostor.Server.Net.Manager;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -24,8 +25,8 @@ namespace Impostor.Server.Net
|
||||
private readonly GameManager _gameManager;
|
||||
private readonly ICustomMessageManager<ICustomRootMessage> _customMessageManager;
|
||||
|
||||
public Client(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, ICustomMessageManager<ICustomRootMessage> customMessageManager, string name, int gameVersion, Language language, QuickChatModes chatMode, IHazelConnection connection)
|
||||
: base(name, gameVersion, language, chatMode, connection)
|
||||
public Client(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, ICustomMessageManager<ICustomRootMessage> customMessageManager, string name, int gameVersion, Language language, QuickChatModes chatMode, PlatformSpecificData platformSpecificData, IHazelConnection connection)
|
||||
: base(name, gameVersion, language, chatMode, platformSpecificData, connection)
|
||||
{
|
||||
_logger = logger;
|
||||
_antiCheatConfig = antiCheatOptions.Value;
|
||||
@@ -64,7 +65,7 @@ namespace Impostor.Server.Net
|
||||
case MessageFlags.HostGame:
|
||||
{
|
||||
// Read game settings.
|
||||
var gameInfo = Message00HostGameC2S.Deserialize(reader, out _);
|
||||
var gameInfo = Message00HostGameC2S.Deserialize(reader);
|
||||
|
||||
// Create game.
|
||||
var game = await _gameManager.CreateAsync(this, gameInfo);
|
||||
@@ -120,6 +121,12 @@ namespace Impostor.Server.Net
|
||||
case GameJoinError.GameDestroyed:
|
||||
await DisconnectAsync(DisconnectReason.Custom, DisconnectMessages.Destroyed);
|
||||
break;
|
||||
case GameJoinError.ClientOutdated:
|
||||
await DisconnectAsync(DisconnectReason.Custom, DisconnectMessages.ClientOutdated);
|
||||
break;
|
||||
case GameJoinError.ClientTooNew:
|
||||
await DisconnectAsync(DisconnectReason.Custom, DisconnectMessages.ClientTooNew);
|
||||
break;
|
||||
case GameJoinError.Custom:
|
||||
await DisconnectAsync(DisconnectReason.Custom, result.Message);
|
||||
break;
|
||||
@@ -257,6 +264,19 @@ namespace Impostor.Server.Net
|
||||
break;
|
||||
}
|
||||
|
||||
case MessageFlags.SetActivePodType:
|
||||
{
|
||||
Message21SetActivePodType.Deserialize(reader, out _);
|
||||
break;
|
||||
}
|
||||
|
||||
case MessageFlags.QueryPlatformIds:
|
||||
{
|
||||
Message22QueryPlatformIdsC2S.Deserialize(reader, out var gameCode);
|
||||
await OnQueryPlatformIds(gameCode);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (_customMessageManager.TryGet(flag, out var customRootMessage))
|
||||
{
|
||||
@@ -342,11 +362,28 @@ namespace Impostor.Server.Net
|
||||
{
|
||||
using var message = MessageWriter.Get(MessageType.Reliable);
|
||||
|
||||
var games = _gameManager.FindListings((MapFlags)options.Map, options.NumImpostors, options.Keywords);
|
||||
var games = _gameManager.FindListings((MapFlags)options.Map, options.NumImpostors, options.Keywords, this.GameVersion);
|
||||
|
||||
Message16GetGameListS2C.Serialize(message, games);
|
||||
|
||||
return Connection.SendAsync(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the connected client requests the PlatformSpecificData.
|
||||
/// </summary>
|
||||
/// <param name="code">
|
||||
/// The GameCode of the game whose platform id's are checked.
|
||||
/// </param>
|
||||
private ValueTask OnQueryPlatformIds(GameCode code)
|
||||
{
|
||||
using var message = MessageWriter.Get(MessageType.Reliable);
|
||||
|
||||
var playerSpecificData = _gameManager.Find(code)?.Players.Select(p => p.Client.PlatformSpecificData) ?? Enumerable.Empty<PlatformSpecificData>();
|
||||
|
||||
Message22QueryPlatformIdsS2C.Serialize(message, code, playerSpecificData);
|
||||
|
||||
return Connection.SendAsync(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,19 @@ using Impostor.Api;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.S2C;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Server.Net.State;
|
||||
|
||||
namespace Impostor.Server.Net
|
||||
{
|
||||
internal abstract class ClientBase : IClient
|
||||
{
|
||||
protected ClientBase(string name, int gameVersion, Language language, QuickChatModes chatMode, IHazelConnection connection)
|
||||
protected ClientBase(string name, int gameVersion, Language language, QuickChatModes chatMode, PlatformSpecificData platformSpecificData, IHazelConnection connection)
|
||||
{
|
||||
Name = name;
|
||||
GameVersion = gameVersion;
|
||||
Language = language;
|
||||
ChatMode = chatMode;
|
||||
PlatformSpecificData = platformSpecificData;
|
||||
Connection = connection;
|
||||
Items = new ConcurrentDictionary<object, object>();
|
||||
}
|
||||
@@ -31,6 +30,8 @@ namespace Impostor.Server.Net
|
||||
|
||||
public QuickChatModes ChatMode { get; }
|
||||
|
||||
public PlatformSpecificData PlatformSpecificData { get; }
|
||||
|
||||
public int GameVersion { get; }
|
||||
|
||||
public IHazelConnection Connection { get; }
|
||||
@@ -52,15 +53,7 @@ namespace Impostor.Server.Net
|
||||
|
||||
public async ValueTask DisconnectAsync(DisconnectReason reason, string? message = null)
|
||||
{
|
||||
if (!Connection.IsConnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var writer = MessageWriter.Get();
|
||||
MessageDisconnect.Serialize(writer, true, reason, message);
|
||||
|
||||
await Connection.DisconnectAsync(message ?? reason.ToString(), writer);
|
||||
await Connection.CustomDisconnectAsync(reason, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@ namespace Impostor.Server.Net.Factories
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public ClientBase Create(IHazelConnection connection, string name, int clientVersion, Language language, QuickChatModes chatMode)
|
||||
public ClientBase Create(IHazelConnection connection, string name, int clientVersion, Language language, QuickChatModes chatMode, PlatformSpecificData platformSpecificData)
|
||||
{
|
||||
var client = ActivatorUtilities.CreateInstance<TClient>(_serviceProvider, name, clientVersion, language, chatMode, connection);
|
||||
var client = ActivatorUtilities.CreateInstance<TClient>(_serviceProvider, name, clientVersion, language, chatMode, platformSpecificData, connection);
|
||||
connection.Client = client;
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ namespace Impostor.Server.Net.Factories
|
||||
{
|
||||
internal interface IClientFactory
|
||||
{
|
||||
ClientBase Create(IHazelConnection connection, string name, int clientVersion, Language language, QuickChatModes chatMode);
|
||||
ClientBase Create(IHazelConnection connection, string name, int clientVersion, Language language, QuickChatModes chatMode, PlatformSpecificData platformSpecificData);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Server.Net.Inner.Objects;
|
||||
|
||||
@@ -85,6 +86,32 @@ namespace Impostor.Server.Net.Inner
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateCanVent(CheatContext context, IClientPlayer sender, InnerPlayerInfo playerInfo, bool value = true)
|
||||
{
|
||||
if (playerInfo.CanVent != value)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Failed can vent check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateRole(CheatContext context, IClientPlayer sender, InnerPlayerInfo playerInfo, RoleTypes role)
|
||||
{
|
||||
if (playerInfo.RoleType != role)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, $"Failed role = {role} check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> UnregisteredCall(CheatContext context, IClientPlayer sender)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Client sent unregistered call"))
|
||||
|
||||
@@ -120,25 +120,36 @@ namespace Impostor.Server.Net.Inner.Objects.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (!await ValidateImpostor(call, sender, _playerControl.PlayerInfo))
|
||||
if (!await ValidateCanVent(call, sender, _playerControl.PlayerInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var vents = Game.GameNet.ShipStatus!.Data.Vents.Values;
|
||||
|
||||
var vent = vents.SingleOrDefault(x => Approximately(x.Position, position + ColliderOffset));
|
||||
|
||||
if (vent == null)
|
||||
if (Game.GameNet.ShipStatus == null)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(call, "Failed vent position check"))
|
||||
// Cannot perform vent position check on unknown ship statuses
|
||||
if (await sender.Client.ReportCheatAsync(call, "Failed vent position check on unknown map"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await _eventManager.CallAsync(new PlayerVentEvent(Game, sender, _playerControl, vent));
|
||||
var vents = Game.GameNet.ShipStatus!.Data.Vents.Values;
|
||||
|
||||
var vent = vents.SingleOrDefault(x => Approximately(x.Position, position + ColliderOffset));
|
||||
|
||||
if (vent == null)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(call, "Failed vent position check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await _eventManager.CallAsync(new PlayerVentEvent(Game, sender, _playerControl, vent));
|
||||
}
|
||||
}
|
||||
|
||||
await SnapToAsync(sender, position, minSid);
|
||||
|
||||
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user