mirror of
https://github.com/Impostor/Impostor.git
synced 2026-10-20 01:46:11 +00:00
Sync Impostor with 6pak fork (#327)
Co-authored-by: DatGuy1 <datguysteam@gmail.com> Co-authored-by: miniduikboot <5243971+miniduikboot@users.noreply.github.com>
This commit is contained in:
123 files changed
+2472
-1405
No files matched your search
@@ -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
|
||||
+2
-3
@@ -1,12 +1,11 @@
|
||||
version: '{build}'
|
||||
|
||||
environment:
|
||||
IMPOSTOR_VERSION: '1.2.2'
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
|
||||
branches:
|
||||
except:
|
||||
- gh-pages
|
||||
- gh-pages
|
||||
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
@@ -17,7 +16,7 @@ assembly_info:
|
||||
dotnet_csproj:
|
||||
patch: false
|
||||
|
||||
image: Visual Studio 2019 Preview
|
||||
image: Ubuntu2004
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
|
||||
+32
-58
@@ -2,19 +2,19 @@
|
||||
#addin "nuget:?package=Cake.Compression&Version=0.2.4"
|
||||
#addin "nuget:?package=Cake.FileHelpers&Version=3.3.0"
|
||||
|
||||
|
||||
var buildId = EnvironmentVariable("APPVEYOR_BUILD_VERSION") ?? "0";
|
||||
var buildVersion = EnvironmentVariable("IMPOSTOR_VERSION") ?? "1.0.0";
|
||||
var buildBranch = EnvironmentVariable("APPVEYOR_REPO_BRANCH") ?? "dev";
|
||||
var buildId = EnvironmentVariable("GITHUB_RUN_NUMBER") ?? EnvironmentVariable("APPVEYOR_BUILD_VERSION");
|
||||
var buildRelease = EnvironmentVariable("APPVEYOR_REPO_TAG") == "true";
|
||||
var buildVersion = FindRegexMatchGroupInFile("./src/Directory.Build.props", @"\<VersionPrefix\>(.*?)\<\/VersionPrefix\>", 1, System.Text.RegularExpressions.RegexOptions.None).Value;
|
||||
var buildDir = MakeAbsolute(Directory("./build"));
|
||||
|
||||
var prNumber = EnvironmentVariable("APPVEYOR_PULL_REQUEST_NUMBER");
|
||||
var target = Argument("target", "Deploy");
|
||||
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 DotNetCoreMSBuildSettings();
|
||||
|
||||
if (!buildRelease && buildId != null) {
|
||||
msbuildSettings.Properties["VersionSuffix"] = new[] { "ci." + buildId };
|
||||
buildVersion += "-ci." + buildId;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -34,7 +34,8 @@ private void ImpostorPublish(string name, string project, string runtime, bool i
|
||||
SelfContained = false,
|
||||
PublishSingleFile = true,
|
||||
PublishTrimmed = false,
|
||||
OutputDirectory = projBuildDir
|
||||
OutputDirectory = projBuildDir,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
|
||||
if (isServer) {
|
||||
@@ -46,11 +47,7 @@ private void ImpostorPublish(string name, string project, string runtime, bool i
|
||||
}
|
||||
}
|
||||
|
||||
if (runtime == "win-x64") {
|
||||
Zip(projBuildDir, buildDir.CombineWithFilePath(projBuildName + ".zip"));
|
||||
} else {
|
||||
GZipCompress(projBuildDir, buildDir.CombineWithFilePath(projBuildName + ".tar.gz"));
|
||||
}
|
||||
Zip(projBuildDir, buildDir.CombineWithFilePath(projBuildName + ".zip"));
|
||||
}
|
||||
|
||||
private void ImpostorPublishNF(string name, string project) {
|
||||
@@ -62,7 +59,8 @@ private void ImpostorPublishNF(string name, string project) {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net472",
|
||||
OutputDirectory = projBuildDir
|
||||
OutputDirectory = projBuildDir,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
|
||||
Zip(projBuildDir, projBuildZip);
|
||||
@@ -86,13 +84,6 @@ Task("Restore")
|
||||
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>");
|
||||
});
|
||||
|
||||
Task("Replay")
|
||||
.Does(() => {
|
||||
// D:\Projects\GitHub\Impostor\Impostor\src\Impostor.Tools.ServerReplay\sessions
|
||||
@@ -107,7 +98,6 @@ Task("Replay")
|
||||
|
||||
Task("Build")
|
||||
.IsDependentOn("Clean")
|
||||
.IsDependentOn("Patch")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("Replay")
|
||||
.Does(() => {
|
||||
@@ -116,44 +106,28 @@ Task("Build")
|
||||
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");
|
||||
// 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");
|
||||
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"
|
||||
});
|
||||
|
||||
DotNetCoreBuild("./src/Impostor.Server/Impostor.Server.csproj", new DotNetCoreBuildSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
Framework = "net5.0"
|
||||
});
|
||||
}
|
||||
// API.
|
||||
DotNetCorePack("./src/Impostor.Api/Impostor.Api.csproj", new DotNetCorePackSettings {
|
||||
Configuration = configuration,
|
||||
OutputDirectory = buildDir,
|
||||
IncludeSource = true,
|
||||
IncludeSymbols = true,
|
||||
MSBuildSettings = msbuildSettings
|
||||
});
|
||||
});
|
||||
|
||||
Task("Test")
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
-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,7 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.2.2</VersionPrefix>
|
||||
<VersionSuffix>dev</VersionSuffix>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using Impostor.Server.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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Events.Announcements
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired after client requests a announcement.
|
||||
/// </summary>
|
||||
public interface IAnnouncementRequestEvent : IEvent
|
||||
{
|
||||
public interface IResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets FreeWeekendState, currently unused by the client.
|
||||
/// </summary>
|
||||
public FreeWeekendState FreeWeekendState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether announcement should be loaded from client's cache, can save some bytes.
|
||||
/// </summary>
|
||||
public bool UseCached { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets announcement, should be null when <see cref="UseCached"/> is set to true.
|
||||
/// </summary>
|
||||
public Announcement? Announcement { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets client's last announcement id.
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets client's language.
|
||||
/// </summary>
|
||||
public Language Language { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets plugin made response.
|
||||
/// </summary>
|
||||
public IResponse Response { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Impostor.Api.Events.Player
|
||||
{
|
||||
public interface IPlayerMovementEvent : IPlayerEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using System.Threading.Tasks;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Inner;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Games
|
||||
@@ -35,6 +34,9 @@ namespace Impostor.Api.Games
|
||||
|
||||
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"/>.
|
||||
@@ -53,13 +55,6 @@ namespace Impostor.Api.Games
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
ValueTask SyncSettingsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified list as Impostor on all connected players.
|
||||
/// </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);
|
||||
|
||||
/// <summary>
|
||||
/// Send the message to all players.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<CodeAnalysisRuleSet>ProjectRules.ruleset</CodeAnalysisRuleSet>
|
||||
<LangVersion>9</LangVersion>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>1.0.0</Version>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<AssemblyName>Impostor.Api</AssemblyName>
|
||||
@@ -22,7 +21,6 @@
|
||||
</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">
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public readonly struct Announcement
|
||||
{
|
||||
public readonly int Id;
|
||||
public readonly string Message;
|
||||
|
||||
public Announcement(int id, string message)
|
||||
{
|
||||
Id = id;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum HatType
|
||||
public enum HatType : uint
|
||||
{
|
||||
NoHat = 0,
|
||||
Astronaut = 1,
|
||||
@@ -45,8 +45,8 @@
|
||||
ThirdEyeHat = 40,
|
||||
ToiletPaperHat = 41,
|
||||
Toppat = 42,
|
||||
Fedora = 43,
|
||||
Goggles2 = 44,
|
||||
BlackFedora = 43,
|
||||
SkiGoggles = 44,
|
||||
Headphones = 45,
|
||||
MaskHat = 46,
|
||||
PaperMask = 47,
|
||||
@@ -58,7 +58,7 @@
|
||||
Cheese = 53,
|
||||
Cherry = 54,
|
||||
Egg = 55,
|
||||
Fedora2 = 56,
|
||||
GreenFedora = 56,
|
||||
Flamingo = 57,
|
||||
FlowerPin = 58,
|
||||
Helmet = 59,
|
||||
@@ -95,6 +95,7 @@
|
||||
MiniCrewmate = 90,
|
||||
NinjaMask = 91,
|
||||
RamHorns = 92,
|
||||
Snowman2 = 93,
|
||||
SnowCrewmate = 93,
|
||||
GeoffHat = 94,
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum PetType
|
||||
public enum PetType : uint
|
||||
{
|
||||
NoPet = 0,
|
||||
Alien = 1,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Impostor.Api.Innersloth.Customization
|
||||
{
|
||||
public enum SkinType : byte
|
||||
public enum SkinType : uint
|
||||
{
|
||||
None = 0,
|
||||
Astro = 1,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
[Flags]
|
||||
public enum FreeWeekendState : byte
|
||||
{
|
||||
NotFree,
|
||||
FreeMIRA,
|
||||
FreePolus,
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ namespace Impostor.Api.Innersloth
|
||||
/// </summary>
|
||||
/// <param name="writer">The stream to write the message to.</param>
|
||||
/// <param name="version">The version of the game.</param>
|
||||
public void Serialize(BinaryWriter writer, byte version)
|
||||
public void Serialize(BinaryWriter writer, byte version = LatestVersion)
|
||||
{
|
||||
writer.Write((byte)version);
|
||||
writer.Write((byte)MaxPlayers);
|
||||
@@ -204,6 +204,14 @@ namespace Impostor.Api.Innersloth
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(IMessageWriter writer)
|
||||
{
|
||||
using var memory = new MemoryStream();
|
||||
using var writerBin = new BinaryWriter(memory);
|
||||
Serialize(writerBin);
|
||||
writer.WriteBytesAndSize(memory.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize a ReadOnlyMemory object to this instance of the GameOptionsData object.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public enum Language
|
||||
{
|
||||
English,
|
||||
Spanish,
|
||||
Portuguese,
|
||||
Korean,
|
||||
Russian,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Impostor.Api.Innersloth
|
||||
{
|
||||
public class MapSpawn
|
||||
{
|
||||
private MapSpawn(float spawnRadius, Vector2 initialSpawnCenter, Vector2 meetingSpawnCenter)
|
||||
{
|
||||
SpawnRadius = spawnRadius;
|
||||
InitialSpawnCenter = initialSpawnCenter;
|
||||
MeetingSpawnCenter = meetingSpawnCenter;
|
||||
}
|
||||
|
||||
public static Dictionary<MapTypes, MapSpawn> Maps { get; } = new Dictionary<MapTypes, MapSpawn>
|
||||
{
|
||||
[MapTypes.Skeld] = new MapSpawn(1.6f, new Vector2(-0.72f, 0.62f), new Vector2(-0.72f, 0.62f)),
|
||||
[MapTypes.MiraHQ] = new MapSpawn(1.55f, new Vector2(-4.4f, 2.2f), new Vector2(24.043f, 1.72f)),
|
||||
[MapTypes.Polus] = new MapSpawn(1f, new Vector2(16.64f, -2.46f), new Vector2(17.726f, -16.286f)),
|
||||
};
|
||||
|
||||
public float SpawnRadius { get; }
|
||||
|
||||
public Vector2 InitialSpawnCenter { get; }
|
||||
|
||||
public Vector2 MeetingSpawnCenter { get; }
|
||||
|
||||
public Vector2 GetSpawnLocation(int playerId, int numPlayer, bool initialSpawn)
|
||||
{
|
||||
var vector = new Vector2(0, 1);
|
||||
vector = Rotate(vector, (playerId - 1) * (360f / numPlayer));
|
||||
vector *= this.SpawnRadius;
|
||||
return (initialSpawn ? this.InitialSpawnCenter : this.MeetingSpawnCenter) + vector + new Vector2(0f, 0.3636f);
|
||||
}
|
||||
|
||||
private static Vector2 Rotate(Vector2 self, float degrees)
|
||||
{
|
||||
var f = 0.017453292f * degrees;
|
||||
var num = (float)Math.Cos(f);
|
||||
var num2 = (float)Math.Sin(f);
|
||||
return new Vector2((self.X * num) - (num2 * self.Y), (self.X * num2) + (num * self.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Reactor;
|
||||
|
||||
namespace Impostor.Api.Net
|
||||
{
|
||||
@@ -27,6 +28,11 @@ namespace Impostor.Api.Net
|
||||
/// </remarks>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets mods sent by client in modded handshake.
|
||||
/// </summary>
|
||||
ISet<Mod> Mods { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connection of the client.
|
||||
/// </summary>
|
||||
@@ -55,6 +61,8 @@ namespace Impostor.Api.Net
|
||||
/// </summary>
|
||||
IClientPlayer? Player { get; }
|
||||
|
||||
ValueTask<bool> ReportCheatAsync(CheatContext context, string message);
|
||||
|
||||
ValueTask HandleMessageAsync(IMessageReader message, MessageType messageType);
|
||||
|
||||
ValueTask HandleDisconnectAsync(string reason);
|
||||
|
||||
@@ -5,6 +5,16 @@ namespace Impostor.Api.Net.Inner.Objects.Components
|
||||
{
|
||||
public interface IInnerCustomNetworkTransform : IInnerNetObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets position where the object thinks it is (not interpolated).
|
||||
/// </summary>
|
||||
Vector2 Position { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets current object's velocity.
|
||||
/// </summary>
|
||||
Vector2 Velocity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Snaps the current to the given position <see cref="IInnerPlayerControl"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -41,48 +41,32 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
/// Sets the color of the current <see cref="IInnerPlayerControl"/>.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="colorId">A color for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetColorAsync(byte colorId);
|
||||
|
||||
/// <param name="colorType">A color for the player.</param>
|
||||
/// <inheritdoc cref="SetColorAsync(byte)" />
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetColorAsync(ColorType colorType);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the hat of the current <see cref="IInnerPlayerControl"/>.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="hatId">An hat for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetHatAsync(uint hatId);
|
||||
|
||||
/// <param name="hatType">An hat for the player.</param>
|
||||
/// <inheritdoc cref="SetHatAsync(uint)" />
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetHatAsync(HatType hatType);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pet of the current <see cref="IInnerPlayerControl"/>.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="petId">A pet for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetPetAsync(uint petId);
|
||||
|
||||
/// <param name="petType">A pet for the player.</param>
|
||||
/// <inheritdoc cref="SetPetAsync(uint)" />
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetPetAsync(PetType petType);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the skin of the current <see cref="IInnerPlayerControl"/>.
|
||||
/// Visible to all players.
|
||||
/// </summary>
|
||||
/// <param name="skinId">A skin for the player.</param>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetSkinAsync(uint skinId);
|
||||
|
||||
/// <param name="skinType">A skin for the player.</param>
|
||||
/// <inheritdoc cref="SetSkinAsync(uint)" />
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetSkinAsync(SkinType skinType);
|
||||
|
||||
/// <summary>
|
||||
@@ -106,11 +90,13 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
ValueTask SendChatToPlayerAsync(string text, IInnerPlayerControl? player = null);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current to be murdered by an impostor <see cref="IInnerPlayerControl"/>.
|
||||
/// Visible to all players.
|
||||
/// Murder <paramref name="target"/> player.
|
||||
/// </summary>
|
||||
/// /// <param name="impostor">The Impostor who kill.</param>
|
||||
/// <param name="target">Target player to murder.</param>
|
||||
/// <exception cref="ImpostorProtocolException">Thrown when player is not the impostor.</exception>
|
||||
/// <exception cref="ImpostorProtocolException">Thrown when player is dead.</exception>
|
||||
/// <exception cref="ImpostorProtocolException">Thrown when target is dead.</exception>
|
||||
/// <returns>Task that must be awaited.</returns>
|
||||
ValueTask SetMurderedByAsync(IClientPlayer impostor);
|
||||
ValueTask MurderPlayerAsync(IInnerPlayerControl target);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Inner.Objects
|
||||
{
|
||||
@@ -14,22 +15,22 @@ namespace Impostor.Api.Net.Inner.Objects
|
||||
/// <summary>
|
||||
/// Gets the color of the player.
|
||||
/// </summary>
|
||||
byte ColorId { get; }
|
||||
ColorType Color { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hat of the player.
|
||||
/// </summary>
|
||||
uint HatId { get; }
|
||||
HatType Hat { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pet of the player.
|
||||
/// </summary>
|
||||
uint PetId { get; }
|
||||
PetType Pet { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the skin of the player.
|
||||
/// </summary>
|
||||
uint SkinId { get; }
|
||||
SkinType Skin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the player is an impostor.
|
||||
|
||||
@@ -33,5 +33,6 @@
|
||||
RepairSystem = 28,
|
||||
SetTasks = 29,
|
||||
UpdateGameData = 30,
|
||||
CustomRpc = byte.MaxValue
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public static class Message00UseCache
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
writer.StartMessage(AnnouncementsMessageFlags.UseCache);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public static class Message01Update
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, int id, string message)
|
||||
{
|
||||
writer.StartMessage(AnnouncementsMessageFlags.SetUpdate);
|
||||
writer.WritePacked(id);
|
||||
writer.Write(message);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out int id, out string message)
|
||||
{
|
||||
id = reader.ReadPackedInt32();
|
||||
message = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public static class Message02SetFreeWeekend
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, FreeWeekendState state)
|
||||
{
|
||||
writer.StartMessage(AnnouncementsMessageFlags.SetFreeWeekend);
|
||||
writer.Write((byte)state);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out FreeWeekendState state)
|
||||
{
|
||||
state = (FreeWeekendState)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Announcements
|
||||
{
|
||||
public class MessageHello
|
||||
{
|
||||
public static void Deserialize(IMessageReader reader, out int announcementVersion, out int id, out Language language)
|
||||
{
|
||||
reader.ReadByte(); // SendOption header, probably added by accident
|
||||
announcementVersion = reader.ReadPackedInt32();
|
||||
id = reader.ReadPackedInt32();
|
||||
language = (Language)reader.ReadPackedInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Impostor.Api.Net.Messages
|
||||
{
|
||||
public class AnnouncementsMessageFlags
|
||||
{
|
||||
public const byte UseCache = 0;
|
||||
public const byte SetUpdate = 1;
|
||||
public const byte SetFreeWeekend = 2;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.C2S
|
||||
{
|
||||
@@ -8,14 +7,7 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
public static void Serialize(IMessageWriter writer, GameOptionsData gameOptionsData)
|
||||
{
|
||||
writer.StartMessage(MessageFlags.HostGame);
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
using (var writerBin = new BinaryWriter(memory))
|
||||
{
|
||||
gameOptionsData.Serialize(writerBin, GameOptionsData.LatestVersion);
|
||||
writer.WriteBytesAndSize(memory.ToArray());
|
||||
}
|
||||
|
||||
gameOptionsData.Serialize(writer);
|
||||
writer.EndMessage();
|
||||
}
|
||||
|
||||
@@ -24,4 +16,4 @@ namespace Impostor.Api.Net.Messages.C2S
|
||||
return GameOptionsData.DeserializeCreate(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner;
|
||||
|
||||
namespace Impostor.Api.Net.Messages
|
||||
{
|
||||
@@ -47,6 +50,8 @@ namespace Impostor.Api.Net.Messages
|
||||
|
||||
float ReadSingle();
|
||||
|
||||
string ReadString(int length);
|
||||
|
||||
string ReadString();
|
||||
|
||||
ReadOnlyMemory<byte> ReadBytesAndSize();
|
||||
@@ -64,5 +69,10 @@ namespace Impostor.Api.Net.Messages
|
||||
void RemoveMessage(IMessageReader message);
|
||||
|
||||
IMessageReader Copy(int offset = 0);
|
||||
|
||||
T? ReadNetObject<T>(IGame game)
|
||||
where T : IInnerNetObject;
|
||||
|
||||
Vector2 ReadVector2();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Numerics;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner;
|
||||
|
||||
namespace Impostor.Api.Net.Messages
|
||||
{
|
||||
@@ -107,6 +109,10 @@ namespace Impostor.Api.Net.Messages
|
||||
|
||||
void WriteBytesAndSize(byte[] bytes, int offset, int length);
|
||||
|
||||
void Write(IInnerNetObject innerNetObject);
|
||||
|
||||
void Write(Vector2 vector);
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new message.
|
||||
/// </summary>
|
||||
@@ -124,4 +130,4 @@ namespace Impostor.Api.Net.Messages
|
||||
/// <param name="type">New type of the message.</param>
|
||||
void Clear(MessageType type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc00PlayAnimation
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, TaskTypes task)
|
||||
{
|
||||
writer.Write((byte)task);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out TaskTypes task)
|
||||
{
|
||||
task = (TaskTypes)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc01CompleteTask
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, uint taskId)
|
||||
{
|
||||
writer.WritePacked(taskId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out uint taskId)
|
||||
{
|
||||
taskId = reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc02SyncSettings
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, GameOptionsData gameOptionsData)
|
||||
{
|
||||
gameOptionsData.Serialize(writer);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, GameOptionsData gameOptionsData)
|
||||
{
|
||||
gameOptionsData.Deserialize(reader.ReadBytesAndSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc03SetInfected
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte[] infectedIds)
|
||||
{
|
||||
writer.WriteBytesAndSize(infectedIds);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out ReadOnlyMemory<byte> infectedIds)
|
||||
{
|
||||
infectedIds = reader.ReadBytesAndSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc04Exiled
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc05CheckName
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string name)
|
||||
{
|
||||
writer.Write(name);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string name)
|
||||
{
|
||||
name = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc06SetName
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string name)
|
||||
{
|
||||
writer.Write(name);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string name)
|
||||
{
|
||||
name = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc07CheckColor
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, ColorType color)
|
||||
{
|
||||
writer.Write((byte)color);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out ColorType color)
|
||||
{
|
||||
color = (ColorType)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc08SetColor
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, ColorType color)
|
||||
{
|
||||
writer.Write((byte)color);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out ColorType color)
|
||||
{
|
||||
color = (ColorType)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc09SetHat
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, HatType hat)
|
||||
{
|
||||
writer.WritePacked((uint)hat);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out HatType hat)
|
||||
{
|
||||
hat = (HatType)reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc10SetSkin
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, SkinType skin)
|
||||
{
|
||||
writer.WritePacked((uint)skin);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out SkinType skin)
|
||||
{
|
||||
skin = (SkinType)reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc11ReportDeadBody
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte targetId)
|
||||
{
|
||||
writer.Write(targetId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out byte targetId)
|
||||
{
|
||||
targetId = reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc12MurderPlayer
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, IInnerPlayerControl target)
|
||||
{
|
||||
writer.Write(target);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IGame game, out IInnerPlayerControl? target)
|
||||
{
|
||||
target = reader.ReadNetObject<IInnerPlayerControl>(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc13SendChat
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string message)
|
||||
{
|
||||
writer.Write(message);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out string message)
|
||||
{
|
||||
message = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc14StartMeeting
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte targetId)
|
||||
{
|
||||
writer.Write(targetId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out byte targetId)
|
||||
{
|
||||
targetId = reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc15SetScanner
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, bool on, byte scannerCount)
|
||||
{
|
||||
writer.Write(on);
|
||||
writer.Write(scannerCount);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out bool on, out byte scannerCount)
|
||||
{
|
||||
on = reader.ReadBoolean();
|
||||
scannerCount = reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc16SendChatNote
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte playerId, ChatNoteType chatNoteType)
|
||||
{
|
||||
writer.Write(playerId);
|
||||
writer.Write((byte)chatNoteType);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out byte playerId, out ChatNoteType chatNoteType)
|
||||
{
|
||||
playerId = reader.ReadByte();
|
||||
chatNoteType = (ChatNoteType)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth.Customization;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc17SetPet
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, PetType pet)
|
||||
{
|
||||
writer.WritePacked((uint)pet);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out PetType pet)
|
||||
{
|
||||
pet = (PetType)reader.ReadPackedUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc18SetStartCounter
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, int sequenceId, sbyte startCounter)
|
||||
{
|
||||
writer.Write(sequenceId);
|
||||
writer.Write(startCounter);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out int sequenceId, out sbyte startCounter)
|
||||
{
|
||||
sequenceId = reader.ReadPackedInt32();
|
||||
startCounter = reader.ReadSByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc19EnterVent
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, int ventId)
|
||||
{
|
||||
writer.WritePacked(ventId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out int ventId)
|
||||
{
|
||||
ventId = reader.ReadPackedInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc20ExitVent
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, int ventId)
|
||||
{
|
||||
writer.WritePacked(ventId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out int ventId)
|
||||
{
|
||||
ventId = reader.ReadPackedInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc21SnapTo
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, Vector2 position, ushort minSid)
|
||||
{
|
||||
writer.Write(position);
|
||||
writer.Write(minSid);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out Vector2 position, out ushort minSid)
|
||||
{
|
||||
position = reader.ReadVector2();
|
||||
minSid = reader.ReadUInt16();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc22Close
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc23VotingComplete
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte[] states, byte playerId, bool tie)
|
||||
{
|
||||
writer.WriteBytesAndSize(states);
|
||||
writer.Write(playerId);
|
||||
writer.Write(tie);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out ReadOnlyMemory<byte> states, out byte playerId, out bool tie)
|
||||
{
|
||||
states = reader.ReadBytesAndSize();
|
||||
playerId = reader.ReadByte();
|
||||
tie = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc24CastVote
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte playerId, sbyte suspectPlayerId)
|
||||
{
|
||||
writer.Write(playerId);
|
||||
writer.Write(suspectPlayerId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out byte playerId, out sbyte suspectPlayerId)
|
||||
{
|
||||
playerId = reader.ReadByte();
|
||||
suspectPlayerId = reader.ReadSByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc25ClearVote
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc26AddVote
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, int clientId, int targetClientId)
|
||||
{
|
||||
writer.Write(clientId);
|
||||
writer.Write(targetClientId);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out int clientId, out int targetClientId)
|
||||
{
|
||||
clientId = reader.ReadInt32();
|
||||
targetClientId = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc27CloseDoorsOfType
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, SystemTypes systemType)
|
||||
{
|
||||
writer.Write((byte)systemType);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out SystemTypes systemType)
|
||||
{
|
||||
systemType = (SystemTypes)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc28RepairSystem
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, SystemTypes systemType, IInnerPlayerControl player, byte amount)
|
||||
{
|
||||
writer.Write((byte)systemType);
|
||||
writer.Write(player);
|
||||
writer.Write(amount);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IGame game, out SystemTypes systemType, out IInnerPlayerControl? player, out byte amount)
|
||||
{
|
||||
systemType = (SystemTypes)reader.ReadByte();
|
||||
player = reader.ReadNetObject<IInnerPlayerControl>(game);
|
||||
amount = reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc29SetTasks
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, byte playerId, ReadOnlyMemory<byte> taskTypeIds)
|
||||
{
|
||||
writer.Write(playerId);
|
||||
writer.Write(taskTypeIds);
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, out byte playerId, out ReadOnlyMemory<byte> taskTypeIds)
|
||||
{
|
||||
playerId = reader.ReadByte();
|
||||
taskTypeIds = reader.ReadBytesAndSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Api.Net.Messages.Rpcs
|
||||
{
|
||||
public static class Rpc30UpdateGameData
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void Deserialize(IMessageReader reader, IInnerGameData gameData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.ReadabilityRules">
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1111" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.NamingRules">
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Impostor.Api.Reactor
|
||||
{
|
||||
public readonly struct Mod
|
||||
{
|
||||
public readonly string Id;
|
||||
public readonly string Version;
|
||||
public readonly PluginSide Side;
|
||||
|
||||
public Mod(string id, string version, PluginSide side)
|
||||
{
|
||||
Id = id;
|
||||
Version = version;
|
||||
Side = side;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Id} ({Version})";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Reactor
|
||||
{
|
||||
public static class ModList
|
||||
{
|
||||
public static void Deserialize(IMessageReader reader, out ISet<Mod> mods)
|
||||
{
|
||||
var length = reader.ReadPackedInt32();
|
||||
|
||||
mods = new HashSet<Mod>(length);
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var id = reader.ReadString();
|
||||
var version = reader.ReadString();
|
||||
var pluginSide = (PluginSide)reader.ReadByte();
|
||||
|
||||
mods.Add(new Mod(id, version, pluginSide));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Reactor
|
||||
{
|
||||
public static class ModdedHandshakeC2S
|
||||
{
|
||||
public static void Deserialize(IMessageReader reader, out int clientVersion, out string name, out ISet<Mod>? mods)
|
||||
{
|
||||
clientVersion = reader.ReadInt32();
|
||||
name = reader.ReadString();
|
||||
|
||||
if (reader.Length > reader.Position)
|
||||
{
|
||||
ModList.Deserialize(reader, out mods);
|
||||
}
|
||||
else
|
||||
{
|
||||
mods = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Impostor.Api.Net.Messages;
|
||||
|
||||
namespace Impostor.Api.Reactor
|
||||
{
|
||||
public static class ModdedHandshakeS2C
|
||||
{
|
||||
public static void Serialize(IMessageWriter writer, string serverBrand)
|
||||
{
|
||||
writer.StartMessage(byte.MaxValue);
|
||||
writer.Write(serverBrand);
|
||||
writer.EndMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Impostor.Api.Reactor
|
||||
{
|
||||
/// <summary>
|
||||
/// Plugin side used in modded handshake
|
||||
/// </summary>
|
||||
public enum PluginSide : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Required by both sides, reject connection if missing on the other side
|
||||
/// </summary>
|
||||
Both,
|
||||
|
||||
/// <summary>
|
||||
/// Required only by client
|
||||
/// </summary>
|
||||
ClientOnly,
|
||||
|
||||
/// <summary>
|
||||
/// Required only by server
|
||||
/// </summary>
|
||||
ServerOnly,
|
||||
}
|
||||
}
|
||||
@@ -50,5 +50,10 @@
|
||||
/// <para>The interpolated float result between the two float values.</para>
|
||||
/// </returns>
|
||||
public static float Lerp(float a, float b, float t) => a + ((b - a) * Clamp01(t));
|
||||
|
||||
public static float ReverseLerp(float t)
|
||||
{
|
||||
return Clamp((t - -40f) / (40f - -40f), 0f, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<DefineConstants>HAZEL_BAG</DefineConstants>
|
||||
<Version>1.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net.Inner;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Unity;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Impostor.Hazel
|
||||
@@ -123,12 +127,16 @@ namespace Impostor.Hazel
|
||||
return output;
|
||||
}
|
||||
|
||||
public string ReadString(int length)
|
||||
{
|
||||
var output = Encoding.UTF8.GetString(Buffer.AsSpan(ReadPosition, length));
|
||||
Position += length;
|
||||
return output;
|
||||
}
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
var len = ReadPackedInt32();
|
||||
var output = Encoding.UTF8.GetString(Buffer.AsSpan(ReadPosition, len));
|
||||
Position += len;
|
||||
return output;
|
||||
return ReadString(ReadPackedInt32());
|
||||
}
|
||||
|
||||
public ReadOnlyMemory<byte> ReadBytesAndSize()
|
||||
@@ -239,6 +247,19 @@ namespace Impostor.Hazel
|
||||
return reader;
|
||||
}
|
||||
|
||||
public T ReadNetObject<T>(IGame game) where T : IInnerNetObject
|
||||
{
|
||||
return game.FindObjectByNetId<T>(ReadPackedUInt32());
|
||||
}
|
||||
|
||||
public Vector2 ReadVector2()
|
||||
{
|
||||
var x = ReadUInt16() / (float) ushort.MaxValue;
|
||||
var y = ReadUInt16() / (float) ushort.MaxValue;
|
||||
|
||||
return new Vector2(Mathf.Lerp(-40f, 40f, x), Mathf.Lerp(-40f, 40f, y));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private byte FastByte()
|
||||
{
|
||||
|
||||
@@ -4,7 +4,10 @@ using Impostor.Api.Net.Messages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Impostor.Api.Net.Inner;
|
||||
using Impostor.Api.Unity;
|
||||
|
||||
namespace Impostor.Hazel
|
||||
{
|
||||
@@ -89,6 +92,24 @@ namespace Impostor.Hazel
|
||||
this.Write(value.Value);
|
||||
}
|
||||
|
||||
public void Write(IInnerNetObject innerNetObject)
|
||||
{
|
||||
if (innerNetObject == null)
|
||||
{
|
||||
this.Write(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.WritePacked(innerNetObject.NetId);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(Vector2 vector)
|
||||
{
|
||||
Write((ushort)(Mathf.ReverseLerp(vector.X) * (double) ushort.MaxValue));
|
||||
Write((ushort)(Mathf.ReverseLerp(vector.Y) * (double) ushort.MaxValue));
|
||||
}
|
||||
|
||||
///
|
||||
public void StartMessage(byte typeFlag)
|
||||
{
|
||||
|
||||
@@ -309,9 +309,6 @@ namespace Impostor.Hazel.Udp
|
||||
//Get the ID form the packet
|
||||
var id = (ushort)((b1 << 8) + b2);
|
||||
|
||||
//Send an acknowledgement
|
||||
await SendAck(id);
|
||||
|
||||
/*
|
||||
* It gets a little complicated here (note the fact I'm actually using a multiline comment for once...)
|
||||
*
|
||||
@@ -337,6 +334,8 @@ namespace Impostor.Hazel.Udp
|
||||
* So...
|
||||
*/
|
||||
|
||||
var result = true;
|
||||
|
||||
lock (reliableDataPacketsMissing)
|
||||
{
|
||||
//Calculate overwritePointer
|
||||
@@ -379,12 +378,15 @@ namespace Impostor.Hazel.Udp
|
||||
//See if we're missing it, else this packet is a duplicate as so we return false
|
||||
if (!reliableDataPacketsMissing.Remove(id))
|
||||
{
|
||||
return false;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Send an acknowledgement
|
||||
await SendAck(id);
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -143,7 +143,10 @@ namespace Impostor.Patcher.Shared
|
||||
return false;
|
||||
}
|
||||
|
||||
return WriteIp(ipAddress, port);
|
||||
var result = WriteIp(ipAddress, port);
|
||||
OnSaved(ip, port);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +179,6 @@ namespace Impostor.Patcher.Shared
|
||||
|
||||
region.Serialize(writer);
|
||||
|
||||
OnSaved(ip, port);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<Version>1.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Impostor.Plugins.Example
|
||||
services.AddSingleton<IEventListener, GameEventListener>();
|
||||
services.AddSingleton<IEventListener, PlayerEventListener>();
|
||||
services.AddSingleton<IEventListener, MeetingEventListener>();
|
||||
services.AddSingleton<IEventListener, AnnouncementsListener>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Impostor.Api.Events;
|
||||
using Impostor.Api.Events.Announcements;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Plugins.Example.Handlers
|
||||
{
|
||||
public class AnnouncementsListener : IEventListener
|
||||
{
|
||||
private const int Id = 50;
|
||||
|
||||
[EventListener]
|
||||
public void OnAnnouncementRequestEvent(IAnnouncementRequestEvent e)
|
||||
{
|
||||
if (e.Id == Id)
|
||||
{
|
||||
// Client already has announcement cached, lets just use that
|
||||
e.Response.UseCached = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Client is receiving this announcement for the first time, window will popup
|
||||
e.Response.Announcement = new Announcement(Id, "Hello!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Impostor.Server.Utils;
|
||||
|
||||
namespace Impostor.Server.Config
|
||||
{
|
||||
internal class AnnouncementsServerConfig
|
||||
{
|
||||
private string? _resolvedListenIp;
|
||||
|
||||
public const string Section = "AnnouncementsServer";
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public string ListenIp { get; set; } = "0.0.0.0";
|
||||
|
||||
public ushort ListenPort { get; set; } = 22024;
|
||||
|
||||
public string ResolveListenIp()
|
||||
{
|
||||
return _resolvedListenIp ??= IpUtils.ResolveIp(ListenIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
{
|
||||
public const string Section = "AntiCheat";
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public bool BanIpFromGame { get; set; } = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Impostor.Api.Events.Announcements;
|
||||
using Impostor.Api.Innersloth;
|
||||
|
||||
namespace Impostor.Server.Events.Announcements
|
||||
{
|
||||
public class AnnouncementRequestEvent : IAnnouncementRequestEvent
|
||||
{
|
||||
public AnnouncementRequestEvent(int id, Language language)
|
||||
{
|
||||
Id = id;
|
||||
Language = language;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
|
||||
public Language Language { get; }
|
||||
|
||||
public IAnnouncementRequestEvent.IResponse Response { get; set; } = new AnnouncementResponse();
|
||||
|
||||
public class AnnouncementResponse : IAnnouncementRequestEvent.IResponse
|
||||
{
|
||||
public FreeWeekendState FreeWeekendState { get; set; } = FreeWeekendState.NotFree;
|
||||
|
||||
public bool UseCached { get; set; } = false;
|
||||
|
||||
public Announcement? Announcement { get; set; } = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Events;
|
||||
using Impostor.Api.Events.Managers;
|
||||
using Impostor.Server.Events.Register;
|
||||
@@ -91,10 +90,6 @@ namespace Impostor.Server.Events
|
||||
await eventListener.InvokeAsync(handler, @event, _serviceProvider);
|
||||
}
|
||||
}
|
||||
catch (ImpostorCheatException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Invocation of event {0} threw an exception.", @event.GetType().Name);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using Impostor.Api.Events.Player;
|
||||
using Impostor.Api.Events;
|
||||
using Impostor.Api.Events.Player;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Server.Events.Player
|
||||
{
|
||||
public class PlayerChatEvent : IPlayerChatEvent
|
||||
public class PlayerChatEvent : IPlayerChatEvent, IEventCancelable
|
||||
{
|
||||
public PlayerChatEvent(IGame game, IClientPlayer clientPlayer, IInnerPlayerControl playerControl, string message)
|
||||
{
|
||||
@@ -22,5 +23,7 @@ namespace Impostor.Server.Events.Player
|
||||
public IInnerPlayerControl PlayerControl { get; }
|
||||
|
||||
public string Message { get; }
|
||||
|
||||
public bool IsCancelled { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Impostor.Api.Events.Player;
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
|
||||
|
||||
@@ -2,23 +2,46 @@
|
||||
using Impostor.Api.Games;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Inner.Objects;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Impostor.Server.Events.Player
|
||||
{
|
||||
// TODO: Finish and use event, needs to be pooled
|
||||
public class PlayerMovementEvent : IPlayerEvent
|
||||
public class PlayerMovementEvent : IPlayerMovementEvent
|
||||
{
|
||||
public PlayerMovementEvent(IGame game, IClientPlayer clientPlayer, IInnerPlayerControl playerControl)
|
||||
#pragma warning disable 8766
|
||||
public IGame? Game { get; private set; }
|
||||
|
||||
public IClientPlayer? ClientPlayer { get; private set; }
|
||||
|
||||
public IInnerPlayerControl? PlayerControl { get; private set; }
|
||||
#pragma warning restore 8766
|
||||
|
||||
public void Reset(IGame game, IClientPlayer clientPlayer, IInnerPlayerControl playerControl)
|
||||
{
|
||||
Game = game;
|
||||
ClientPlayer = clientPlayer;
|
||||
PlayerControl = playerControl;
|
||||
}
|
||||
|
||||
public IGame Game { get; }
|
||||
public void Reset()
|
||||
{
|
||||
Game = null;
|
||||
ClientPlayer = null;
|
||||
PlayerControl = null;
|
||||
}
|
||||
|
||||
public IClientPlayer ClientPlayer { get; }
|
||||
public class PlayerMovementEventObjectPolicy : IPooledObjectPolicy<PlayerMovementEvent>
|
||||
{
|
||||
public PlayerMovementEvent Create()
|
||||
{
|
||||
return new PlayerMovementEvent();
|
||||
}
|
||||
|
||||
public IInnerPlayerControl PlayerControl { get; }
|
||||
public bool Return(PlayerMovementEvent obj)
|
||||
{
|
||||
obj.Reset();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Server.Net.Inner;
|
||||
using Impostor.Server.Net.State;
|
||||
|
||||
namespace Impostor.Server
|
||||
{
|
||||
internal static class MessageReaderExtensions
|
||||
{
|
||||
public static T ReadNetObject<T>(this IMessageReader reader, Game game)
|
||||
where T : InnerNetObject
|
||||
{
|
||||
return game.FindObjectByNetId<T>(reader.ReadPackedUInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Impostor.Server.Events.Player;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Impostor.Server
|
||||
{
|
||||
public static class ServiceProviderExtensions
|
||||
{
|
||||
public static void AddEventPools(this IServiceCollection services)
|
||||
{
|
||||
services.TryAddSingleton<ObjectPoolProvider>(new DefaultObjectPoolProvider());
|
||||
|
||||
services.AddSingleton(serviceProvider =>
|
||||
{
|
||||
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
|
||||
var policy = ActivatorUtilities.CreateInstance<PlayerMovementEvent.PlayerMovementEventObjectPolicy>(serviceProvider);
|
||||
return provider.Create(policy);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
<AssemblyTitle>Impostor.Server</AssemblyTitle>
|
||||
<Product>Impostor.Server</Product>
|
||||
<Copyright>Copyright © AeonLucid 2020</Copyright>
|
||||
<Version>1.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -35,6 +34,8 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!-- HACK: Some plugins depend on System.IO.Pipelines and expect the version to be 5.0.0.0, but .NET 5 only ships version 5.0.0.1. It is pretty hard to convince MSBuild to build against the correct DLL, so we special case it here. Remove once we move past .NET 5 -->
|
||||
<PackageReference Include="System.IO.Pipelines" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -55,4 +56,4 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Events.Managers;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.Announcements;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Hazel.Udp;
|
||||
using Impostor.Server.Config;
|
||||
using Impostor.Server.Events.Announcements;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Impostor.Server.Net
|
||||
{
|
||||
internal class AnnouncementsService : IHostedService
|
||||
{
|
||||
private readonly AnnouncementsServerConfig _config;
|
||||
private readonly ObjectPool<MessageReader> _readerPool;
|
||||
private readonly IEventManager _eventManager;
|
||||
private UdpConnectionListener _connection;
|
||||
|
||||
public AnnouncementsService(IOptions<AnnouncementsServerConfig> config, ObjectPool<MessageReader> readerPool, IEventManager eventManager)
|
||||
{
|
||||
_config = config.Value;
|
||||
_readerPool = readerPool;
|
||||
_eventManager = eventManager;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var endpoint = new IPEndPoint(IPAddress.Parse(_config.ResolveListenIp()), _config.ListenPort);
|
||||
|
||||
var mode = endpoint.AddressFamily switch
|
||||
{
|
||||
AddressFamily.InterNetwork => IPMode.IPv4,
|
||||
AddressFamily.InterNetworkV6 => IPMode.IPv6,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
|
||||
_connection = new UdpConnectionListener(endpoint, _readerPool, mode)
|
||||
{
|
||||
NewConnection = OnNewConnection,
|
||||
};
|
||||
|
||||
await _connection.StartAsync();
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _connection.DisposeAsync();
|
||||
}
|
||||
|
||||
private async ValueTask OnNewConnection(NewConnectionEventArgs e)
|
||||
{
|
||||
MessageHello.Deserialize(e.HandshakeData, out var announcementVersion, out var id, out var language);
|
||||
|
||||
if (announcementVersion != 2)
|
||||
{
|
||||
await e.Connection.Disconnect("Unsupported announcement version");
|
||||
return;
|
||||
}
|
||||
|
||||
var @event = new AnnouncementRequestEvent(id, language);
|
||||
await _eventManager.CallAsync(@event);
|
||||
|
||||
var response = @event.Response;
|
||||
|
||||
if (response.UseCached)
|
||||
{
|
||||
using var writer = MessageWriter.Get(MessageType.Reliable);
|
||||
Message00UseCache.Serialize(writer);
|
||||
await e.Connection.SendAsync(writer);
|
||||
}
|
||||
|
||||
if (response.Announcement != null)
|
||||
{
|
||||
using var writer = MessageWriter.Get(MessageType.Reliable);
|
||||
var announcement = response.Announcement.Value;
|
||||
Message01Update.Serialize(writer, announcement.Id, announcement.Message);
|
||||
await e.Connection.SendAsync(writer);
|
||||
}
|
||||
|
||||
if (response.FreeWeekendState != FreeWeekendState.NotFree)
|
||||
{
|
||||
using var writer = MessageWriter.Get(MessageType.Reliable);
|
||||
Message02SetFreeWeekend.Serialize(writer, response.FreeWeekendState);
|
||||
await e.Connection.SendAsync(writer);
|
||||
}
|
||||
|
||||
await e.Connection.Disconnect(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Games;
|
||||
@@ -7,6 +8,7 @@ using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.C2S;
|
||||
using Impostor.Api.Net.Messages.S2C;
|
||||
using Impostor.Api.Reactor;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Server.Config;
|
||||
using Impostor.Server.Net.Manager;
|
||||
@@ -22,8 +24,8 @@ namespace Impostor.Server.Net
|
||||
private readonly ClientManager _clientManager;
|
||||
private readonly GameManager _gameManager;
|
||||
|
||||
public Client(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, string name, IHazelConnection connection)
|
||||
: base(name, connection)
|
||||
public Client(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, string name, IHazelConnection connection, ISet<Mod> mods)
|
||||
: base(name, connection, mods)
|
||||
{
|
||||
_logger = logger;
|
||||
_antiCheatConfig = antiCheatOptions.Value;
|
||||
@@ -31,6 +33,25 @@ namespace Impostor.Server.Net
|
||||
_gameManager = gameManager;
|
||||
}
|
||||
|
||||
public override async ValueTask<bool> ReportCheatAsync(CheatContext context, string message)
|
||||
{
|
||||
_logger.LogWarning("Client {Name} ({Id}) was caught cheating: [{Context}] {Message}", Name, Id, context.Name, message);
|
||||
|
||||
if (!_antiCheatConfig.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_antiCheatConfig.BanIpFromGame)
|
||||
{
|
||||
Player?.Game.BanIp(Connection.EndPoint.Address);
|
||||
}
|
||||
|
||||
await DisconnectAsync(DisconnectReason.Hacking, context.Name + ": " + message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async ValueTask HandleMessageAsync(IMessageReader reader, MessageType messageType)
|
||||
{
|
||||
var flag = reader.Tag;
|
||||
@@ -150,38 +171,25 @@ namespace Impostor.Server.Net
|
||||
// Handle packet.
|
||||
using var readerCopy = reader.Copy();
|
||||
|
||||
// TODO: Return value, either a bool (to cancel) or a writer (to cancel (null) or modify/overwrite).
|
||||
try
|
||||
var verified = await Player.Game.HandleGameDataAsync(readerCopy, Player, toPlayer);
|
||||
if (verified)
|
||||
{
|
||||
var verified = await Player.Game.HandleGameDataAsync(readerCopy, Player, toPlayer);
|
||||
if (verified)
|
||||
// Broadcast packet to all other players.
|
||||
using (var writer = MessageWriter.Get(messageType))
|
||||
{
|
||||
// Broadcast packet to all other players.
|
||||
using (var writer = MessageWriter.Get(messageType))
|
||||
if (toPlayer)
|
||||
{
|
||||
if (toPlayer)
|
||||
{
|
||||
var target = reader.ReadPackedInt32();
|
||||
reader.CopyTo(writer);
|
||||
await Player.Game.SendToAsync(writer, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.CopyTo(writer);
|
||||
await Player.Game.SendToAllExceptAsync(writer, Id);
|
||||
}
|
||||
var target = reader.ReadPackedInt32();
|
||||
reader.CopyTo(writer);
|
||||
await Player.Game.SendToAsync(writer, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.CopyTo(writer);
|
||||
await Player.Game.SendToAllExceptAsync(writer, Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ImpostorCheatException e)
|
||||
{
|
||||
if (_antiCheatConfig.BanIpFromGame)
|
||||
{
|
||||
Player.Game.BanIp(Connection.EndPoint.Address);
|
||||
}
|
||||
|
||||
await DisconnectAsync(DisconnectReason.Hacking, e.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -196,7 +204,7 @@ namespace Impostor.Server.Net
|
||||
Message08EndGameC2S.Deserialize(
|
||||
reader,
|
||||
out var gameOverReason);
|
||||
|
||||
|
||||
await Player.Game.HandleEndGame(reader, gameOverReason);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.S2C;
|
||||
using Impostor.Api.Reactor;
|
||||
using Impostor.Hazel;
|
||||
using Impostor.Server.Net.State;
|
||||
|
||||
@@ -13,17 +16,34 @@ namespace Impostor.Server.Net
|
||||
{
|
||||
internal abstract class ClientBase : IClient
|
||||
{
|
||||
protected ClientBase(string name, IHazelConnection connection)
|
||||
protected ClientBase(string name, IHazelConnection connection, ISet<Mod> mods)
|
||||
{
|
||||
Name = name;
|
||||
Connection = connection;
|
||||
Mods = mods;
|
||||
Items = new ConcurrentDictionary<object, object>();
|
||||
|
||||
ModIdMap = new Dictionary<int, string>();
|
||||
|
||||
var i = -1;
|
||||
|
||||
foreach (var mod in mods.OrderBy(x => x.Id))
|
||||
{
|
||||
if (mod.Side == PluginSide.Both)
|
||||
{
|
||||
ModIdMap[i--] = mod.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public ISet<Mod> Mods { get; }
|
||||
|
||||
public Dictionary<int, string> ModIdMap { get; }
|
||||
|
||||
public IHazelConnection Connection { get; }
|
||||
|
||||
public IDictionary<object, object> Items { get; }
|
||||
@@ -32,6 +52,11 @@ namespace Impostor.Server.Net
|
||||
|
||||
IClientPlayer? IClient.Player => Player;
|
||||
|
||||
public virtual ValueTask<bool> ReportCheatAsync(CheatContext context, string message)
|
||||
{
|
||||
return new ValueTask<bool>(false);
|
||||
}
|
||||
|
||||
public abstract ValueTask HandleMessageAsync(IMessageReader message, MessageType messageType);
|
||||
|
||||
public abstract ValueTask HandleDisconnectAsync(string reason);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Reactor;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Impostor.Server.Net.Factories
|
||||
@@ -14,9 +16,9 @@ namespace Impostor.Server.Net.Factories
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public ClientBase Create(IHazelConnection connection, string name, int clientVersion)
|
||||
public ClientBase Create(IHazelConnection connection, string name, int clientVersion, ISet<Mod> mods)
|
||||
{
|
||||
var client = ActivatorUtilities.CreateInstance<TClient>(_serviceProvider, name, connection);
|
||||
var client = ActivatorUtilities.CreateInstance<TClient>(_serviceProvider, name, connection, mods);
|
||||
connection.Client = client;
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using Impostor.Api.Net;
|
||||
using System.Collections.Generic;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Reactor;
|
||||
|
||||
namespace Impostor.Server.Net.Factories
|
||||
{
|
||||
internal interface IClientFactory
|
||||
{
|
||||
ClientBase Create(IHazelConnection connection, string name, int clientVersion);
|
||||
ClientBase Create(IHazelConnection connection, string name, int clientVersion, ISet<Mod> mods);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Server.Net.Inner.Objects;
|
||||
|
||||
namespace Impostor.Server.Net.Inner
|
||||
{
|
||||
internal abstract partial class InnerNetObject
|
||||
{
|
||||
protected async ValueTask<bool> ValidateOwnership(CheatContext context, IClientPlayer sender)
|
||||
{
|
||||
if (!sender.IsOwner(this))
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, $"Failed ownership check on {GetType().Name}"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateHost(CheatContext context, IClientPlayer sender)
|
||||
{
|
||||
if (!sender.IsHost)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Failed host check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateTarget(CheatContext context, IClientPlayer sender, IClientPlayer? target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Failed target check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateBroadcast(CheatContext context, IClientPlayer sender, IClientPlayer? target)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Failed broadcast check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateCmd(CheatContext context, IClientPlayer sender, IClientPlayer? target)
|
||||
{
|
||||
if (target == null || !target.IsHost)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Failed cmd check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> ValidateImpostor(CheatContext context, IClientPlayer sender, InnerPlayerInfo playerInfo, bool value = true)
|
||||
{
|
||||
if (playerInfo.IsImpostor != value)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Failed impostor check"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async ValueTask<bool> UnregisteredCall(CheatContext context, IClientPlayer sender)
|
||||
{
|
||||
if (await sender.Client.ReportCheatAsync(context, "Client sent unregistered call"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Inner;
|
||||
using Impostor.Api.Net.Messages;
|
||||
@@ -6,7 +7,7 @@ using Impostor.Server.Net.State;
|
||||
|
||||
namespace Impostor.Server.Net.Inner
|
||||
{
|
||||
internal abstract class InnerNetObject : GameObject, IInnerNetObject
|
||||
internal abstract partial class InnerNetObject : GameObject, IInnerNetObject
|
||||
{
|
||||
private const int HostInheritId = -2;
|
||||
|
||||
@@ -16,16 +17,31 @@ namespace Impostor.Server.Net.Inner
|
||||
|
||||
public SpawnFlags SpawnFlags { get; internal set; }
|
||||
|
||||
public abstract ValueTask HandleRpc(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader);
|
||||
|
||||
public abstract bool Serialize(IMessageWriter writer, bool initialState);
|
||||
|
||||
public abstract void Deserialize(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState);
|
||||
|
||||
public bool IsOwnedBy(IClientPlayer player)
|
||||
{
|
||||
return OwnerId == player.Client.Id ||
|
||||
(OwnerId == HostInheritId && player.IsHost);
|
||||
}
|
||||
|
||||
public abstract ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState);
|
||||
|
||||
public abstract ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState);
|
||||
|
||||
public abstract ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader);
|
||||
|
||||
protected ValueTask<bool> HandleCustomRpc(IMessageReader reader, Game game)
|
||||
{
|
||||
var lengthOrShortId = reader.ReadPackedInt32();
|
||||
|
||||
var pluginId = lengthOrShortId < 0
|
||||
? game.Host!.Client.ModIdMap[lengthOrShortId]
|
||||
: reader.ReadString(lengthOrShortId);
|
||||
|
||||
var id = reader.ReadPackedInt32();
|
||||
|
||||
// TODO handle custom rpcs
|
||||
|
||||
return ValueTask.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,12 @@ namespace Impostor.Server.Net.Inner.Objects.Components
|
||||
var minSid = (ushort)(_lastSequenceId + 5U);
|
||||
|
||||
// Snap in the server.
|
||||
SnapTo(position, minSid);
|
||||
await SnapToAsync(_game.GetClientPlayer(OwnerId), position, minSid);
|
||||
|
||||
// Broadcast to all clients.
|
||||
using (var writer = _game.StartRpc(NetId, RpcCalls.SnapTo))
|
||||
{
|
||||
WriteVector2(writer, position);
|
||||
writer.Write(position);
|
||||
writer.Write(_lastSequenceId);
|
||||
await _game.FinishRpcAsync(writer);
|
||||
}
|
||||
|
||||
@@ -1,125 +1,84 @@
|
||||
using System.Numerics;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Events.Managers;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.Rpcs;
|
||||
using Impostor.Server.Events.Player;
|
||||
using Impostor.Server.Net.State;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Impostor.Server.Net.Inner.Objects.Components
|
||||
{
|
||||
internal partial class InnerCustomNetworkTransform : InnerNetObject
|
||||
{
|
||||
private static readonly FloatRange XRange = new FloatRange(-40f, 40f);
|
||||
private static readonly FloatRange YRange = new FloatRange(-40f, 40f);
|
||||
|
||||
private readonly ILogger<InnerCustomNetworkTransform> _logger;
|
||||
private readonly InnerPlayerControl _playerControl;
|
||||
private readonly Game _game;
|
||||
private readonly IEventManager _eventManager;
|
||||
private readonly ObjectPool<PlayerMovementEvent> _pool;
|
||||
|
||||
private ushort _lastSequenceId;
|
||||
private Vector2 _targetSyncPosition;
|
||||
private Vector2 _targetSyncVelocity;
|
||||
|
||||
public InnerCustomNetworkTransform(ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, Game game)
|
||||
public Vector2 Position { get; private set; }
|
||||
|
||||
public Vector2 Velocity { get; private set; }
|
||||
|
||||
public InnerCustomNetworkTransform(ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, Game game, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool)
|
||||
{
|
||||
_logger = logger;
|
||||
_playerControl = playerControl;
|
||||
_game = game;
|
||||
_game = game;
|
||||
_eventManager = eventManager;
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
private static bool SidGreaterThan(ushort newSid, ushort prevSid)
|
||||
{
|
||||
var num = (ushort)(prevSid + (uint) short.MaxValue);
|
||||
var num = (ushort)(prevSid + (uint)short.MaxValue);
|
||||
|
||||
return (int) prevSid < (int) num
|
||||
return (int)prevSid < (int)num
|
||||
? newSid > prevSid && newSid <= num
|
||||
: newSid > prevSid || newSid <= num;
|
||||
}
|
||||
|
||||
private static void WriteVector2(IMessageWriter writer, Vector2 vec)
|
||||
{
|
||||
writer.Write((ushort)(XRange.ReverseLerp(vec.X) * (double) ushort.MaxValue));
|
||||
writer.Write((ushort)(YRange.ReverseLerp(vec.Y) * (double) ushort.MaxValue));
|
||||
}
|
||||
|
||||
private static Vector2 ReadVector2(IMessageReader reader)
|
||||
{
|
||||
var v1 = reader.ReadUInt16() / (float) ushort.MaxValue;
|
||||
var v2 = reader.ReadUInt16() / (float) ushort.MaxValue;
|
||||
|
||||
return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2));
|
||||
}
|
||||
|
||||
public override ValueTask HandleRpc(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
|
||||
{
|
||||
if (call == RpcCalls.SnapTo)
|
||||
{
|
||||
if (!sender.IsOwner(this))
|
||||
{
|
||||
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} to an unowned {nameof(InnerPlayerControl)}");
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} to a specific player instead of broadcast");
|
||||
}
|
||||
|
||||
if (!sender.Character.PlayerInfo.IsImpostor)
|
||||
{
|
||||
throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} as crewmate");
|
||||
}
|
||||
|
||||
SnapTo(ReadVector2(reader), reader.ReadUInt16());
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerCustomNetworkTransform), call);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override bool Serialize(IMessageWriter writer, bool initialState)
|
||||
public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
|
||||
{
|
||||
if (initialState)
|
||||
{
|
||||
writer.Write(_lastSequenceId);
|
||||
WriteVector2(writer, _targetSyncPosition);
|
||||
WriteVector2(writer, _targetSyncVelocity);
|
||||
return true;
|
||||
writer.Write(Position);
|
||||
writer.Write(Velocity);
|
||||
return new ValueTask<bool>(true);
|
||||
}
|
||||
|
||||
// TODO: DirtyBits == 0 return false.
|
||||
_lastSequenceId++;
|
||||
|
||||
writer.Write(_lastSequenceId);
|
||||
WriteVector2(writer, _targetSyncPosition);
|
||||
WriteVector2(writer, _targetSyncVelocity);
|
||||
return true;
|
||||
writer.Write(Position);
|
||||
writer.Write(Velocity);
|
||||
return new ValueTask<bool>(true);
|
||||
}
|
||||
|
||||
public override void Deserialize(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
|
||||
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
|
||||
{
|
||||
var sequenceId = reader.ReadUInt16();
|
||||
|
||||
if (initialState)
|
||||
{
|
||||
_lastSequenceId = sequenceId;
|
||||
_targetSyncPosition = ReadVector2(reader);
|
||||
_targetSyncVelocity = ReadVector2(reader);
|
||||
await SetPositionAsync(sender, reader.ReadVector2(), reader.ReadVector2());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sender.IsOwner(this))
|
||||
if (!await ValidateOwnership(CheatContext.Deserialize, sender) || !await ValidateBroadcast(CheatContext.Deserialize, sender, target))
|
||||
{
|
||||
throw new ImpostorCheatException($"Client attempted to send unowned {nameof(InnerCustomNetworkTransform)} data");
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
throw new ImpostorCheatException($"Client attempted to send {nameof(InnerCustomNetworkTransform)} data to a specific player, must be broadcast");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SidGreaterThan(sequenceId, _lastSequenceId))
|
||||
@@ -128,21 +87,48 @@ namespace Impostor.Server.Net.Inner.Objects.Components
|
||||
}
|
||||
|
||||
_lastSequenceId = sequenceId;
|
||||
_targetSyncPosition = ReadVector2(reader);
|
||||
_targetSyncVelocity = ReadVector2(reader);
|
||||
await SetPositionAsync(sender, reader.ReadVector2(), reader.ReadVector2());
|
||||
}
|
||||
}
|
||||
|
||||
private void SnapTo(Vector2 position, ushort minSid)
|
||||
public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
|
||||
{
|
||||
if (call == RpcCalls.SnapTo)
|
||||
{
|
||||
if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(RpcCalls.MurderPlayer, sender, _playerControl.PlayerInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Rpc21SnapTo.Deserialize(reader, out var position, out var minSid);
|
||||
|
||||
await SnapToAsync(sender, position, minSid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return await UnregisteredCall(call, sender);
|
||||
}
|
||||
|
||||
internal async ValueTask SetPositionAsync(IClientPlayer sender, Vector2 position, Vector2 velocity)
|
||||
{
|
||||
Position = position;
|
||||
Velocity = velocity;
|
||||
|
||||
var playerMovementEvent = _pool.Get();
|
||||
playerMovementEvent.Reset(_game, sender, _playerControl);
|
||||
await _eventManager.CallAsync(playerMovementEvent);
|
||||
_pool.Return(playerMovementEvent);
|
||||
}
|
||||
|
||||
private ValueTask SnapToAsync(IClientPlayer sender, Vector2 position, ushort minSid)
|
||||
{
|
||||
if (!SidGreaterThan(minSid, _lastSequenceId))
|
||||
{
|
||||
return;
|
||||
return default;
|
||||
}
|
||||
|
||||
_lastSequenceId = minSid;
|
||||
_targetSyncPosition = position;
|
||||
_targetSyncVelocity = Vector2.Zero;
|
||||
return SetPositionAsync(sender, position, Velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Impostor.Api;
|
||||
using Impostor.Api.Events.Managers;
|
||||
using Impostor.Api.Innersloth;
|
||||
using Impostor.Api.Net;
|
||||
using Impostor.Api.Net.Messages;
|
||||
using Impostor.Api.Net.Messages.Rpcs;
|
||||
using Impostor.Server.Events.Player;
|
||||
using Impostor.Server.Net.State;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -26,45 +27,45 @@ namespace Impostor.Server.Net.Inner.Objects.Components
|
||||
_game = game;
|
||||
}
|
||||
|
||||
public override async ValueTask HandleRpc(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
|
||||
{
|
||||
if (call != RpcCalls.EnterVent && call != RpcCalls.ExitVent)
|
||||
{
|
||||
_logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerPlayerPhysics), call);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sender.IsOwner(this))
|
||||
{
|
||||
throw new ImpostorCheatException($"Client sent {call} to an unowned {nameof(InnerPlayerControl)}");
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
throw new ImpostorCheatException($"Client sent {call} to a specific player instead of broadcast");
|
||||
}
|
||||
|
||||
if (!sender.Character.PlayerInfo.IsImpostor)
|
||||
{
|
||||
throw new ImpostorCheatException($"Client sent {call} as crewmate");
|
||||
}
|
||||
|
||||
var ventId = reader.ReadPackedUInt32();
|
||||
var ventEnter = call == RpcCalls.EnterVent;
|
||||
|
||||
await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, ventEnter));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public override bool Serialize(IMessageWriter writer, bool initialState)
|
||||
public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Deserialize(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
|
||||
public override ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
|
||||
{
|
||||
if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(RpcCalls.MurderPlayer, sender, _playerControl.PlayerInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int ventId;
|
||||
|
||||
switch (call)
|
||||
{
|
||||
case RpcCalls.EnterVent:
|
||||
Rpc19EnterVent.Deserialize(reader, out ventId);
|
||||
break;
|
||||
|
||||
case RpcCalls.ExitVent:
|
||||
Rpc19EnterVent.Deserialize(reader, out ventId);
|
||||
break;
|
||||
|
||||
case RpcCalls.CustomRpc:
|
||||
return await HandleCustomRpc(reader, _game);
|
||||
|
||||
default:
|
||||
return await UnregisteredCall(call, sender);
|
||||
}
|
||||
|
||||
await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, call == RpcCalls.EnterVent));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user