mirror of
https://github.com/Impostor/Impostor.git
synced 2026-10-20 11:39:41 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b341bea14 | ||
|
|
af371c92ef | ||
|
|
ff49e895ec | ||
|
|
0e9fb4b41c | ||
|
|
4f00bf1ee7 | ||
|
|
a519c0daed | ||
|
|
1f98102e5a | ||
|
|
93fdc83ce7 | ||
|
|
e29552ca28 | ||
|
|
8eee7f888f | ||
|
|
a77e4e17c2 | ||
|
|
9ebf5cd8e9 | ||
|
|
4ffca69714 | ||
|
|
dede1c5b09 | ||
|
|
b31e3bf1e3 | ||
|
|
c9bb8323f4 | ||
|
|
1521410e79 | ||
|
|
be8e4a49f0 | ||
|
|
631e994759 | ||
|
|
c06916084e | ||
|
|
c9c044365a | ||
|
|
5ab4bf70da | ||
|
|
58c8bdec26 | ||
|
|
5e080b290b | ||
|
|
97390a0882 | ||
|
|
23499929fb | ||
|
|
579f618ac6 | ||
|
|
6962d01dbd | ||
|
|
0fb6556365 | ||
|
|
9cd5de6a36 | ||
|
|
94015d475d | ||
|
|
11bb2dec47 | ||
|
|
e7d745608e | ||
|
|
a1120f8468 | ||
|
|
1fa684d843 | ||
|
|
fac4103d70 | ||
|
|
3b5b538b39 | ||
|
|
62f8a7099d | ||
|
|
f8b3bf7295 | ||
|
|
4e5edcee49 | ||
|
|
5a8927e4c9 | ||
|
|
752b155152 | ||
|
|
5a1f1c9d86 | ||
|
|
adb74f628c | ||
|
|
c106695707 | ||
|
|
a7fb2b8b19 | ||
|
|
d4ac24ae17 | ||
|
|
e0b85c959b | ||
|
|
980d172d4f | ||
|
|
8dfa38b4b5 | ||
|
|
d1ac9301be | ||
|
|
d667f99c9f | ||
|
|
679bfecb42 | ||
|
|
519bae28b5 | ||
|
|
e5db56317a | ||
|
|
ed89e00f3a | ||
|
|
d5165a79f1 | ||
|
|
7bb7d2178b | ||
|
|
39b7d626dc | ||
|
|
116bb3cda4 | ||
|
|
8fe5c2205e | ||
|
|
a418e1f15a | ||
|
|
a7cff4aef1 | ||
|
|
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 | ||
|
|
d86efc1345 | ||
|
|
301a851ec3 | ||
|
|
86c27402e2 | ||
|
|
c63eb3b2d1 | ||
|
|
a1dac9f8b7 | ||
|
|
3065e8df48 | ||
|
|
dc52e478dc | ||
|
|
eb86c3c683 | ||
|
|
e7c83769ef | ||
|
|
c6b8066794 | ||
|
|
1ec5a050ad | ||
|
|
1e7d132f31 | ||
|
|
9543134ef3 | ||
|
|
389c72caa6 | ||
|
|
66b4d860a9 | ||
|
|
dca26cff59 | ||
|
|
3437c86bff | ||
|
|
66fb8426a6 | ||
|
|
4c839e2dd8 | ||
|
|
c6aa596e3b | ||
|
|
d8843db3eb | ||
|
|
b918f25443 | ||
|
|
824359f93b | ||
|
|
046d09b5fa | ||
|
|
5410c71280 | ||
|
|
241e867343 | ||
|
|
11f2ffd24d | ||
|
|
9df01d2cf7 | ||
|
|
d2720442e9 | ||
|
|
ddedffd121 | ||
|
|
2f04f6ea98 | ||
|
|
5f4c40bf36 | ||
|
|
ef4cc5646b | ||
|
|
d894e9adc3 | ||
|
|
c086cf80b1 | ||
|
|
1118a59167 | ||
|
|
5154dd9aa5 | ||
|
|
a621225fcd | ||
|
|
73a5463848 | ||
|
|
02d25a290f | ||
|
|
ced530b83a | ||
|
|
8f1cba8429 | ||
|
|
9009bac883 | ||
|
|
f3460f05bc | ||
|
|
a13fee108f | ||
|
|
adc0e6fe9b | ||
|
|
ce62815dc5 | ||
|
|
b1a0adaa28 | ||
|
|
fe697b1b63 | ||
|
|
55e6d38f9f | ||
|
|
b73a46ff56 | ||
|
|
901deeff59 | ||
|
|
f2126fd4c6 | ||
|
|
9aa6109b3a | ||
|
|
e1a6fdda98 | ||
|
|
283f59b51f | ||
|
|
d47343df08 | ||
|
|
0bb5442a3a | ||
|
|
7ac6c32b5d | ||
|
|
fbd9f12f9e | ||
|
|
f43577b745 | ||
|
|
a56eed2680 | ||
|
|
f0434f071c | ||
|
|
8d27016cb7 | ||
|
|
e941796a4c | ||
|
|
1d66f07906 | ||
|
|
7764987f91 | ||
|
|
bfba4385fd | ||
|
|
f03e72206e | ||
|
|
304b4bb7bf | ||
|
|
970f826dc8 | ||
|
|
0a30fe5a3e | ||
|
|
4866a350f8 | ||
|
|
13bddeb7bd | ||
|
|
225b56e71f | ||
|
|
60bf6b5f58 | ||
|
|
b5cee48242 | ||
|
|
c750c65481 | ||
|
|
d801a36af8 | ||
|
|
441d9c300c | ||
|
|
7fd68e31e6 | ||
|
|
47aebe7b7b | ||
|
|
66c2434320 | ||
|
|
c01062ed65 | ||
|
|
d5ae007d1c | ||
|
|
16a2b0aac6 | ||
|
|
4c1bd4a578 | ||
|
|
d311150967 | ||
|
|
92e3506f51 | ||
|
|
a63fc40099 | ||
|
|
4f53d3f4e6 | ||
|
|
a39fae3325 | ||
|
|
7c34836d50 | ||
|
|
989b06d04c | ||
|
|
11e87e51db | ||
|
|
b90e5b2c88 | ||
|
|
a0627bbc87 | ||
|
|
40a41f3573 | ||
|
|
8621f09761 | ||
|
|
3321e3049f | ||
|
|
a90bbebab9 | ||
|
|
f4dc0cd403 | ||
|
|
fbed06bf81 | ||
|
|
ef5320c820 | ||
|
|
bc85ef6810 | ||
|
|
e90ba734ab | ||
|
|
0f6bfb3597 | ||
|
|
dc759b1d57 | ||
|
|
be332e21d1 | ||
|
|
fe7a641bad | ||
|
|
e0041e89d8 | ||
|
|
f04bacf0de | ||
|
|
7e16b5595a | ||
|
|
a1c59363a1 | ||
|
|
ea1085406a | ||
|
|
e359f0a15d | ||
|
|
72f1e81c5f | ||
|
|
443168ef71 | ||
|
|
20d5284a7a | ||
|
|
9915f8b0cf | ||
|
|
0901be56f5 | ||
|
|
3090cea768 | ||
|
|
1059a4da16 | ||
|
|
acd2a56898 | ||
|
|
575ad25fb6 | ||
|
|
781ba34e1b | ||
|
|
9bd43b4629 | ||
|
|
e769b874c8 | ||
|
|
be19b1524b | ||
|
|
020a1b6447 | ||
|
|
bbbf368a6f | ||
|
|
d4bffd20ad | ||
|
|
87a062c1b3 | ||
|
|
f2d6531063 |
No files matched your search
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"cake.tool": {
|
||||
"version": "0.38.5",
|
||||
"version": "2.2.0",
|
||||
"commands": [
|
||||
"dotnet-cake"
|
||||
]
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
@@ -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: 7.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 }}
|
||||
@@ -2,7 +2,7 @@ name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: dev
|
||||
branches: master
|
||||
paths:
|
||||
- 'src/Impostor.Server/**'
|
||||
- 'src/Impostor.Shared/**'
|
||||
@@ -33,15 +33,16 @@ jobs:
|
||||
run: |
|
||||
DOCKER_IMAGE=aeonlucid/impostor
|
||||
VERSION=noop
|
||||
VERSIONSUFFIX=docker
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
VERSION=${GITHUB_REF#refs/tags/}
|
||||
VERSIONSUFFIX=none
|
||||
elif [[ $GITHUB_REF == refs/heads/* ]]; then
|
||||
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g')
|
||||
if [ "${{ github.event.repository.default_branch }}" = "dev" ]; then
|
||||
VERSION=nightly
|
||||
fi
|
||||
VERSION=nightly
|
||||
VERSIONSUFFIX=docker.${{ github.run_number }}
|
||||
elif [[ $GITHUB_REF == refs/pull/* ]]; then
|
||||
VERSION=pr-${{ github.event.number }}
|
||||
VERSIONSUFFIX=pr.${{ github.event.number }}
|
||||
fi
|
||||
TAGS="${DOCKER_IMAGE}:${VERSION}"
|
||||
if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
@@ -49,6 +50,7 @@ jobs:
|
||||
fi
|
||||
echo ::set-output name=version::${VERSION}
|
||||
echo ::set-output name=tags::${TAGS}
|
||||
echo ::set-output name=versionsuffix::${VERSIONSUFFIX}
|
||||
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
@@ -68,3 +70,5 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.prep.outputs.tags }}
|
||||
build-args: |
|
||||
VERSIONSUFFIX=${{ steps.prep.outputs.versionsuffix }}
|
||||
Whitespace-only changes.
+3
-3
@@ -9,14 +9,14 @@ We are always looking for people to help improve Impostor.
|
||||
- Don't commit unnecessary changes to the codebase or debugging code.
|
||||
- Write meaningful commits or squash them.
|
||||
- Please try to follow the code style of the rest of the codebase. An `.editorconfig` file has been provided to keep consistency.
|
||||
- Stylecop is also enabled: please make sure your PR compiles without warnings.
|
||||
|
||||
## Pull requests
|
||||
|
||||
- Only make pull requests to the `dev` branch.
|
||||
- Only implement one feature per pull request to keep it easy to understand.
|
||||
- Expect comments or questions on your pull request from the project maintainers. We try to keep the code as consistent and maintainable as possible.
|
||||
- Each pull request should come from a new branch in your fork, it should have a meaningful name.
|
||||
- Each pull request should come from a new branch in your fork, it should have a meaningful name.
|
||||
- We try to respond to pull requests as fast as possible. If you think we might have missed it, let us know on [Discord](https://discord.gg/Mk3w6Tb).
|
||||
|
||||
|
||||
If you have any questions, let us know.
|
||||
If you have any questions, let us know.
|
||||
+20
-8
@@ -1,15 +1,17 @@
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:5.0 AS build
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||
|
||||
# See for all possible platforms
|
||||
# https://github.com/containerd/containerd/blob/master/platforms/platforms.go#L17
|
||||
ARG TARGETARCH
|
||||
|
||||
ARG VERSIONSUFFIX="docker"
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
# Copy csproj and restore.
|
||||
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/Impostor.Hazel.csproj ./src/Impostor.Hazel/Impostor.Hazel.csproj
|
||||
COPY src/Directory.Build.props ./src/Directory.Build.props
|
||||
|
||||
RUN case "$TARGETARCH" in \
|
||||
amd64) NETCORE_PLATFORM='linux-x64';; \
|
||||
@@ -18,8 +20,7 @@ RUN case "$TARGETARCH" in \
|
||||
*) echo "unsupported architecture"; exit 1 ;; \
|
||||
esac && \
|
||||
dotnet restore -r "$NETCORE_PLATFORM" ./src/Impostor.Server/Impostor.Server.csproj && \
|
||||
dotnet restore -r "$NETCORE_PLATFORM" ./src/Impostor.Api/Impostor.Api.csproj && \
|
||||
dotnet restore -r "$NETCORE_PLATFORM" ./src/Impostor.Hazel/Impostor.Hazel.csproj
|
||||
dotnet restore -r "$NETCORE_PLATFORM" ./src/Impostor.Api/Impostor.Api.csproj
|
||||
|
||||
# Copy everything else.
|
||||
COPY src/. ./src/
|
||||
@@ -29,11 +30,22 @@ RUN case "$TARGETARCH" in \
|
||||
arm) NETCORE_PLATFORM='linux-arm';; \
|
||||
*) echo "unsupported architecture"; exit 1 ;; \
|
||||
esac && \
|
||||
dotnet publish -c release -o /app -r "$NETCORE_PLATFORM" --no-restore ./src/Impostor.Server/Impostor.Server.csproj
|
||||
[ $VERSIONSUFFIX = "none" ] && VERSIONSUFFIX=; \
|
||||
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/aspnet:7.0
|
||||
WORKDIR /app
|
||||
COPY --from=build /app ./
|
||||
EXPOSE 22023/udp
|
||||
ENTRYPOINT ["./Impostor.Server"]
|
||||
|
||||
# Add Impostor.Http as a default built-in plugin
|
||||
ADD https://github.com/Impostor/Impostor.Http/releases/download/v0.5.0/Impostor.Http.dll /app/builtin-plugins/
|
||||
# Make it listen to 0.0.0.0 to expose it to the outside world.
|
||||
ENV IMPOSTOR_HTTP_HttpServer__ListenIp=0.0.0.0
|
||||
# Override ASPNETCORE_URLS to stop warning.
|
||||
ENV ASPNETCORE_URLS=
|
||||
# Enable the built-in plugin folder. Use a high number to prevent conflicts with existing configurations
|
||||
ENV IMPOSTOR_PluginLoader__Paths__76=/app/builtin-plugins
|
||||
|
||||
EXPOSE 22023/tcp 22023/udp
|
||||
ENTRYPOINT ["./Impostor.Server"]
|
||||
@@ -1,16 +1,13 @@
|
||||
# Impostor
|
||||
|
||||
[](https://discord.gg/Mk3w6Tb)
|
||||
[](https://ci.appveyor.com/project/Impostor/Impostor/branch/dev)
|
||||
[](https://github.com/Impostor/Impostor/actions)
|
||||
|
||||
Impostor is one of the first **Among Us** private servers, written in C#.
|
||||
Impostor is the first working **Among Us** private server, written in C#.
|
||||
|
||||
We support Steam, Itch, Android and iOS. The latest version supported is `2020.9.22`, the `dev` build currently supports `2020.11.17`.
|
||||
As Among Us is actively updated, you may want to use the latest build from the master branch if you want to play on the latest version of Among Us that supported by Impostor.
|
||||
|
||||
| Impostor version | Among Us version | Experimental | Download |
|
||||
|-|-|-|-|
|
||||
| 1.1.0 | 2020.09.07 - 2020.09.22 | No | [](https://github.com/Impostor/Impostor/releases/tag/v1.1.0) |
|
||||
| 1.2.2 | 2020.09.22 - 2020.11.17 | Yes | [](https://ci.appveyor.com/project/Impostor/Impostor/branch/dev/artifacts) |
|
||||
If you want to play on an older version of Among Us, you can download old releases from [here](https://github.com/Impostor/Impostor/releases/), however these versions are less supported.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -22,34 +19,7 @@ We support Steam, Itch, Android and iOS. The latest version supported is `2020.9
|
||||
|
||||
### Client
|
||||
|
||||
If you just want to play on a server hosted by someone else, you need to follow these instructions.
|
||||
|
||||
#### Windows
|
||||
|
||||
1. Find the [latest release](https://github.com/AeonLucid/Impostor/releases/latest).
|
||||
2. Download `Impostor-Client-win-x64.zip`.
|
||||
3. Extract the zip.
|
||||
4. Run `Impostor.Client.exe`.
|
||||
5. Follow the instructions inside the application.
|
||||
|
||||

|
||||
|
||||
If you do not wish to execute any programs. Follow the instructions in [this website](https://impostor.github.io/Impostor)
|
||||
|
||||
#### Android
|
||||
|
||||
##### Android 10 and below.
|
||||
1. Go to [this website](https://impostor.github.io/Impostor) **(ON YOUR MOBILE DEVICE)**
|
||||
2. Follow the instructions listed there.
|
||||
|
||||
##### Android 11.
|
||||
1. Connect your phone to a computer. Go to [this website](https://impostor.github.io/Impostor) on the computer and follow the steps 1 and 2 to generate a `regionInfo.dat` file.
|
||||
2. Instead of following the next steps, open the phone's internal storage on your computer and navigate to `/sdcard/Android/data/com.innersloth.spacemafia/files`.
|
||||
3. Copy the generated `regionInfo.dat` file into the `files` folder you just navigated to.
|
||||
|
||||
#### iOS
|
||||
|
||||
iOS devices need to be jailbroken in order to connect to Impostor servers.
|
||||
If you just want to play on a server hosted by someone else, you need to configure your client to connect to an Impostor server. Please go to [this website](https://impostor.github.io/Impostor) to set up your client by following the instructions for your OS there.
|
||||
|
||||
### Server
|
||||
|
||||
@@ -57,7 +27,7 @@ See the [docs](docs/Running-the-server.md) for instructions on how to set it up.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [TROUBLESHOOTING](docs/TROUBLESHOOTING.md) to solve issues the Impostor client or the server.
|
||||
See [TROUBLESHOOTING](docs/TROUBLESHOOTING.md) to solve issues with the Impostor client or the server.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
environment:
|
||||
IMPOSTOR_VERSION: '1.2.2'
|
||||
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: Visual Studio 2019 Preview
|
||||
|
||||
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
|
||||
+59
-72
@@ -1,20 +1,33 @@
|
||||
#addin "nuget:?package=SharpZipLib&Version=1.3.0"
|
||||
#addin "nuget:?package=Cake.Compression&Version=0.2.4"
|
||||
#addin "nuget:?package=Cake.FileHelpers&Version=3.3.0"
|
||||
#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("APPVEYOR_BUILD_VERSION") ?? "0";
|
||||
var buildVersion = EnvironmentVariable("IMPOSTOR_VERSION") ?? "1.0.0";
|
||||
var buildBranch = EnvironmentVariable("APPVEYOR_REPO_BRANCH") ?? "dev";
|
||||
var buildVersion = FindRegexMatchGroupInFile("./src/Directory.Build.props", @"\<VersionPrefix\>(.*?)\<\/VersionPrefix\>", 1, System.Text.RegularExpressions.RegexOptions.None).Value;
|
||||
var buildDir = MakeAbsolute(Directory("./build"));
|
||||
|
||||
var prNumber = EnvironmentVariable("APPVEYOR_PULL_REQUEST_NUMBER");
|
||||
var target = Argument("target", "Deploy");
|
||||
var target = Argument("target", "Test");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
|
||||
// On any branch that is not master, we need to tag the version as prerelease.
|
||||
if (buildBranch != "master") {
|
||||
buildVersion = buildVersion + "-ci." + buildId;
|
||||
var msbuildSettings = new DotNetMSBuildSettings();
|
||||
|
||||
if (tag != null)
|
||||
{
|
||||
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 != 0)
|
||||
{
|
||||
buildId += 500;
|
||||
msbuildSettings.VersionSuffix = "ci." + buildId;
|
||||
buildVersion += "-ci." + buildId;
|
||||
}
|
||||
else
|
||||
{
|
||||
buildVersion += "-dev";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -26,15 +39,15 @@ 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,
|
||||
PublishTrimmed = false,
|
||||
OutputDirectory = projBuildDir
|
||||
OutputDirectory = projBuildDir,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
|
||||
if (isServer) {
|
||||
@@ -51,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) {
|
||||
@@ -58,11 +75,12 @@ 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",
|
||||
OutputDirectory = projBuildDir
|
||||
OutputDirectory = projBuildDir,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
|
||||
Zip(projBuildDir, projBuildZip);
|
||||
@@ -83,96 +101,65 @@ Task("Clean")
|
||||
|
||||
Task("Restore")
|
||||
.Does(() => {
|
||||
DotNetCoreRestore("./src/Impostor.sln");
|
||||
});
|
||||
|
||||
Task("Patch")
|
||||
.WithCriteria(BuildSystem.AppVeyor.IsRunningOnAppVeyor)
|
||||
.Does(() => {
|
||||
ReplaceRegexInFiles("./src/**/*.csproj", @"<Version>.*?<\/Version>", "<Version>" + buildVersion + "</Version>");
|
||||
ReplaceRegexInFiles("./src/**/*.props", @"<Version>.*?<\/Version>", "<Version>" + buildVersion + "</Version>");
|
||||
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"
|
||||
});
|
||||
});
|
||||
|
||||
Task("Build")
|
||||
.IsDependentOn("Clean")
|
||||
.IsDependentOn("Patch")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("Replay")
|
||||
.Does(() => {
|
||||
// Tests.
|
||||
DotNetCoreBuild("./src/Impostor.Tests/Impostor.Tests.csproj", new DotNetCoreBuildSettings {
|
||||
DotNetBuild("./src/Impostor.Tests/Impostor.Tests.csproj", new DotNetBuildSettings {
|
||||
Configuration = configuration,
|
||||
});
|
||||
|
||||
// Only build artifacts if;
|
||||
// - buildBranch is master/dev
|
||||
// - it is not a pull request
|
||||
if ((buildBranch == "master" || buildBranch == "dev") && string.IsNullOrEmpty(prNumber)) {
|
||||
// Client.
|
||||
ImpostorPublishNF("Impostor-Patcher", "./src/Impostor.Patcher/Impostor.Patcher.WinForms/Impostor.Patcher.WinForms.csproj");
|
||||
|
||||
ImpostorPublish("Impostor-Patcher-Cli", "./src/Impostor.Patcher/Impostor.Patcher.Cli/Impostor.Patcher.Cli.csproj", "win-x64");
|
||||
ImpostorPublish("Impostor-Patcher-Cli", "./src/Impostor.Patcher/Impostor.Patcher.Cli/Impostor.Patcher.Cli.csproj", "osx-x64");
|
||||
ImpostorPublish("Impostor-Patcher-Cli", "./src/Impostor.Patcher/Impostor.Patcher.Cli/Impostor.Patcher.Cli.csproj", "linux-x64");
|
||||
|
||||
// Server.
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "win-x64", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "osx-x64", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-x64", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-arm", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-arm64", true);
|
||||
// Server.
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "win-x64", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "osx-x64", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-x64", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-arm", true);
|
||||
ImpostorPublish("Impostor-Server", "./src/Impostor.Server/Impostor.Server.csproj", "linux-arm64", true);
|
||||
|
||||
// API.
|
||||
DotNetCorePack("./src/Impostor.Api/Impostor.Api.csproj", new DotNetCorePackSettings {
|
||||
Configuration = configuration,
|
||||
OutputDirectory = buildDir,
|
||||
IncludeSource = true,
|
||||
IncludeSymbols = true
|
||||
});
|
||||
} else {
|
||||
DotNetCoreBuild("./src/Impostor.Patcher/Impostor.Patcher.WinForms/Impostor.Patcher.WinForms.csproj", new DotNetCoreBuildSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net472"
|
||||
});
|
||||
// API.
|
||||
DotNetPack("./src/Impostor.Api/Impostor.Api.csproj", new DotNetPackSettings {
|
||||
Configuration = configuration,
|
||||
OutputDirectory = buildDir,
|
||||
IncludeSource = true,
|
||||
IncludeSymbols = true,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
|
||||
DotNetCoreBuild("./src/Impostor.Server/Impostor.Server.csproj", new DotNetCoreBuildSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net5.0"
|
||||
});
|
||||
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,45 +1,29 @@
|
||||
# Building from source
|
||||
|
||||
The solution contains two main projects, the Impostor client and server. The client is built using [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472) and the server with [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0).
|
||||
|
||||
Currently .NET 5 is not yet officially released, so in order to build using Visual Studio, you should have Visual Studio 2019 **Preview** installed.
|
||||
This documentation will go over building both the [Server](#building-the-server) and the [Client](#building-the-client) and their requirements.
|
||||
The solution contains the Impostor server and its dependencies, like Hazel and the plugin API. The server is built using [.NET 7](https://dotnet.microsoft.com/download/dotnet/7.0).
|
||||
|
||||
## Cloning Impostor
|
||||
|
||||
You need to clone Impostor with all submodules.
|
||||
You need to clone Impostor using git:
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/AeonLucid/Impostor.git
|
||||
```
|
||||
|
||||
If you already have cloned Impostor but have errors related to Hazel, run the following.
|
||||
|
||||
```bash
|
||||
git submodule update --init
|
||||
git clone https://github.com/Impostor/Impostor.git
|
||||
```
|
||||
|
||||
## Building the server
|
||||
|
||||
### Dependencies
|
||||
- [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0)
|
||||
- [Visual Studio Preview](https://visualstudio.microsoft.com/vs/preview/) (Optional, only if you want the full IDE experience)
|
||||
|
||||
- [.NET 7 SDK](https://dotnet.microsoft.com/download/dotnet/7.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
|
||||
|
||||
```bash
|
||||
cd src/Impostor.Server/
|
||||
dotnet build
|
||||
# Or if you want a single file, ready for production: (change linux-x64 to win-x64 if you use Windows)
|
||||
dotnet publish -c Release -r linux-x64 -p:PublishSingleFile=true
|
||||
```
|
||||
|
||||
To setup the server, please look at [Running the server](Running-the-server.md).
|
||||
|
||||
## Building the client
|
||||
|
||||
### Dependencies
|
||||
* [.NET Framework 4.7.2 Developer Pack](https://dotnet.microsoft.com/download/dotnet-framework/thank-you/net472-developer-pack-offline-installer)
|
||||
|
||||
### Build using the CLI
|
||||
```bash
|
||||
cd src/Impostor.Client/Impostor.Client.WinForms
|
||||
dotnet build
|
||||
```
|
||||
+7
-3
@@ -1,11 +1,15 @@
|
||||
# Frequently Answered Questions
|
||||
|
||||
## What is this?
|
||||
The Impostor project is a reverse engineered and open sourced server for the game Among Us. The game itself is developed by [InnerSloth](http://www.innersloth.com/) while this project is maintained by the community. This project was built out of frustration for the lack of server availability in certain regions and the inability for the core developer, [AeonLucid](https://github.com/AeonLucid), to join a public game. As of this time, it has not been officially endorsed by the studio.
|
||||
|
||||
The Impostor project is a reverse engineered and open source server for the game Among Us. The game itself is developed by [Innersloth](http://www.innersloth.com/) while this project is maintained by the community. This project was built out of frustration for the lack of server availability in certain regions and the inability for the core developer, [AeonLucid](https://github.com/AeonLucid), to join a public game. As of this time, it has not been officially endorsed by the studio.
|
||||
|
||||
## Can this be used with the mobile version of the game?
|
||||
Yes, Impostor can be used with both the Android and iOS\* versions of the game.
|
||||
###### \* In order to play on an Impostor server with iOS, you _must_ have a jailbroken device.
|
||||
|
||||
Yes, Impostor can be used with both the Android and iOS versions of the game. You can add a custom server via a link, you can do this using the [site](https://impostor.github.io/Impostor)
|
||||
|
||||
## How can I get started?
|
||||
|
||||
See [Setting up your Server](Running-the-server.md) for more information on running the server and [Client Setup](https://impostor.github.io/Impostor/) for helping your friends join in!
|
||||
|
||||
If you're having issues with the server software, check the [Troubleshooting page](TROUBLESHOOTING.md).
|
||||
+40
-77
@@ -1,30 +1,50 @@
|
||||
# Running the server
|
||||
|
||||
There are currently two modes to run the Impostor server in. The first way is the simplest one and is the one you should probably use. The other way will distribute players across other servers and is a more advanced configuration.
|
||||
There are currently two install methods for Impostor: You can install it normally or inside of a Docker container. If you do not have a particular preference, we recommend the normal installation over the Docker container method.
|
||||
|
||||
## Single server
|
||||
## General remarks for both install methods
|
||||
|
||||
### Without docker
|
||||
1. Install the **.NET 5.0 runtime**.
|
||||
- [Windows x64](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-5.0.0-windows-x64-installer)
|
||||
- [Linux x64](https://docs.microsoft.com/en-us/dotnet/core/install/linux)
|
||||
- [macOS x64](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-5.0.0-macos-x64-installer)
|
||||
2. Find the [latest dev release](https://ci.appveyor.com/project/Impostor/Impostor/branch/dev/artifacts).
|
||||
3. Download either the Windows or the Linux version.
|
||||
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)*
|
||||
6. Run `Impostor.Server.exe` (Windows) / `Impostor.Server` (Linux)
|
||||
This section applies to both the normal installation as well as the Docker (Compose) installation
|
||||
|
||||
### Using docker
|
||||
To connect to the server, you need to configure and install a region file on https://impostor.github.io/Impostor/
|
||||
|
||||
[](https://hub.docker.com/repository/docker/aeonlucid/impostor)
|
||||
[](https://hub.docker.com/repository/docker/aeonlucid/impostor)
|
||||
Among Us connects to the server using two network services: the (TCP) HTTP service points Among Us to the UDP service, then the UDP service hosts the actual game traffic. Because of this, Impostor uses port 22023 using **both** the TCP and UDP protocols.
|
||||
|
||||
As the phone version of Among Us requires this HTTP connection to be secure, we recommend using a HTTP reverse proxy to terminate SSL on the HTTP service. Setup instructions for this are in the [Impostor.Http readme](https://github.com/Impostor/Impostor.Http#readme).
|
||||
|
||||
Depending on your host you may also need to port forward Impostor to the internet or pass Impostor traffic by your firewall. Port 22023 UDP needs to be accessible for everyone that wants to play on the server, then you also need to portforward your HTTP reverse proxy or port 22023 TCP if you don't use a reverse proxy. As port forwarding changes per host or router configuration, port forwarding is not covered by this guide.
|
||||
|
||||
## Normal installation
|
||||
|
||||
1. Install [.NET 7.0](https://dotnet.microsoft.com/download/dotnet/7.0). We recommend either the ASP.NET Core Runtime or the SDK. The SDK is necessary in case you want to develop Impostor or Impostor plugins.
|
||||
2. Download the [latest release](https://github.com/Impostor/Impostor/releases) or the [latest CI build](https://nightly.link/Impostor/Impostor/workflows/ci/master). Note that Impostor is built for multiple CPU-architectures and operating systems, you most likely want the x64 version, unless you are running on a Raspberry Pi or another device with an Arm processor.
|
||||
3. Extract the zip.
|
||||
4. Download the [Impostor.Http](https://github.com/Impostor/Impostor.Http) plugin and put it in your `plugins` folder. Please note the Reverse Proxy configuration: you either need to configure a reverse proxy to terminate SSL or expose the service to the world by changing ListenIp.
|
||||
5. Modify `config.json` to your liking. Documentation can be found [here](Server-configuration.md). You need to at least change `PublicIp` to the address people will connect to your server to.
|
||||
6. Run `Impostor.Server` (Linux/macOS) or `Impostor.Server.exe` (Windows)
|
||||
7. (OPTIONAL - Linux) Configure a systemd definition file and enable the service to start on boot - [systemd configuration](Server-configuration.md#systemd)
|
||||
|
||||
## Using Docker
|
||||
|
||||
[](https://hub.docker.com/r/aeonlucid/impostor)
|
||||
[](https://hub.docker.com/r/aeonlucid/impostor)
|
||||
|
||||
Docker is a program that allows you to run programs like Impostor in a container.
|
||||
|
||||
After installing Docker, you can just start a Docker container with `docker run`:
|
||||
|
||||
```
|
||||
docker run -p 22023:22023/udp aeonlucid/impostor:nightly
|
||||
docker run -p 127.0.0.1:22023:22023/tcp -p 22023:22023/udp -e IMPOSTOR_Server__PublicIp=your.public.ip.here aeonlucid/impostor:nightly
|
||||
```
|
||||
|
||||
### Using docker-compose
|
||||
Please replace `your.public.ip.here` with the public IP address of your server. This is the address Among Us will try to reach your client at.
|
||||
|
||||
To configure the docker container, either use environment variables or mount config.json in your container.
|
||||
|
||||
## Using Docker Compose
|
||||
|
||||
Docker Compose allows you to start a Docker container using a prefined configuration. This is an example configuration you can continue on:
|
||||
|
||||
```
|
||||
version: '3.4'
|
||||
|
||||
@@ -33,69 +53,12 @@ services:
|
||||
image: aeonlucid/impostor:nightly
|
||||
container_name: impostor
|
||||
ports:
|
||||
- 127.0.0.1:22023:22023/tcp
|
||||
- 22023:22023/udp
|
||||
environment: # Either configure Impostor using environment variables or mount a copy of config.json
|
||||
- IMPOSTOR_Server__PublicIp=your.public.ip.here
|
||||
volumes:
|
||||
- /path/to/local/config.json:/app/config.json # For easy editing of the config
|
||||
- /path/to/local/plugins:/app/plugins # Only needed if using plugins
|
||||
- /path/to/local/libraries:/app/libraries # Only needed if using external libraries
|
||||
```
|
||||
|
||||
## Multiple servers
|
||||
|
||||
Follow the steps from the single server on two or more servers.
|
||||
|
||||
### Master server
|
||||
|
||||
The master server will accept client connections and redirect them to the other servers listed in the configuration. It will not host any games itself.
|
||||
|
||||
Example configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"Server": {
|
||||
"PublicIp": "127.0.0.1",
|
||||
"PublicPort": 22023,
|
||||
"ListenIp": "0.0.0.0",
|
||||
"ListenPort": 22023
|
||||
},
|
||||
"ServerRedirector": {
|
||||
"Enabled": true,
|
||||
"Master": true,
|
||||
"Locator": {
|
||||
"Redis": "",
|
||||
"UdpMasterEndpoint": "127.0.0.1:22024"
|
||||
},
|
||||
"Nodes": [
|
||||
{
|
||||
"Ip": "127.0.0.1",
|
||||
"Port": 22025
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Node servers
|
||||
|
||||
The node server should have `ServerRedirector` enabled too, but `Master` **must be disabled**. Nodes do not need to be aware of each other.
|
||||
|
||||
Example configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"Server": {
|
||||
"PublicIp": "127.0.0.1",
|
||||
"PublicPort": 22025,
|
||||
"ListenIp": "0.0.0.0",
|
||||
"ListenPort": 22025
|
||||
},
|
||||
"ServerRedirector": {
|
||||
"Enabled": true,
|
||||
"Master": false,
|
||||
"Locator": {
|
||||
"Redis": "",
|
||||
"UdpMasterEndpoint": "127.0.0.1:22024"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
+133
-49
@@ -1,34 +1,79 @@
|
||||
# Server configuration
|
||||
|
||||
Some information about all the possible configurations. Click [here](https://github.com/AeonLucid/Impostor/blob/master/src/Impostor.Server/config.full.json) to see all the possible config options.
|
||||
Some information about all the possible configurations. Click [here](https://github.com/Impostor/Impostor/blob/master/src/Impostor.Server/config-full.json) to see all the possible config options.
|
||||
|
||||
## Options
|
||||
|
||||
### Required Server Configuration
|
||||
|
||||
| Key | Default | Description |
|
||||
|-|-|-|
|
||||
| **PublicIp** | `127.0.0.1` | This needs to the public IPv4 address of the server which you give to others to connect. You can find your IPv4 address [on this website](http://whatismyip.host/). Unless you are only planning to use Impostor privately, on your local network, you should change this to your public ip. It is also possible to use hostnames instead of IPv4 addresses, which will be resolved to IPv4 addresses. |
|
||||
| **PublicPort** | `22023` | The public port of the server which you give to others to connect. (**This is the external port you configure on your router when port forwarding.**) Usually `22023`. |
|
||||
| **ListenIp** | `0.0.0.0` | The network interface to listen on. If you do not know what to put here, use `0.0.0.0`. Since 1.2.2 it is also possible to use hostnames instead of IPv4 addresses, these must resolve to a valid IPv4 address. |
|
||||
| **ListenPort** | `22023` | The listen port of the server, usually `22023`. |
|
||||
| Key | Default | Description |
|
||||
| -------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **PublicIp** | `127.0.0.1` | This needs to the public IPv4 address of the server which you give to others to connect. You can find your IPv4 address [on this website](http://whatismyip.host/). Unless you are only planning to use Impostor privately, on your local network, you should change this to your public ip. It is also possible to use hostnames instead of IPv4 addresses, which will be resolved to IPv4 addresses. |
|
||||
| **PublicPort** | `22023` | The public port of the server which you give to others to connect. (**This is the external port you configure on your router when port forwarding.**) Usually `22023`. |
|
||||
| **ListenIp** | `0.0.0.0` | The network interface to listen on. If you do not know what to put here, use `0.0.0.0`. Since 1.2.2 it is also possible to use hostnames instead of IPv4 addresses, these must resolve to a valid IPv4 address. |
|
||||
| **ListenPort** | `22023` | The listen port of the server, usually `22023`. |
|
||||
|
||||
### AntiCheat
|
||||
|
||||
| Key | Default | Value |
|
||||
|-|-|-|
|
||||
| **BanIpFromGame** | `true` | When 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. **(Setting this to false does not disable the anti-cheat!)** |
|
||||
Impostor has an Anticheat that makes it possible to kick cheaters from games automatically. Note that the anticheat is tuned on the vanilla version of the game, so client-side modifications could trigger the Anticheat if you're playing with them.
|
||||
|
||||
### ServerRedirector
|
||||
In a multi-node setup these need to be specified.
|
||||
| Key | Default | Value |
|
||||
|-|-|-|
|
||||
| **Enabled** | `false` | Whether the server runs in multi-node setup. If this is `false`, all other options in this section do not have any effect. |
|
||||
| **Master** | `false` | Whether the current server is a master. A master is responsible for redirecting clients to nodes |
|
||||
| **Locator** | | Fill in either `Redis` or `UdpMasterEndpoint` to choose which method to use for locating other nodes. This must be the same across all servers. |
|
||||
| **>Redis** | | Format `127.0.0.1.6379`, you can also use a password like so: `127.0.0.1.6379,password=value`. |
|
||||
| **>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. |
|
||||
| Key | Default | Value |
|
||||
| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Enabled** | `true` | Whether the anticheat should be enabled. |
|
||||
| **BanIpFromGame** | `true` | When anticheat is enabled and a player is caught hacking, they will be kicked from the server. If this value is set to `true`, the player will be banned instead and will not be able to rejoin that specific game. |
|
||||
|
||||
### Compatibility
|
||||
|
||||
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 |
|
||||
| ------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **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
|
||||
|
||||
The Debug configuration is used to enable the game recorder. This is mostly useful when developing Impostor.
|
||||
|
||||
| Key | Default | Value |
|
||||
| ----------------------- | ------- | -------------------------------------------- |
|
||||
| **GameRecorderEnabled** | `false` | Enables the Game Recorder. |
|
||||
| **GameRecorderPath** | _empty_ | Path where the recorded games will be saved. |
|
||||
|
||||
### 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
|
||||
|
||||
@@ -36,42 +81,81 @@ In a multi-node setup these need to be specified.
|
||||
|
||||
The simplest option to configure is by using the `config.json` file next to the server executable. For all possible options see the [config-full.json](https://github.com/Impostor/Impostor/blob/dev/src/Impostor.Server/config-full.json) file.
|
||||
|
||||
### Command line arguments
|
||||
|
||||
TODO
|
||||
|
||||
```
|
||||
Server:PublicIp=127.0.0.1
|
||||
Server:PublicPort=22023
|
||||
Server:ListenIp=0.0.0.0
|
||||
Server:ListenPort=22023
|
||||
AntiCheat:BanIpFromGame=true
|
||||
ServerRedirector:Enabled=false
|
||||
ServerRedirector:Master=true
|
||||
ServerRedirector:Locator:Redis=127.0.0.1.6379
|
||||
ServerRedirector:Locator:UdpMasterEndpoint=127.0.0.1:32320
|
||||
ServerRedirector:Nodes:0:Ip=127.0.0.1
|
||||
ServerRedirector:Nodes:0:Port=22024
|
||||
ServerRedirector:Nodes:1:Ip=127.0.0.1
|
||||
ServerRedirector:Nodes:1:Port=22025
|
||||
```
|
||||
|
||||
### Environment variables
|
||||
|
||||
TODO
|
||||
If you're unable to edit the config.json file, you can instead set Environment variables to configure Impostor. The general pattern for each variable is `IMPOSTOR_SectionName__VariableName`. For example, to disable the anticheat, you can set the environment variable `IMPOSTOR_AntiCheat__Enabled=false`. Here are some more examples:
|
||||
|
||||
```
|
||||
IMPOSTOR_Server__PublicIp=127.0.0.1
|
||||
IMPOSTOR_Server__PublicPort=22023
|
||||
IMPOSTOR_Server__ListenIp=0.0.0.0
|
||||
IMPOSTOR_Server__ListenPort=22023
|
||||
IMPOSTOR_AntiCheat__Enabled=true
|
||||
IMPOSTOR_AntiCheat__BanIpFromGame=true
|
||||
IMPOSTOR_ServerRedirector__Enabled=false
|
||||
IMPOSTOR_ServerRedirector__Master=true
|
||||
IMPOSTOR_ServerRedirector__Locator__Redis=127.0.0.1.6379
|
||||
IMPOSTOR_ServerRedirector__Locator__UdpMasterEndpoint=127.0.0.1:32320
|
||||
IMPOSTOR_ServerRedirector__Nodes__0__Ip=127.0.0.1
|
||||
IMPOSTOR_ServerRedirector__Nodes__0__Port=22024
|
||||
IMPOSTOR_ServerRedirector__Nodes__1__Ip=127.0.0.1
|
||||
IMPOSTOR_ServerRedirector__Nodes__1__Port=22025
|
||||
```
|
||||
|
||||
# systemd
|
||||
|
||||
Linux users will likely want to create a systemd service definition to manage running the Impostor application. Benefits to using a systemd service include the following:
|
||||
|
||||
- The server process can automatically restart if the process dies
|
||||
- Impostor can be set to start on boot (handy if you do system updates regularly)
|
||||
- You can use systemd targets to ensure the process doesn't start until the system dependencies are met
|
||||
|
||||
Using your favorite text editor, create the following service file:
|
||||
|
||||
```
|
||||
sudoedit /etc/systemd/system/impostor.service
|
||||
```
|
||||
|
||||
Modify the following template to your needs and populate the service file.
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Impostor private Among Us server - https://github.com/Impostor/Impostor
|
||||
|
||||
[Service]
|
||||
# Directory where Impostor is installed
|
||||
WorkingDirectory=/opt/impostor
|
||||
# Path to Impostor binary
|
||||
ExecStart=/opt/impostor/Impostor.Server
|
||||
Restart=always
|
||||
# Restart service after 10 seconds if the dotnet service crashes
|
||||
RestartSec=10
|
||||
KillSignal=SIGTERM
|
||||
SyslogIdentifier=impostor
|
||||
|
||||
# User and group that will run the Impostor server process -- ensure that user is allowed to execute the binary
|
||||
User=impostor
|
||||
Group=impostor
|
||||
TimeoutStopSec=10
|
||||
|
||||
[Install]
|
||||
# Wait until most system services have started before starting Impostor
|
||||
After=multi-user.target
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Reload all systemd unit files to source in the new file you've created.
|
||||
|
||||
```
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
|
||||
Start the service.
|
||||
|
||||
```
|
||||
sudo systemctl start impostor.service
|
||||
```
|
||||
|
||||
Check the log for the service and verify it has started correctly -- Hint: Use the Q key to quit out of journalctl.
|
||||
|
||||
```
|
||||
sudo journalctl -u impostor.service
|
||||
```
|
||||
|
||||
If everything has started correctly, ensure the service is set to start on boot.
|
||||
|
||||
```
|
||||
sudo systemctl enable impostor.service
|
||||
```
|
||||
+38
-9
@@ -1,28 +1,57 @@
|
||||
# Troubleshooting
|
||||
|
||||
If you're reading this, something went wrong.
|
||||
Don't worry though, as this is the most thorough guide to help you!
|
||||
|
||||
## `./Impostor.Server: line 1: ELF: not found` (plus other errors)
|
||||
|
||||
No idea where you got that system. But we clearly do **NOT** support it.
|
||||
|
||||
## `cannot execute binary file: Exec format error`
|
||||
Please check that you have downloaded the right version of Impostor, as we mantain two CPU architectures (x64 and ARM).
|
||||
Unless you are running Impostor on a SBC (Single-Board Computer), like the Raspberry Pi, you most likely want to use the x64 version.
|
||||
|
||||
Please check that you have downloaded the right version of Impostor, as we mantain two CPU architectures (x64 and ARM).
|
||||
Unless you are running Impostor on a computer like the Raspberry Pi, you most likely want to use the x64 version.
|
||||
|
||||
## `./Impostor.Server: Permission denied`
|
||||
|
||||
This is an error related to Linux file permissions.
|
||||
Some files do not hold their executable bit (the permission that allows them to run) during a download.
|
||||
You can solve this by doing: `chmod +x Impostor.Server`
|
||||
|
||||
## `You are using an older version of the game`
|
||||
You are using an older version of Impostor. The game does not really check who is outdated and blames it on the user.
|
||||
Make sure you got the latest working version of Impostor (probably in AppVeyor, not Github).
|
||||
## Disconnected with `Your client is too new, please update your Impostor to play`
|
||||
|
||||
## `You disconnected from the server. Reliable Packet 1 ...`
|
||||
Please double-check that you have followed the [Server Configuration](Server-configuration.md) correctly.
|
||||
**NOTE: Your public ip does not start with `127` nor `192`**
|
||||
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 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.
|
||||
|
||||
## Disconnected with `Please update your game to play on this server`
|
||||
|
||||
This happens when you're using a version of Impostor that is too new for your game version. You can download an older version from [the GitHub release page](https://github.com/Impostor/Impostor/releases). We however don't support older versions of Impostor with new API's and bugfixes so we recommend to update your game instead.
|
||||
|
||||
## Disconnected with `You are using an older version of the game`
|
||||
|
||||
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 CI works](https://nightly.link/Impostor/Impostor/workflows/ci/master).
|
||||
|
||||
## Disconnected with `You disconnected from the server. Reliable Packet 1 ...`
|
||||
|
||||
Please double-check that you have followed the [Server Configuration](Server-configuration.md) correctly.
|
||||
**NOTE: Your public ip does not start with `10`, `127` or `192`**
|
||||
Also check if the port Impostor (ListenPort) is listening on is correctly port-forwarded for UDP (or TCP/UDP).
|
||||
|
||||
## `Could not load file or assembly...`
|
||||
Please check that you only have **working** plugins in the `plugins` folder.
|
||||
|
||||
Please check that you only have **working** plugins in the `plugins` folder.
|
||||
This error can be caused by non-plugin files or plugins that are not working correctly.
|
||||
|
||||
## My question is not yet answered and I'm still having problems!
|
||||
|
||||
That's unfortunate. Join the [Impostor Discord](https://discord.gg/Mk3w6Tb), ask your question there and we'll try to help you out. Note that we're not always available, so it may take some time to get an answer. To make answering your question easier, please add the following details:
|
||||
|
||||
- Which version of Impostor are you using?
|
||||
- Which version or Among Us are you using?
|
||||
- Which operating system are you running Impostor on?
|
||||
- If you have console logs, attaching these will also help.
|
||||
+13
-16
@@ -19,31 +19,32 @@ 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 7, which includes:
|
||||
|
||||
- .NET Standard 2.0
|
||||
- .NET Standard 2.1
|
||||
- .NET Core 3.1
|
||||
- .NET 5
|
||||
- .NET 6
|
||||
- .NET 7
|
||||
|
||||
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** until .NET 5 is released officially. This should give you enough functionality. If not, upgrade to .NET Core 3.1.
|
||||
> At the moment of writing this document, I recommend you to use **.NET 7.0**.
|
||||
|
||||
When the project has been created, you should have `Class.cs` and `Project.csproj` files. Your `Project.csproj` should look something like this.
|
||||
|
||||
```xml
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
```
|
||||
@@ -62,16 +63,13 @@ Make sure to get a prerelease if you are writing a plugin for a dev release of t
|
||||
1. Right click your project.
|
||||
2. Click `Manage NuGet Packages`.
|
||||
3. Click `Browse`.
|
||||
4. Next to the search bar, enable `Include prerelease`.
|
||||
5. Search for `Impostor.Api`.
|
||||
6. Click the `Impostor.Api` result and press install on the right side.
|
||||
4. Search for `Impostor.Api`.
|
||||
5. Click the `Impostor.Api` result and press install on the right side.
|
||||
|
||||
### Dotnet CLI
|
||||
|
||||
> Make sure to grab the latest (pre-)release version from NuGet [here](https://www.nuget.org/packages/Impostor.Api).
|
||||
|
||||
1. Open your project folder in command prompt / bash.
|
||||
2. Run `dotnet add package Impostor.Api -v "1.2.0-ci.58"`.
|
||||
2. Run `dotnet add package Impostor.Api`.
|
||||
|
||||
## 4. The plugin class
|
||||
|
||||
@@ -272,7 +270,7 @@ Now your plugin is ready to be tested.
|
||||
|
||||
1. Right click your project and press `Build`.
|
||||
2. Right click your project and press `Open Folder in File Explorer`.
|
||||
3. Go to `bin/Debug/netstandard2.1/`.
|
||||
3. Go to `bin/Debug/net7.0/`.
|
||||
4. In this directory, you should find your plugin named `Project.dll`.
|
||||
5. Copy the `Project.dll` to the `plugins` directory in your Impostor server directory.
|
||||
6. (Re)start your Impostor server.
|
||||
@@ -295,7 +293,6 @@ Some extra information that might be useful for those developing plugins.
|
||||
- `IEventManager`
|
||||
- `IClientManager`
|
||||
- `IOptions<ServerConfig>`
|
||||
- `IOptions<ServerRedirectorConfig>`
|
||||
- You can add your own classes and `EventListener` implementation to the `IServiceProvider` by creating a new class and implementing `IPluginStartup`. Make sure to register them as a singleton `services.AddSingleton<IEventListener, GameEventListener>();`.
|
||||
|
||||
### Server configuration
|
||||
@@ -312,7 +309,7 @@ Constantly copying the plugin dll to your server directory can be pretty annoyin
|
||||
},
|
||||
"PluginLoader": {
|
||||
"Paths": [
|
||||
"D:\\Projects\\Impostor\\src\\Impostor.Plugins.Example\\bin\\Debug\\netstandard2.1"
|
||||
"D:\\Projects\\Impostor\\src\\Impostor.Plugins.Example\\bin\\Debug\\net7.0"
|
||||
],
|
||||
"LibraryPaths": []
|
||||
}
|
||||
@@ -340,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)
|
||||
+13
-4
@@ -4,8 +4,8 @@ root = true
|
||||
# Don't use tabs for indentation.
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = crlf
|
||||
insert_final_newline = false
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
|
||||
# Code files
|
||||
@@ -144,6 +144,12 @@ dotnet_naming_style.end_in_async.word_separator =
|
||||
# error RS2008: Enable analyzer release tracking for the analyzer project containing rule '{0}'
|
||||
dotnet_diagnostic.RS2008.severity = none
|
||||
|
||||
# IDE0005: Remove unnecessary import
|
||||
dotnet_diagnostic.IDE0005.severity = warning
|
||||
|
||||
# IDE0007: Use `var` instead of explicit type
|
||||
dotnet_diagnostic.IDE0007.severity = warning
|
||||
|
||||
# IDE0035: Remove unreachable code
|
||||
dotnet_diagnostic.IDE0035.severity = warning
|
||||
|
||||
@@ -163,7 +169,7 @@ csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
# csharp_new_line_before_members_in_object_initializers = true TODO seems like Rider/ReSharper has the value inverted, uncomment when its fixed
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
@@ -171,7 +177,7 @@ csharp_new_line_between_query_expression_clauses = true
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_case_contents_when_block = false
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = flush_left
|
||||
|
||||
@@ -228,3 +234,6 @@ csharp_preserve_single_line_statements = true
|
||||
|
||||
# warning RS0037: PublicAPI.txt is missing '#nullable enable'
|
||||
dotnet_diagnostic.RS0037.severity = none
|
||||
|
||||
# ReSharper properties
|
||||
resharper_trailing_comma_in_multiline_lists = true
|
||||
-149
@@ -26,21 +26,6 @@ bld/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
@@ -72,32 +57,12 @@ artifacts/
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
@@ -112,72 +77,11 @@ _TeamCity*
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
#*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
@@ -197,13 +101,6 @@ ClientBin/
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
@@ -212,52 +109,6 @@ Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<LangVersion>11</LangVersion>
|
||||
<VersionPrefix>1.8.4</VersionPrefix>
|
||||
<VersionSuffix>dev</VersionSuffix>
|
||||
<EnforceCodeStyleInBuild Condition="$(MSBuildProjectName)!='Hazel'">true</EnforceCodeStyleInBuild>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using Impostor.Api.Net.Inner;
|
||||
|
||||
namespace Impostor.Api
|
||||
{
|
||||
public class CheatContext
|
||||
{
|
||||
public CheatContext(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public static CheatContext Deserialize { get; } = new CheatContext(nameof(Deserialize));
|
||||
|
||||
public static CheatContext Serialize { get; } = new CheatContext(nameof(Serialize));
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public static implicit operator CheatContext(RpcCalls rpcCalls) => new CheatContext(rpcCalls.ToString());
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -1,9 +1,11 @@
|
||||
namespace Impostor.Server.Config
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class AntiCheatConfig
|
||||
{
|
||||
public const string Section = "AntiCheat";
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public bool BanIpFromGame { get; set; } = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,6 +6,6 @@
|
||||
|
||||
public bool GameRecorderEnabled { get; set; }
|
||||
|
||||
public string GameRecorderPath { get; set; }
|
||||
public string GameRecorderPath { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public static class DisconnectMessages
|
||||
{
|
||||
public const string Error = "There was an internal server error. " +
|
||||
"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.";
|
||||
|
||||
public const string UsernameLength = "Your username is too long, please make it shorter.";
|
||||
|
||||
public const string UsernameIllegalCharacters = "Your username contains illegal characters, please remove them.";
|
||||
|
||||
public const string VersionClientTooOld = "Please update your game to play on this server.";
|
||||
|
||||
public const string VersionServerTooOld = "Your client is too new, please update your Impostor server to play.";
|
||||
|
||||
public const string VersionUnsupported = "Your client version is unsupported, please update your Game and/or Impostor server.";
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,14 +1,14 @@
|
||||
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";
|
||||
|
||||
private string? _resolvedPublicIp;
|
||||
private string? _resolvedListenIp;
|
||||
|
||||
public const string Section = "Server";
|
||||
|
||||
public string PublicIp { get; set; } = "127.0.0.1";
|
||||
|
||||
public ushort PublicPort { get; set; } = 22023;
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Impostor.Api.Config
|
||||
{
|
||||
public class TimeoutConfig
|
||||
{
|
||||
public const string Section = "Timeout";
|
||||
|
||||
public int SpawnTimeout { get; set; } = 2500;
|
||||
|
||||
public int ConnectionTimeout { get; set; } = 2500;
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,18 @@ namespace Impostor.Api.Events
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The priority of the event listener.
|
||||
/// Gets or sets the priority of the event listener.
|
||||
/// </summary>
|
||||
public EventPriority Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The events that the listener is listening to.
|
||||
/// Gets or sets the event that the listener is listening to.
|
||||
/// </summary>
|
||||
public Type? Event { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the listener will be called regardless of the <see cref="IEventCancelable.IsCancelled"/>.
|
||||
/// Gets or sets a value indicating whether the listener will be called regardless of the <see cref="IEventCancelable.IsCancelled" />.
|
||||
/// </summary>
|
||||
public bool IgnoreCancelled { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Called just after a <see cref="IClient"/> is created and connected.
|
||||
/// </summary>
|
||||
public interface IClientConnectedEvent : IClientEvent
|
||||
{
|
||||
IClient Client { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Called just before a <see cref="IHazelConnection"/> is registered.
|
||||
/// </summary>
|
||||
public interface IClientConnectionEvent : IClientEvent
|
||||
{
|
||||
IMessageReader HandshakeData { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events.Client
|
||||
{
|
||||
public interface IClientEvent : IEvent
|
||||
{
|
||||
IHazelConnection Connection { get; }
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Called whenever a new <see cref="IGame"/> is created.
|
||||
/// Called whenever a new <see cref="IGame" /> is created.
|
||||
/// </summary>
|
||||
public interface IGameCreatedEvent : IGameEvent
|
||||
{
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Called just before a new <see cref="IGame"/> is created.
|
||||
/// </summary>
|
||||
public interface IGameCreationEvent : IEventCancelable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the client that requested creation of the game.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Will be null if game creation was requested by a plugin.
|
||||
/// </remarks>
|
||||
IClient? Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the desired <see cref="Games.GameCode"/>.
|
||||
/// </summary>
|
||||
/// <exception cref="ImpostorException">If the GameCode is invalid or already used in another game.</exception>
|
||||
GameCode? GameCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Called whenever a new <see cref="IGame"/> is destroyed.
|
||||
/// Called whenever a new <see cref="IGame" /> is destroyed.
|
||||
/// </summary>
|
||||
public interface IGameDestroyedEvent : IGameEvent
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Impostor.Api.Events
|
||||
public interface IGameEvent : IEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IGame"/> this event belongs to.
|
||||
/// Gets the <see cref="IGame" /> this event belongs to.
|
||||
/// </summary>
|
||||
IGame Game { get; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
public interface IGameHostChangedEvent : IGameEvent
|
||||
{
|
||||
IClientPlayer PreviousHost { get; }
|
||||
|
||||
IClientPlayer? NewHost { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
namespace Impostor.Api.Events
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
public interface IGamePlayerJoinedEvent : IGameEvent
|
||||
{
|
||||
IClientPlayer Player { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Called just before a <see cref="IClientPlayer"/> joins a game.
|
||||
/// </summary>
|
||||
public interface IGamePlayerJoiningEvent : IGameEvent
|
||||
{
|
||||
IClientPlayer Player { get; }
|
||||
|
||||
GameJoinResult? JoinResult { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
namespace Impostor.Api.Events
|
||||
using Impostor.Api.Net;
|
||||
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
public interface IGamePlayerLeftEvent : IGameEvent
|
||||
{
|
||||
IClientPlayer Player { get; }
|
||||
|
||||
bool IsBan { get; }
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Called when the game is going to start.
|
||||
/// When this is called, not all players are initialized properly yet.
|
||||
/// If you want to get correct player states, use <see cref="IGameStartedEvent"/>.
|
||||
/// If you want to get correct player states, use <see cref="IGameStartedEvent" />.
|
||||
/// </summary>
|
||||
public interface IGameStartingEvent : IGameEvent
|
||||
{
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
namespace Impostor.Api.Events.Meeting
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Events.Meeting
|
||||
{
|
||||
public interface IMeetingEndedEvent : IMeetingEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the exiled player.
|
||||
/// </summary>
|
||||
IInnerPlayerControl? Exiled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether meeting result is a tie.
|
||||
/// </summary>
|
||||
bool IsTie { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
public interface IPlayerChatEvent : IPlayerEvent
|
||||
public interface IPlayerChatEvent : IPlayerEvent, IEventCancelable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the message sent by the player.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Called whenever a player enters a vent.
|
||||
/// </summary>
|
||||
public interface IPlayerEnterVentEvent : IPlayerEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entered vent.
|
||||
/// </summary>
|
||||
public IVent Vent { get; }
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,14 @@ namespace Impostor.Api.Events.Player
|
||||
public interface IPlayerEvent : IGameEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IClientPlayer"/> that triggered this <see cref="IPlayerEvent"/>.
|
||||
/// Gets the <see cref="IClientPlayer" /> that triggered this <see cref="IPlayerEvent" />.
|
||||
/// </summary>
|
||||
IClientPlayer ClientPlayer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the networked <see cref="IInnerPlayerControl"/> that triggered this <see cref="IPlayerEvent"/>.
|
||||
/// This <see cref="IInnerPlayerControl"/> belongs to the <see cref="IClientPlayer"/>.
|
||||
/// Gets the networked <see cref="IInnerPlayerControl" /> that triggered this <see cref="IPlayerEvent" />.
|
||||
/// This <see cref="IInnerPlayerControl" /> belongs to the <see cref="IClientPlayer" />.
|
||||
/// </summary>
|
||||
IInnerPlayerControl PlayerControl { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Called whenever a player exits a vent.
|
||||
/// </summary>
|
||||
public interface IPlayerExitVentEvent : IPlayerEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the exited vent.
|
||||
/// </summary>
|
||||
public IVent Vent { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
public interface IPlayerMovementEvent : IPlayerEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Impostor.Api.Events.Player
|
||||
public interface IPlayerStartMeetingEvent : IPlayerEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player who's body got reported. Is null when the meeting started by Emergency call button
|
||||
/// Gets the player who's body got reported. Is null when the meeting started by Emergency call button.
|
||||
/// </summary>
|
||||
IInnerPlayerControl? Body { get; }
|
||||
}
|
||||
|
||||
@@ -2,16 +2,14 @@ using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Called whenever a player moves to another vent.
|
||||
/// </summary>
|
||||
public interface IPlayerVentEvent : IPlayerEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets get the id of the used vent.
|
||||
/// Gets the vent player moved to.
|
||||
/// </summary>
|
||||
public VentLocation VentId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the vent was entered or exited.
|
||||
/// </summary>
|
||||
public bool VentEnter { get; }
|
||||
public IVent NewVent { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
public enum VoteType : byte
|
||||
{
|
||||
HasNotVoted = 255,
|
||||
Missed = 254,
|
||||
Skipped = 253,
|
||||
Dead = 252,
|
||||
Player = 0,
|
||||
}
|
||||
|
||||
public interface IPlayerVotedEvent : IPlayerEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the player he voted for.
|
||||
/// </summary>
|
||||
IInnerPlayerControl? VotedFor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Vote type.
|
||||
/// </summary>
|
||||
VoteType VoteType { get; }
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,4 @@
|
||||
public interface IEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
public interface IEventCancelable : IEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// True if the event was cancelled.
|
||||
/// Gets or sets a value indicating whether the event was cancelled.
|
||||
/// </summary>
|
||||
bool IsCancelled { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,4 @@
|
||||
public interface IEventListener
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ namespace Impostor.Api.Events
|
||||
{
|
||||
public interface IManualEventListener : IEventListener
|
||||
{
|
||||
EventPriority Priority { get; set; }
|
||||
|
||||
public bool CanExecute<T>();
|
||||
|
||||
public ValueTask Execute(IEvent @event);
|
||||
|
||||
EventPriority Priority { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,20 +16,20 @@ namespace Impostor.Api.Events.Managers
|
||||
where TListener : IEventListener;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if an event with the type <see cref="TEvent"/> is registered.
|
||||
/// Returns true if an event with the type <typeparamref name="TEvent" /> is registered.
|
||||
/// </summary>
|
||||
/// <returns>True if the <see cref="TEvent"/> is registered.</returns>
|
||||
/// <returns>True if the <typeparamref name="TEvent" /> is registered.</returns>
|
||||
/// <typeparam name="TEvent">Type of the event.</typeparam>
|
||||
bool IsRegistered<TEvent>()
|
||||
where TEvent : IEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Call all the event listeners for the type <see cref="TEvent"/>.
|
||||
/// Call all the event listeners for the type <typeparamref name="TEvent" />.
|
||||
/// </summary>
|
||||
/// <param name="event">The event argument.</param>
|
||||
/// <typeparam name="TEvent">Type of the event.</typeparam>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask CallAsync<TEvent>(TEvent @event)
|
||||
where TEvent : IEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Impostor.Server.Events
|
||||
namespace Impostor.Api.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Disposes multiple <see cref="IDisposable"/>.
|
||||
/// Disposes multiple <see cref="IDisposable" />.
|
||||
/// </summary>
|
||||
internal class MultiDisposable : IDisposable
|
||||
public class MultiDisposable : IDisposable
|
||||
{
|
||||
private readonly IEnumerable<IDisposable> _disposables;
|
||||
|
||||
@@ -15,6 +16,10 @@ namespace Impostor.Server.Events
|
||||
_disposables = disposables;
|
||||
}
|
||||
|
||||
public MultiDisposable(params IDisposable[] disposables) : this(disposables.AsEnumerable())
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var disposable in _disposables)
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Impostor.Api
|
||||
{
|
||||
public class ImpostorCheatException : ImpostorException
|
||||
{
|
||||
public ImpostorCheatException()
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorCheatException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ImpostorCheatException(string? message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ImpostorCheatException(string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,6 @@ namespace Impostor.Api
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorConfigException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ImpostorConfigException(string? message) : base(message)
|
||||
{
|
||||
}
|
||||
@@ -20,5 +16,9 @@ namespace Impostor.Api
|
||||
public ImpostorConfigException(string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorConfigException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,6 @@ namespace Impostor.Api
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ImpostorException(string? message) : base(message)
|
||||
{
|
||||
}
|
||||
@@ -20,5 +16,9 @@ namespace Impostor.Api
|
||||
public ImpostorException(string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,6 @@ namespace Impostor.Api
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorProtocolException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ImpostorProtocolException(string? message) : base(message)
|
||||
{
|
||||
}
|
||||
@@ -20,5 +16,9 @@ namespace Impostor.Api
|
||||
public ImpostorProtocolException(string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected ImpostorProtocolException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Impostor.Api
|
||||
{
|
||||
public static class DictionaryExtensions
|
||||
{
|
||||
/// <summary>Returns a read-only <see cref="ReadOnlyDictionary{TKey,TValue}" /> wrapper for the dictionary.</summary>
|
||||
/// <param name="dictionary">An <see cref="IDictionary{TKey,TValue}" /> to create a <see cref="ReadOnlyDictionary{TKey,TValue}" /> from.</param>
|
||||
/// <typeparam name="TKey">The type of the keys of <paramref name="dictionary" />.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the values of <paramref name="dictionary" />.</typeparam>
|
||||
/// <returns>An object that acts as a read-only wrapper around the <see cref="IDictionary{TKey,TValue}" />.</returns>
|
||||
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
|
||||
where TKey : notnull
|
||||
{
|
||||
return new ReadOnlyDictionary<TKey, TValue>(dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
||||
namespace Impostor.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Priovides a StreamReader-like api throught extensions
|
||||
/// Priovides a StreamReader-like api throught extensions.
|
||||
/// </summary>
|
||||
public static class SpanReaderExtensions
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -35,9 +42,7 @@ namespace Impostor.Api
|
||||
{
|
||||
var original = Advance<float>(ref input);
|
||||
|
||||
// BitConverter.Int32BitsToSingle
|
||||
// Doesn't exist in net 2.0 for some reason
|
||||
return Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(original));
|
||||
return BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(original));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -46,18 +51,12 @@ namespace Impostor.Api
|
||||
return input.ReadByte() != 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe float Int32BitsToSingle(int value)
|
||||
{
|
||||
return *((float*)&value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Advances the position of <see cref="input"/> by the size of <see cref="T"/>.
|
||||
/// Advances the position of <paramref name="input" /> by the size of <typeparamref name="T" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type that will be read.</typeparam>
|
||||
/// <param name="input">input "stream"/span.</param>
|
||||
/// <returns>The original input</returns>
|
||||
/// <returns>The original input.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ReadOnlySpan<byte> Advance<T>(ref ReadOnlySpan<byte> input)
|
||||
where T : unmanaged
|
||||
@@ -67,4 +66,4 @@ namespace Impostor.Api
|
||||
return original;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,4 @@ namespace Impostor.Api
|
||||
return SystemTypeHelpers.Names[(int)type];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Games
|
||||
{
|
||||
@@ -39,4 +38,4 @@ namespace Impostor.Api.Games
|
||||
return game.SendToAsync(writer, player.Client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Impostor.Api.Games
|
||||
{
|
||||
public static int GetGameCount(this IGameManager manager, MapFlags map)
|
||||
{
|
||||
return manager.Games.Count(game => map.HasFlag((MapFlags)(1 << game.Options.MapId)));
|
||||
return manager.Games.Count(game => map.HasFlag((MapFlags)(1 << (byte)game.Options.Map)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Games
|
||||
@@ -14,13 +14,15 @@ namespace Impostor.Api.Games
|
||||
public GameCode(string code)
|
||||
{
|
||||
Value = GameCodeParser.GameNameToInt(code);
|
||||
Code = code;
|
||||
Code = code.ToUpperInvariant();
|
||||
}
|
||||
|
||||
public string Code { get; }
|
||||
|
||||
public int Value { get; }
|
||||
|
||||
public bool IsInvalid => Value == -1;
|
||||
|
||||
public static implicit operator string(GameCode code) => code.Code;
|
||||
|
||||
public static implicit operator int(GameCode code) => code.Value;
|
||||
@@ -48,19 +50,19 @@ namespace Impostor.Api.Games
|
||||
|
||||
public static GameCode From(string value) => new GameCode(value);
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc />
|
||||
public bool Equals(GameCode other)
|
||||
{
|
||||
return Code == other.Code && Value == other.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is GameCode other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Code, Value);
|
||||
@@ -71,4 +73,4 @@ namespace Impostor.Api.Games
|
||||
return Code;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,12 +37,22 @@
|
||||
/// </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>
|
||||
/// <remarks>
|
||||
/// A custom message can be set in <see cref="GameJoinResult.Message"/>.
|
||||
/// A custom message can be set in <see cref="GameJoinResult.Message" />.
|
||||
/// </remarks>
|
||||
Custom,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,4 +45,4 @@ namespace Impostor.Api.Games
|
||||
return new GameJoinResult(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,17 @@
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Innersloth.GameOptions;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Inner;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Games
|
||||
{
|
||||
public interface IGame
|
||||
{
|
||||
GameOptionsData Options { get; }
|
||||
IGameOptions Options { get; }
|
||||
|
||||
GameFilterOptions FilterOptions { get; }
|
||||
|
||||
GameCode Code { get; }
|
||||
|
||||
@@ -25,47 +26,54 @@ namespace Impostor.Api.Games
|
||||
|
||||
int PlayerCount { get; }
|
||||
|
||||
IClientPlayer Host { get; }
|
||||
IClientPlayer? Host { get; }
|
||||
|
||||
bool IsPublic { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets display name on game list.
|
||||
/// </summary>
|
||||
string? DisplayName { get; set; }
|
||||
|
||||
IDictionary<object, object> Items { get; }
|
||||
|
||||
int HostId { get; }
|
||||
|
||||
IClientPlayer GetClientPlayer(int clientId);
|
||||
IClientPlayer? GetClientPlayer(int clientId);
|
||||
|
||||
T? FindObjectByNetId<T>(uint netId)
|
||||
where T : IInnerNetObject;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IPAddress"/> to the ban list of this game.
|
||||
/// Prevents all future joins from this <see cref="IPAddress"/>.
|
||||
///
|
||||
/// This does not kick the player with that <see cref="IPAddress"/> from the lobby.
|
||||
/// Adds an <see cref="IPAddress" /> to the ban list of this game.
|
||||
/// Prevents all future joins from this <see cref="IPAddress" />.
|
||||
/// This does not kick the player with that <see cref="IPAddress" /> from the lobby.
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">
|
||||
/// The <see cref="IPAddress"/> to ban.
|
||||
/// The <see cref="IPAddress" /> to ban.
|
||||
/// </param>
|
||||
void BanIp(IPAddress ipAddress);
|
||||
|
||||
/// <summary>
|
||||
/// Syncs the internal <see cref="GameOptionsData"/> to all players.
|
||||
/// Syncs the internal <see cref="IGameOptions" /> to all players.
|
||||
/// Necessary to do if you modified it, otherwise it won't be used.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask SyncSettingsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified list as Impostor on all connected players.
|
||||
/// Sets game's privacy.
|
||||
/// </summary>
|
||||
/// <param name="players">List of players to be Impostor.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
ValueTask SetInfectedAsync(IEnumerable<IInnerPlayerControl> players);
|
||||
/// <param name="isPublic">Privacy to set.</param>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask SetPrivacyAsync(bool isPublic);
|
||||
|
||||
/// <summary>
|
||||
/// Send the message to all players.
|
||||
/// </summary>
|
||||
/// <param name="writer">Message to send.</param>
|
||||
/// <param name="states">Required limbo state of the player.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask SendToAllAsync(IMessageWriter writer, LimboStates states = LimboStates.NotLimbo);
|
||||
|
||||
/// <summary>
|
||||
@@ -74,7 +82,7 @@ namespace Impostor.Api.Games
|
||||
/// <param name="writer">Message to send.</param>
|
||||
/// <param name="senderId">The player to exclude from sending the message.</param>
|
||||
/// <param name="states">Required limbo state of the player.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask SendToAllExceptAsync(IMessageWriter writer, int senderId, LimboStates states = LimboStates.NotLimbo);
|
||||
|
||||
/// <summary>
|
||||
@@ -82,7 +90,26 @@ namespace Impostor.Api.Games
|
||||
/// </summary>
|
||||
/// <param name="writer">Message to send.</param>
|
||||
/// <param name="id">ID of the client.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask SendToAsync(IMessageWriter writer, int id);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a MessageWriter with GameData header.
|
||||
/// </summary>
|
||||
/// <remarks>Use with caution, recommended only for advanced developers.</remarks>
|
||||
/// <param name="targetNetId">Net id of the InnerNetObject.</param>
|
||||
/// <param name="callId">Rpc id of the message.</param>
|
||||
/// <param name="targetClientId">Client id of GameDataTo's target.</param>
|
||||
/// <param name="type">Message type of the message.</param>
|
||||
/// <returns>A <see cref="IMessageWriter" /> that you can fill with rpc data and send using <see cref="FinishRpcAsync"/>.</returns>
|
||||
IMessageWriter StartRpc(uint targetNetId, RpcCalls callId, int? targetClientId, MessageType type = MessageType.Reliable);
|
||||
|
||||
/// <summary>
|
||||
/// Finishes rpc message and sends it to the target.
|
||||
/// </summary>
|
||||
/// <param name="writer">Message writer of the rpc.</param>
|
||||
/// <param name="targetClientId">Id of the receiving client.</param>
|
||||
/// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
|
||||
ValueTask FinishRpcAsync(IMessageWriter writer, int? targetClientId = null);
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@
|
||||
{
|
||||
GameCode Create();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Innersloth.GameOptions;
|
||||
|
||||
namespace Impostor.Api.Games.Managers
|
||||
{
|
||||
@@ -7,5 +10,14 @@ namespace Impostor.Api.Games.Managers
|
||||
IEnumerable<IGame> Games { get; }
|
||||
|
||||
IGame? Find(GameCode code);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new game.
|
||||
/// </summary>
|
||||
/// <param name="options">Game options.</param>
|
||||
/// <param name="filterOptions">Filter options.</param>
|
||||
/// <returns>Created game or null if creation was cancelled by a plugin.</returns>
|
||||
/// <exception cref="ImpostorException">Thrown when game creation failed.</exception>
|
||||
ValueTask<IGame?> CreateAsync(IGameOptions options, GameFilterOptions filterOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Impostor.Hazel.Abstractions;
|
||||
@@ -1,12 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<CodeAnalysisRuleSet>ProjectRules.ruleset</CodeAnalysisRuleSet>
|
||||
<LangVersion>9</LangVersion>
|
||||
<CodeAnalysisRuleSet>../ProjectRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>1.0.0</Version>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<AssemblyName>Impostor.Api</AssemblyName>
|
||||
@@ -16,23 +13,22 @@
|
||||
<PackageId>Impostor.Api</PackageId>
|
||||
<PackageTags>Among Us;Impostor;Impostor Plugin</PackageTags>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/Impostor/Impostor/dev/docs/images/logo_64.png</PackageIconUrl>
|
||||
<PackageIcon>logo_64.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/Impostor/Impostor</PackageProjectUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/Impostor/Impostor</RepositoryUrl>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Nullable" Version="1.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<None Include="../../docs/images/logo_64.png" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
|
||||
<PackageReference Include="Impostor.Hazel.Abstractions" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -4,4 +4,4 @@
|
||||
{
|
||||
ChangePrivacy = 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@
|
||||
{
|
||||
DidVote = 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Impostor.Api.Innersloth;
|
||||
|
||||
public enum CrossplayFlags
|
||||
{
|
||||
Unknown = 0,
|
||||
StandaloneEpicPC = 1 << 1,
|
||||
StandaloneSteamPC = 1 << 2,
|
||||
StandaloneMac = 1 << 3,
|
||||
StandaloneWin10 = 1 << 4,
|
||||
StandaloneItch = 1 << 5,
|
||||
IPhone = 1 << 6,
|
||||
Android = 1 << 7,
|
||||
Switch = 1 << 8,
|
||||
Xbox = 1 << 9,
|
||||
Playstation = 1 << 10,
|
||||
All = int.MaxValue,
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum ColorType : byte
|
||||
public enum ColorType
|
||||
{
|
||||
Red = 0,
|
||||
Blue = 1,
|
||||
@@ -14,5 +14,11 @@
|
||||
Brown = 9,
|
||||
Cyan = 10,
|
||||
Lime = 11,
|
||||
Maroon = 12,
|
||||
Rose = 13,
|
||||
Banana = 14,
|
||||
Gray = 15,
|
||||
Tan = 16,
|
||||
Coral = 17,
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum HatType
|
||||
{
|
||||
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,
|
||||
Fedora = 43,
|
||||
Goggles2 = 44,
|
||||
Headphones = 45,
|
||||
MaskHat = 46,
|
||||
PaperMask = 47,
|
||||
Security = 48,
|
||||
StrapHat = 49,
|
||||
Banana = 50,
|
||||
Beanie = 51,
|
||||
Bear = 52,
|
||||
Cheese = 53,
|
||||
Cherry = 54,
|
||||
Egg = 55,
|
||||
Fedora2 = 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,
|
||||
Snowman2 = 93,
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum PetType
|
||||
{
|
||||
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,54 @@
|
||||
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,22 +0,0 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum SkinType : byte
|
||||
{
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,4 @@
|
||||
Kill = 1,
|
||||
Disconnect = 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,52 +3,66 @@
|
||||
public enum DisconnectReason
|
||||
{
|
||||
ExitGame = 0,
|
||||
Destroy = 16,
|
||||
|
||||
// The game you tried to join is full.
|
||||
// Check with the host to see if you can join next round.
|
||||
GameFull = 1,
|
||||
|
||||
// The game you tried to join already started.
|
||||
// Check with the host to see if you can join next round.
|
||||
GameStarted = 2,
|
||||
// Could not find the game you're looking for.
|
||||
|
||||
// Could not find the game you're looking for..
|
||||
GameMissing = 3,
|
||||
IncorrectGame = 18,
|
||||
// For these a message can be given, specifying an empty message shows
|
||||
|
||||
// For this a message can be given, specifying an empty message shows
|
||||
// "An unknown error disconnected you from the server."
|
||||
CustomMessage1 = 4,
|
||||
// 4, 12, 13, 14, 15 also count as Custom
|
||||
Custom = 8,
|
||||
// CustomMessage3 = 11,
|
||||
// CustomMessage4 = 12,
|
||||
// CustomMessage5 = 13,
|
||||
// CustomMessage6 = 14,
|
||||
// CustomMessage7 = 15,
|
||||
|
||||
// You are running an older version of the game.
|
||||
// Please update to play with others.
|
||||
IncorrectVersion = 5,
|
||||
|
||||
// You were banned from { GameCode ?? "the room" }
|
||||
// You cannot rejoin that room.
|
||||
// You were banned
|
||||
Banned = 6,
|
||||
// You can rejoin if the room hasn't started
|
||||
// You were kicked
|
||||
|
||||
// You were kicked from { GameCode ?? "the room" }
|
||||
// You can rejoin if the room hasn't started.
|
||||
Kicked = 7,
|
||||
|
||||
// You were banned for hacking.
|
||||
// Please stop.
|
||||
Hacking = 10,
|
||||
Destroy = 16,
|
||||
|
||||
// GameModes.LocalGame:
|
||||
// You disconnected from the host.
|
||||
// If this happens often, check your WiFi strength.
|
||||
//
|
||||
// GameModes.OnlineGame:
|
||||
// You disconnected from the server.
|
||||
// If this happens often, check your network strength.
|
||||
// This may also be a server issue.
|
||||
Error = 17,
|
||||
|
||||
// The server stopped this game. Possibly due to inactivity.
|
||||
ServerRequest = 19,
|
||||
|
||||
// The Among Us servers are overloaded.
|
||||
// Sorry! Please try again later!
|
||||
ServerFull = 20,
|
||||
|
||||
FocusLostBackground = 207,
|
||||
|
||||
// You may not join another game for another { BanMinutesLeft } minutes after intentionally disconnecting.
|
||||
IntentionalLeaving = 208,
|
||||
|
||||
// You were disconnected because Among Us was suspended by another app.
|
||||
FocusLost = 209,
|
||||
|
||||
NewConnection = 210,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Impostor.Api.Unity;
|
||||
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public class FloatRange
|
||||
{
|
||||
private readonly float _min;
|
||||
private readonly float _max;
|
||||
|
||||
public FloatRange(float min, float max)
|
||||
{
|
||||
_min = min;
|
||||
_max = max;
|
||||
}
|
||||
|
||||
public float Width => _max - _min;
|
||||
|
||||
public float Lerp(float v) => Mathf.Lerp(_min, _max, v);
|
||||
|
||||
public float ReverseLerp(float t) => Mathf.Clamp((t - _min) / Width, 0.0f, 1f);
|
||||
}
|
||||
}
|
||||
@@ -9,36 +9,9 @@ namespace Impostor.Api.Innersloth
|
||||
public static class GameCodeParser
|
||||
{
|
||||
private const string V2 = "QWXRTYLPESDFGHUJKZOCVBINMA";
|
||||
private static readonly int[] V2Map = {
|
||||
25,
|
||||
21,
|
||||
19,
|
||||
10,
|
||||
8,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
22,
|
||||
15,
|
||||
16,
|
||||
6,
|
||||
24,
|
||||
23,
|
||||
18,
|
||||
7,
|
||||
0,
|
||||
3,
|
||||
9,
|
||||
4,
|
||||
14,
|
||||
20,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17
|
||||
};
|
||||
private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
|
||||
|
||||
|
||||
private static readonly int[] V2Map = Enumerable.Range(65, 26).Select(v => V2.IndexOf((char)v)).ToArray();
|
||||
|
||||
public static string IntToGameName(int input)
|
||||
{
|
||||
// V2.
|
||||
@@ -57,22 +30,6 @@ namespace Impostor.Api.Innersloth
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string IntToGameNameV2(int input)
|
||||
{
|
||||
var a = input & 0x3FF;
|
||||
var b = (input >> 10) & 0xFFFFF;
|
||||
|
||||
return new string(new []
|
||||
{
|
||||
V2[a % 26],
|
||||
V2[a / 26],
|
||||
V2[b % 26],
|
||||
V2[b / 26 % 26],
|
||||
V2[b / (26 * 26) % 26],
|
||||
V2[b / (26 * 26 * 26) % 26]
|
||||
});
|
||||
}
|
||||
|
||||
public static int GameNameToInt(string code)
|
||||
{
|
||||
var upper = code.ToUpperInvariant();
|
||||
@@ -80,7 +37,7 @@ namespace Impostor.Api.Innersloth
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
var len = code.Length;
|
||||
if (len == 6)
|
||||
{
|
||||
@@ -91,24 +48,9 @@ namespace Impostor.Api.Innersloth
|
||||
{
|
||||
return code[0] | ((code[1] | ((code[2] | (code[3] << 8)) << 8)) << 8);
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int GameNameToIntV2(string code)
|
||||
{
|
||||
var a = V2Map[code[0] - 65];
|
||||
var b = V2Map[code[1] - 65];
|
||||
var c = V2Map[code[2] - 65];
|
||||
var d = V2Map[code[3] - 65];
|
||||
var e = V2Map[code[4] - 65];
|
||||
var f = V2Map[code[5] - 65];
|
||||
|
||||
var one = (a + 26 * b) & 0x3FF;
|
||||
var two = (c + 26 * (d + 26 * (e + 26 * f)));
|
||||
|
||||
return (int) (one | ((two << 10) & 0x3FFFFC00) | 0x80000000);
|
||||
}
|
||||
|
||||
public static int GenerateCode(int len)
|
||||
{
|
||||
@@ -116,15 +58,15 @@ namespace Impostor.Api.Innersloth
|
||||
{
|
||||
throw new ArgumentException("should be 4 or 6", nameof(len));
|
||||
}
|
||||
|
||||
|
||||
// Generate random bytes.
|
||||
#if NETSTANDARD2_0
|
||||
var data = new byte[len];
|
||||
#else
|
||||
Span<byte> data = stackalloc byte[len];
|
||||
#endif
|
||||
Random.GetBytes(data);
|
||||
|
||||
RandomNumberGenerator.Fill(data);
|
||||
|
||||
// Convert to their char representation.
|
||||
Span<char> dataChar = stackalloc char[len];
|
||||
for (var i = 0; i < len; i++)
|
||||
@@ -138,5 +80,36 @@ namespace Impostor.Api.Innersloth
|
||||
return GameNameToInt(new string(dataChar));
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string IntToGameNameV2(int input)
|
||||
{
|
||||
var a = input & 0x3FF;
|
||||
var b = (input >> 10) & 0xFFFFF;
|
||||
|
||||
return new string(new[]
|
||||
{
|
||||
V2[a % 26],
|
||||
V2[a / 26],
|
||||
V2[b % 26],
|
||||
V2[(b / 26) % 26],
|
||||
V2[(b / (26 * 26)) % 26],
|
||||
V2[(b / (26 * 26 * 26)) % 26],
|
||||
});
|
||||
}
|
||||
|
||||
private static int GameNameToIntV2(string code)
|
||||
{
|
||||
var a = V2Map[code[0] - 65];
|
||||
var b = V2Map[code[1] - 65];
|
||||
var c = V2Map[code[2] - 65];
|
||||
var d = V2Map[code[3] - 65];
|
||||
var e = V2Map[code[4] - 65];
|
||||
var f = V2Map[code[5] - 65];
|
||||
|
||||
var one = (a + (26 * b)) & 0x3FF;
|
||||
var two = c + (26 * (d + (26 * (e + (26 * f)))));
|
||||
|
||||
return (int)(one | ((two << 10) & 0x3FFFFC00) | 0x80000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Impostor.Api.Innersloth;
|
||||
|
||||
public class GameFilterOptions
|
||||
{
|
||||
public HashSet<string> FilterTags { get; } = new HashSet<string>();
|
||||
|
||||
public static GameFilterOptions CreateDefault()
|
||||
{
|
||||
return new GameFilterOptions
|
||||
{
|
||||
FilterTags =
|
||||
{
|
||||
"Beginner",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public static GameFilterOptions Deserialize(IMessageReader reader)
|
||||
{
|
||||
var options = new GameFilterOptions();
|
||||
|
||||
var count = reader.ReadPackedInt32();
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
options.FilterTags.Add(reader.ReadString());
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.WritePacked(FilterTags.Count);
|
||||
foreach (var filterTag in FilterTags)
|
||||
{
|
||||
writer.Write(filterTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,24 @@ namespace Impostor.Api.Innersloth
|
||||
public enum GameKeywords : uint
|
||||
{
|
||||
All = 0,
|
||||
Other = 1,
|
||||
Spanish = 2,
|
||||
English = 256,
|
||||
SpanishLA = 2,
|
||||
Brazilian = 2048,
|
||||
Portuguese = 16,
|
||||
Korean = 4,
|
||||
Russian = 8,
|
||||
Portuguese = 16,
|
||||
Dutch = 4096,
|
||||
Filipino = 64,
|
||||
French = 8192,
|
||||
German = 16384,
|
||||
Italian = 32768,
|
||||
Japanese = 512,
|
||||
SpanishEU = 1024,
|
||||
Arabic = 32,
|
||||
Filipone = 64,
|
||||
Polish = 128,
|
||||
English = 256,
|
||||
SChinese = 65536,
|
||||
TChinese = 131072,
|
||||
Irish = 262144,
|
||||
Other = 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public enum GameModes : byte
|
||||
{
|
||||
None,
|
||||
Normal,
|
||||
HideNSeek,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Innersloth.GameOptions;
|
||||
|
||||
public static class GameOptionsFactory
|
||||
{
|
||||
public const byte ModularOptionsDataVersion = 7;
|
||||
|
||||
public static void Serialize(IMessageWriter writer, IGameOptions gameOptions)
|
||||
{
|
||||
if (gameOptions.Version < ModularOptionsDataVersion)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
// In theory we should use WriteBytesAndSize here, but it's costly and requires computing the size
|
||||
// Base game does similar hacks and completely ignores this value for modular game options so we can just write 0 here
|
||||
writer.WritePacked(0);
|
||||
|
||||
writer.Write(gameOptions.Version);
|
||||
writer.StartMessage(0);
|
||||
writer.Write((byte)gameOptions.GameMode);
|
||||
gameOptions.Serialize(writer);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static IGameOptions Deserialize(IMessageReader reader)
|
||||
{
|
||||
reader.ReadPackedInt32();
|
||||
var version = reader.ReadByte();
|
||||
|
||||
if (version < ModularOptionsDataVersion)
|
||||
{
|
||||
return LegacyGameOptionsData.Deserialize(reader, version);
|
||||
}
|
||||
|
||||
var optionsReader = reader.ReadMessage();
|
||||
var gameMode = (GameModes)optionsReader.ReadByte();
|
||||
|
||||
return gameMode switch
|
||||
{
|
||||
GameModes.Normal => NormalGameOptions.Deserialize(optionsReader, version),
|
||||
GameModes.HideNSeek => HideNSeekGameOptions.Deserialize(optionsReader, version),
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
}
|
||||
|
||||
public static void DeserializeInto(IMessageReader reader, IGameOptions gameOptions)
|
||||
{
|
||||
reader.ReadPackedInt32();
|
||||
var version = reader.ReadByte();
|
||||
|
||||
if (version < ModularOptionsDataVersion)
|
||||
{
|
||||
((LegacyGameOptionsData)gameOptions).Deserialize(reader);
|
||||
return;
|
||||
}
|
||||
|
||||
var optionsReader = reader.ReadMessage();
|
||||
var gameMode = (GameModes)optionsReader.ReadByte();
|
||||
|
||||
switch (gameMode)
|
||||
{
|
||||
case GameModes.Normal:
|
||||
((NormalGameOptions)gameOptions).Deserialize(optionsReader);
|
||||
break;
|
||||
case GameModes.HideNSeek:
|
||||
((HideNSeekGameOptions)gameOptions).Deserialize(optionsReader);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(gameMode), gameMode, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
namespace Impostor.Api.Innersloth.GameOptions;
|
||||
|
||||
public class HideNSeekGameOptions : IGameOptions
|
||||
{
|
||||
public const int LatestVersion = 7;
|
||||
|
||||
public HideNSeekGameOptions(byte version = LatestVersion)
|
||||
{
|
||||
Version = version;
|
||||
IGameOptions.EnsureVersionIsModular<HideNSeekGameOptions>(version);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte Version { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public GameModes GameMode => GameModes.HideNSeek;
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte MaxPlayers { get; set; } = 15;
|
||||
|
||||
/// <inheritdoc />
|
||||
public GameKeywords Keywords { get; set; } = GameKeywords.English;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MapTypes Map { get; set; } = MapTypes.Skeld;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int NumImpostors { get; set; } = 1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsDefaults { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Player speed modifier.
|
||||
/// </summary>
|
||||
public float PlayerSpeedMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Light modifier for the players that are members of the crew as a multiplier value.
|
||||
/// </summary>
|
||||
public float CrewLightMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Light modifier for the players that are Impostors as a multiplier value.
|
||||
/// </summary>
|
||||
public float ImpostorLightMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of common tasks.
|
||||
/// </summary>
|
||||
public int NumCommonTasks { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of long tasks.
|
||||
/// </summary>
|
||||
public int NumLongTasks { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of short tasks.
|
||||
/// </summary>
|
||||
public int NumShortTasks { get; set; } = 2;
|
||||
|
||||
public int CrewmateVentUses { get; set; } = 1;
|
||||
|
||||
public float CrewmateTimeInVent { get; set; } = 3f;
|
||||
|
||||
public float HidingTime { get; set; } = 200f;
|
||||
|
||||
public float CrewmateFlashlightSize { get; set; } = 0.35f;
|
||||
|
||||
public float ImpostorFlashlightSize { get; set; } = 0.25f;
|
||||
|
||||
public bool UseFlashlight { get; set; } = true;
|
||||
|
||||
public bool FinalHideSeekMap { get; set; } = true;
|
||||
|
||||
public float FinalHideTime { get; set; } = 50f;
|
||||
|
||||
public float FinalSeekerSpeed { get; set; } = 1.2f;
|
||||
|
||||
public bool FinalHidePings { get; set; } = true;
|
||||
|
||||
public bool ShowNames { get; set; } = true;
|
||||
|
||||
public uint SeekerPlayerId { get; set; } = 0xFFFFFFFF;
|
||||
|
||||
public float MaxPingTime { get; set; } = 6f;
|
||||
|
||||
public static HideNSeekGameOptions Deserialize(IMessageReader reader, byte version)
|
||||
{
|
||||
var options = new HideNSeekGameOptions(version);
|
||||
options.Deserialize(reader);
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Deserialize(IMessageReader reader)
|
||||
{
|
||||
MaxPlayers = reader.ReadByte();
|
||||
Keywords = (GameKeywords)reader.ReadInt32();
|
||||
Map = (MapTypes)reader.ReadByte();
|
||||
PlayerSpeedMod = reader.ReadSingle();
|
||||
CrewLightMod = reader.ReadSingle();
|
||||
ImpostorLightMod = reader.ReadSingle();
|
||||
NumCommonTasks = reader.ReadByte();
|
||||
NumLongTasks = reader.ReadByte();
|
||||
NumShortTasks = reader.ReadByte();
|
||||
IsDefaults = reader.ReadBoolean();
|
||||
|
||||
CrewmateVentUses = reader.ReadInt32();
|
||||
HidingTime = reader.ReadSingle();
|
||||
CrewmateFlashlightSize = reader.ReadSingle();
|
||||
ImpostorFlashlightSize = reader.ReadSingle();
|
||||
UseFlashlight = reader.ReadBoolean();
|
||||
FinalHideSeekMap = reader.ReadBoolean();
|
||||
FinalHideTime = reader.ReadSingle();
|
||||
FinalSeekerSpeed = reader.ReadSingle();
|
||||
FinalHidePings = reader.ReadBoolean();
|
||||
ShowNames = reader.ReadBoolean();
|
||||
SeekerPlayerId = reader.ReadUInt32();
|
||||
MaxPingTime = reader.ReadSingle();
|
||||
CrewmateTimeInVent = reader.ReadSingle();
|
||||
|
||||
if (Version > 7)
|
||||
{
|
||||
IGameOptions.ThrowUnknownVersion<HideNSeekGameOptions>(Version);
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(MaxPlayers);
|
||||
writer.Write((uint)Keywords);
|
||||
writer.Write((byte)Map);
|
||||
writer.Write(PlayerSpeedMod);
|
||||
writer.Write(CrewLightMod);
|
||||
writer.Write(ImpostorLightMod);
|
||||
writer.Write((byte)NumCommonTasks);
|
||||
writer.Write((byte)NumLongTasks);
|
||||
writer.Write((byte)NumShortTasks);
|
||||
writer.Write(IsDefaults);
|
||||
|
||||
writer.Write(CrewmateVentUses);
|
||||
writer.Write(HidingTime);
|
||||
writer.Write(CrewmateFlashlightSize);
|
||||
writer.Write(ImpostorFlashlightSize);
|
||||
writer.Write(UseFlashlight);
|
||||
writer.Write(FinalHideSeekMap);
|
||||
writer.Write(FinalHideTime);
|
||||
writer.Write(FinalSeekerSpeed);
|
||||
writer.Write(FinalHidePings);
|
||||
writer.Write(ShowNames);
|
||||
writer.Write(SeekerPlayerId);
|
||||
writer.Write(MaxPingTime);
|
||||
writer.Write(CrewmateTimeInVent);
|
||||
|
||||
if (Version > 7)
|
||||
{
|
||||
IGameOptions.ThrowUnknownVersion<HideNSeekGameOptions>(Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Impostor.Api.Innersloth.GameOptions;
|
||||
|
||||
public interface IGameOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the version.
|
||||
/// </summary>
|
||||
public byte Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currently active gamemode.
|
||||
/// </summary>
|
||||
public GameModes GameMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum amount of players for this lobby.
|
||||
/// </summary>
|
||||
public byte MaxPlayers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the language of the lobby as per <see cref="GameKeywords" /> enum.
|
||||
/// </summary>
|
||||
public GameKeywords Keywords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Map selected for this lobby.
|
||||
/// </summary>
|
||||
public MapTypes Map { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of impostors for this lobby.
|
||||
/// </summary>
|
||||
public int NumImpostors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the GameOptions are the default ones.
|
||||
/// </summary>
|
||||
public bool IsDefaults { get; set; }
|
||||
|
||||
public void Serialize(IMessageWriter writer);
|
||||
|
||||
public static void EnsureVersionIsModular<TCaller>(byte version)
|
||||
{
|
||||
if (version < GameOptionsFactory.ModularOptionsDataVersion)
|
||||
{
|
||||
throw new ImpostorException($"{typeof(TCaller).Name} didn't exist before version 7, did you mean {nameof(LegacyGameOptionsData)}?");
|
||||
}
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
public static void ThrowUnknownVersion<TCaller>(byte version)
|
||||
{
|
||||
throw new ImpostorException($"Unknown {typeof(TCaller).Name} version {version}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
using Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
namespace Impostor.Api.Innersloth.GameOptions;
|
||||
|
||||
public class LegacyGameOptionsData : IGameOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The latest major version of the game client.
|
||||
/// </summary>
|
||||
public const int LatestVersion = 5;
|
||||
|
||||
public LegacyGameOptionsData(byte version = LatestVersion)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets host's version of the game.
|
||||
/// </summary>
|
||||
public byte Version { get; set; }
|
||||
|
||||
public GameModes GameMode => GameModes.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum amount of players for this lobby.
|
||||
/// </summary>
|
||||
public byte MaxPlayers { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the language of the lobby as per <see cref="GameKeywords" /> enum.
|
||||
/// </summary>
|
||||
public GameKeywords Keywords { get; set; } = GameKeywords.English;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Map selected for this lobby.
|
||||
/// </summary>
|
||||
public MapTypes Map { get; set; } = MapTypes.Skeld;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Player speed modifier.
|
||||
/// </summary>
|
||||
public float PlayerSpeedMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Light modifier for the players that are members of the crew as a multiplier value.
|
||||
/// </summary>
|
||||
public float CrewLightMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Light modifier for the players that are Impostors as a multiplier value.
|
||||
/// </summary>
|
||||
public float ImpostorLightMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Impostor cooldown to kill in seconds.
|
||||
/// </summary>
|
||||
public float KillCooldown { get; set; } = 15f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of common tasks.
|
||||
/// </summary>
|
||||
public int NumCommonTasks { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of long tasks.
|
||||
/// </summary>
|
||||
public int NumLongTasks { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of short tasks.
|
||||
/// </summary>
|
||||
public int NumShortTasks { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum amount of emergency meetings each player can call during the game in seconds.
|
||||
/// </summary>
|
||||
public int NumEmergencyMeetings { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cooldown between each time any player can call an emergency meeting in seconds.
|
||||
/// </summary>
|
||||
public int EmergencyCooldown { get; set; } = 15;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of impostors for this lobby.
|
||||
/// </summary>
|
||||
public int NumImpostors { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether ghosts (dead crew members) can do tasks.
|
||||
/// </summary>
|
||||
public bool GhostsDoTasks { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Kill as per values in <see cref="KillDistances" />.
|
||||
/// </summary>
|
||||
public KillDistances KillDistance { get; set; } = KillDistances.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time for discussion before voting time in seconds.
|
||||
/// </summary>
|
||||
public int DiscussionTime { get; set; } = 15;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time for voting in seconds.
|
||||
/// </summary>
|
||||
public int VotingTime { get; set; } = 120;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether an ejected player is an impostor or not.
|
||||
/// </summary>
|
||||
public bool ConfirmImpostor { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether players are able to see tasks being performed by other players.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By being set to true, tasks such as Empty Garbage, Submit Scan, Clear asteroids, Prime shields execution will be visible to other players.
|
||||
/// </remarks>
|
||||
public bool VisualTasks { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the vote is anonymous.
|
||||
/// </summary>
|
||||
public bool AnonymousVotes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the task bar update mode as per values in <see cref="Innersloth.TaskBarUpdate" />.
|
||||
/// </summary>
|
||||
public TaskBarUpdate TaskBarUpdate { get; set; } = TaskBarUpdate.Always;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets role options.
|
||||
/// </summary>
|
||||
public LegacyRoleOptionsData RoleOptions { get; set; } = new LegacyRoleOptionsData();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the GameOptions are the default ones.
|
||||
/// </summary>
|
||||
public bool IsDefaults { get; set; } = true;
|
||||
|
||||
public static LegacyGameOptionsData Deserialize(IMessageReader reader, byte version)
|
||||
{
|
||||
var options = new LegacyGameOptionsData(version);
|
||||
options.Deserialize(reader);
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Deserialize(IMessageReader reader)
|
||||
{
|
||||
Version = reader.ReadByte();
|
||||
MaxPlayers = reader.ReadByte();
|
||||
Keywords = (GameKeywords)reader.ReadUInt32();
|
||||
Map = (MapTypes)reader.ReadByte();
|
||||
PlayerSpeedMod = reader.ReadSingle();
|
||||
|
||||
CrewLightMod = reader.ReadSingle();
|
||||
ImpostorLightMod = reader.ReadSingle();
|
||||
KillCooldown = reader.ReadSingle();
|
||||
|
||||
NumCommonTasks = reader.ReadByte();
|
||||
NumLongTasks = reader.ReadByte();
|
||||
NumShortTasks = reader.ReadByte();
|
||||
|
||||
NumEmergencyMeetings = reader.ReadInt32();
|
||||
|
||||
NumImpostors = reader.ReadByte();
|
||||
KillDistance = (KillDistances)reader.ReadByte();
|
||||
DiscussionTime = reader.ReadInt32();
|
||||
VotingTime = reader.ReadInt32();
|
||||
|
||||
IsDefaults = reader.ReadBoolean();
|
||||
|
||||
if (Version >= 2)
|
||||
{
|
||||
EmergencyCooldown = reader.ReadByte();
|
||||
}
|
||||
|
||||
if (Version >= 3)
|
||||
{
|
||||
ConfirmImpostor = reader.ReadBoolean();
|
||||
VisualTasks = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (Version >= 4)
|
||||
{
|
||||
AnonymousVotes = reader.ReadBoolean();
|
||||
TaskBarUpdate = (TaskBarUpdate)reader.ReadByte();
|
||||
}
|
||||
|
||||
if (Version >= 5)
|
||||
{
|
||||
RoleOptions = LegacyRoleOptionsData.Deserialize(reader);
|
||||
}
|
||||
|
||||
if (Version >= 6)
|
||||
{
|
||||
// Nothing was changed in V6
|
||||
}
|
||||
|
||||
if (Version > 6)
|
||||
{
|
||||
IGameOptions.ThrowUnknownVersion<LegacyGameOptionsData>(Version);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes this instance of GameOptionsData object to a specified BinaryWriter.
|
||||
/// </summary>
|
||||
/// <param name="writer">The stream to write the message to.</param>
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write((byte)Version);
|
||||
writer.Write((byte)MaxPlayers);
|
||||
writer.Write((uint)Keywords);
|
||||
writer.Write((byte)Map);
|
||||
writer.Write((float)PlayerSpeedMod);
|
||||
writer.Write((float)CrewLightMod);
|
||||
writer.Write((float)ImpostorLightMod);
|
||||
writer.Write((float)KillCooldown);
|
||||
writer.Write((byte)NumCommonTasks);
|
||||
writer.Write((byte)NumLongTasks);
|
||||
writer.Write((byte)NumShortTasks);
|
||||
writer.Write((int)NumEmergencyMeetings);
|
||||
writer.Write((byte)NumImpostors);
|
||||
writer.Write((byte)KillDistance);
|
||||
writer.Write((uint)DiscussionTime);
|
||||
writer.Write((uint)VotingTime);
|
||||
writer.Write((bool)IsDefaults);
|
||||
|
||||
if (Version >= 2)
|
||||
{
|
||||
writer.Write((byte)EmergencyCooldown);
|
||||
}
|
||||
|
||||
if (Version >= 3)
|
||||
{
|
||||
writer.Write((bool)ConfirmImpostor);
|
||||
writer.Write((bool)VisualTasks);
|
||||
}
|
||||
|
||||
if (Version >= 4)
|
||||
{
|
||||
writer.Write((bool)AnonymousVotes);
|
||||
writer.Write((byte)TaskBarUpdate);
|
||||
}
|
||||
|
||||
if (Version >= 5)
|
||||
{
|
||||
RoleOptions.Serialize(writer);
|
||||
}
|
||||
|
||||
if (Version >= 6)
|
||||
{
|
||||
// Nothing was changed in V6
|
||||
}
|
||||
|
||||
if (Version > 6)
|
||||
{
|
||||
throw new ImpostorException($"Unknown {nameof(LegacyGameOptionsData)} version {Version}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
using Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
namespace Impostor.Api.Innersloth.GameOptions;
|
||||
|
||||
public class NormalGameOptions : IGameOptions
|
||||
{
|
||||
public const int LatestVersion = 7;
|
||||
|
||||
public NormalGameOptions(byte version = LatestVersion)
|
||||
{
|
||||
Version = version;
|
||||
IGameOptions.EnsureVersionIsModular<NormalGameOptions>(version);
|
||||
RoleOptions = new RoleOptionsCollection(version);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte Version { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public GameModes GameMode => GameModes.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte MaxPlayers { get; set; } = 10;
|
||||
|
||||
/// <inheritdoc />
|
||||
public GameKeywords Keywords { get; set; } = GameKeywords.English;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MapTypes Map { get; set; } = MapTypes.Skeld;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int NumImpostors { get; set; } = 1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsDefaults { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Player speed modifier.
|
||||
/// </summary>
|
||||
public float PlayerSpeedMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Light modifier for the players that are members of the crew as a multiplier value.
|
||||
/// </summary>
|
||||
public float CrewLightMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Light modifier for the players that are Impostors as a multiplier value.
|
||||
/// </summary>
|
||||
public float ImpostorLightMod { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Impostor cooldown to kill in seconds.
|
||||
/// </summary>
|
||||
public float KillCooldown { get; set; } = 15f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of common tasks.
|
||||
/// </summary>
|
||||
public int NumCommonTasks { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of long tasks.
|
||||
/// </summary>
|
||||
public int NumLongTasks { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of short tasks.
|
||||
/// </summary>
|
||||
public int NumShortTasks { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum amount of emergency meetings each player can call during the game in seconds.
|
||||
/// </summary>
|
||||
public int NumEmergencyMeetings { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cooldown between each time any player can call an emergency meeting in seconds.
|
||||
/// </summary>
|
||||
public int EmergencyCooldown { get; set; } = 15;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether ghosts (dead crew members) can do tasks.
|
||||
/// </summary>
|
||||
public bool GhostsDoTasks { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Kill as per values in <see cref="KillDistances" />.
|
||||
/// </summary>
|
||||
public KillDistances KillDistance { get; set; } = KillDistances.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time for discussion before voting time in seconds.
|
||||
/// </summary>
|
||||
public int DiscussionTime { get; set; } = 15;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time for voting in seconds.
|
||||
/// </summary>
|
||||
public int VotingTime { get; set; } = 120;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether an ejected player is an impostor or not.
|
||||
/// </summary>
|
||||
public bool ConfirmImpostor { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether players are able to see tasks being performed by other players.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By being set to true, tasks such as Empty Garbage, Submit Scan, Clear asteroids, Prime shields execution will be visible to other players.
|
||||
/// </remarks>
|
||||
public bool VisualTasks { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the vote is anonymous.
|
||||
/// </summary>
|
||||
public bool AnonymousVotes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the task bar update mode as per values in <see cref="Innersloth.TaskBarUpdate" />.
|
||||
/// </summary>
|
||||
public TaskBarUpdate TaskBarUpdate { get; set; } = TaskBarUpdate.Always;
|
||||
|
||||
public RoleOptionsCollection RoleOptions { get; set; }
|
||||
|
||||
public static NormalGameOptions Deserialize(IMessageReader reader, byte version)
|
||||
{
|
||||
var options = new NormalGameOptions(version);
|
||||
options.Deserialize(reader);
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Deserialize(IMessageReader reader)
|
||||
{
|
||||
MaxPlayers = reader.ReadByte();
|
||||
Keywords = (GameKeywords)reader.ReadUInt32();
|
||||
Map = (MapTypes)reader.ReadByte();
|
||||
PlayerSpeedMod = reader.ReadSingle();
|
||||
|
||||
CrewLightMod = reader.ReadSingle();
|
||||
ImpostorLightMod = reader.ReadSingle();
|
||||
KillCooldown = reader.ReadSingle();
|
||||
|
||||
NumCommonTasks = reader.ReadByte();
|
||||
NumLongTasks = reader.ReadByte();
|
||||
NumShortTasks = reader.ReadByte();
|
||||
|
||||
NumEmergencyMeetings = reader.ReadInt32();
|
||||
|
||||
NumImpostors = reader.ReadByte();
|
||||
KillDistance = (KillDistances)reader.ReadByte();
|
||||
DiscussionTime = reader.ReadInt32();
|
||||
VotingTime = reader.ReadInt32();
|
||||
|
||||
IsDefaults = reader.ReadBoolean();
|
||||
|
||||
EmergencyCooldown = reader.ReadByte();
|
||||
ConfirmImpostor = reader.ReadBoolean();
|
||||
VisualTasks = reader.ReadBoolean();
|
||||
AnonymousVotes = reader.ReadBoolean();
|
||||
TaskBarUpdate = (TaskBarUpdate)reader.ReadByte();
|
||||
|
||||
RoleOptions.Deserialize(reader);
|
||||
|
||||
if (Version > 7)
|
||||
{
|
||||
IGameOptions.ThrowUnknownVersion<NormalGameOptions>(Version);
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(MaxPlayers);
|
||||
writer.Write((uint)Keywords);
|
||||
writer.Write((byte)Map);
|
||||
writer.Write(PlayerSpeedMod);
|
||||
|
||||
writer.Write(CrewLightMod);
|
||||
writer.Write(ImpostorLightMod);
|
||||
writer.Write(KillCooldown);
|
||||
|
||||
writer.Write((byte)NumCommonTasks);
|
||||
writer.Write((byte)NumLongTasks);
|
||||
writer.Write((byte)NumShortTasks);
|
||||
|
||||
writer.Write(NumEmergencyMeetings);
|
||||
|
||||
writer.Write((byte)NumImpostors);
|
||||
writer.Write((byte)KillDistance);
|
||||
writer.Write(DiscussionTime);
|
||||
writer.Write(VotingTime);
|
||||
|
||||
writer.Write(IsDefaults);
|
||||
|
||||
writer.Write((byte)EmergencyCooldown);
|
||||
writer.Write(ConfirmImpostor);
|
||||
writer.Write(VisualTasks);
|
||||
writer.Write(AnonymousVotes);
|
||||
writer.Write((byte)TaskBarUpdate);
|
||||
|
||||
RoleOptions.Serialize(writer);
|
||||
|
||||
if (Version > 7)
|
||||
{
|
||||
IGameOptions.ThrowUnknownVersion<NormalGameOptions>(Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public class EngineerRoleOptions : IRoleOptions
|
||||
{
|
||||
public EngineerRoleOptions(byte version)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public byte Version { get; }
|
||||
|
||||
public RoleTypes Type => RoleTypes.Engineer;
|
||||
|
||||
public byte Cooldown { get; set; } = 30;
|
||||
|
||||
public byte InVentMaxTime { get; set; } = 15;
|
||||
|
||||
public static EngineerRoleOptions Deserialize(IMessageReader reader, byte version)
|
||||
{
|
||||
var options = new EngineerRoleOptions(version);
|
||||
|
||||
options.Cooldown = reader.ReadByte();
|
||||
options.InVentMaxTime = reader.ReadByte();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(Cooldown);
|
||||
writer.Write(InVentMaxTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public class GuardianAngelRoleOptions : IRoleOptions
|
||||
{
|
||||
public GuardianAngelRoleOptions(byte version)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public byte Version { get; }
|
||||
|
||||
public RoleTypes Type => RoleTypes.GuardianAngel;
|
||||
|
||||
public byte Cooldown { get; set; } = 60;
|
||||
|
||||
public byte ProtectionDurationSeconds { get; set; } = 10;
|
||||
|
||||
public bool ImpostorsCanSeeProtect { get; set; }
|
||||
|
||||
public static GuardianAngelRoleOptions Deserialize(IMessageReader reader, byte version)
|
||||
{
|
||||
var options = new GuardianAngelRoleOptions(version);
|
||||
|
||||
options.Cooldown = reader.ReadByte();
|
||||
options.ProtectionDurationSeconds = reader.ReadByte();
|
||||
options.ImpostorsCanSeeProtect = reader.ReadBoolean();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(Cooldown);
|
||||
writer.Write(ProtectionDurationSeconds);
|
||||
writer.Write(ImpostorsCanSeeProtect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public interface IRoleOptions
|
||||
{
|
||||
RoleTypes Type { get; }
|
||||
|
||||
void Serialize(IMessageWriter writer);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public class LegacyRoleOptionsData
|
||||
{
|
||||
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 LegacyRoleOptionsData Deserialize(IMessageReader reader)
|
||||
{
|
||||
var roleOptionsData = new LegacyRoleOptionsData();
|
||||
var num = reader.ReadPackedInt32();
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
var key = (RoleTypes)reader.ReadInt16();
|
||||
var roleRate = RoleRate.Deserialize(reader);
|
||||
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);
|
||||
roleRate.Value.Serialize(writer);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public class RoleOptionsCollection
|
||||
{
|
||||
public RoleOptionsCollection(byte version)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public byte Version { get; }
|
||||
|
||||
public Dictionary<RoleTypes, RoleData> Roles { get; } = new Dictionary<RoleTypes, RoleData>();
|
||||
|
||||
public void Deserialize(IMessageReader reader)
|
||||
{
|
||||
Roles.Clear();
|
||||
|
||||
var count = reader.ReadPackedInt32();
|
||||
Roles.EnsureCapacity(count);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var roleType = (RoleTypes)reader.ReadInt16();
|
||||
var roleRate = RoleRate.Deserialize(reader);
|
||||
var roleOptionsReader = reader.ReadMessage();
|
||||
IRoleOptions roleOptions = roleType switch
|
||||
{
|
||||
RoleTypes.Scientist => ScientistRoleOptions.Deserialize(roleOptionsReader, Version),
|
||||
RoleTypes.Engineer => EngineerRoleOptions.Deserialize(roleOptionsReader, Version),
|
||||
RoleTypes.GuardianAngel => GuardianAngelRoleOptions.Deserialize(roleOptionsReader, Version),
|
||||
RoleTypes.Shapeshifter => ShapeshifterRoleOptions.Deserialize(roleOptionsReader, Version),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(roleType), roleType, null),
|
||||
};
|
||||
|
||||
Roles.Add(roleType, new RoleData(roleType, roleOptions, roleRate));
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.WritePacked(Roles.Count);
|
||||
foreach (var (key, roleData) in Roles)
|
||||
{
|
||||
writer.Write((ushort)key);
|
||||
roleData.Rate.Serialize(writer);
|
||||
writer.StartMessage(0);
|
||||
roleData.RoleOptions.Serialize(writer);
|
||||
writer.EndMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public readonly record struct RoleData(RoleTypes Type, IRoleOptions RoleOptions, RoleRate Rate);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public readonly record struct RoleRate(byte MaxCount, byte Chance)
|
||||
{
|
||||
public static RoleRate Deserialize(IMessageReader reader)
|
||||
{
|
||||
return new RoleRate(reader.ReadByte(), reader.ReadByte());
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(MaxCount);
|
||||
writer.Write(Chance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace Impostor.Api.Innersloth.GameOptions.RoleOptions;
|
||||
|
||||
public class ScientistRoleOptions : IRoleOptions
|
||||
{
|
||||
public ScientistRoleOptions(byte version)
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public byte Version { get; }
|
||||
|
||||
public RoleTypes Type => RoleTypes.Scientist;
|
||||
|
||||
public byte Cooldown { get; set; } = 15;
|
||||
|
||||
public byte BatteryCharge { get; set; } = 5;
|
||||
|
||||
public static ScientistRoleOptions Deserialize(IMessageReader reader, byte version)
|
||||
{
|
||||
var options = new ScientistRoleOptions(version);
|
||||
|
||||
options.Cooldown = reader.ReadByte();
|
||||
options.BatteryCharge = reader.ReadByte();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.Write(Cooldown);
|
||||
writer.Write(BatteryCharge);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 493 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user