55 Commits

Author SHA1 Message Date
39b780e518 Merge pull request #56 from RAGECOOP/dev-nightly 2023-10-23 10:48:52 -03:00
4a54851c51 Update AssemblyInfo.cs 2023-10-23 10:36:57 -03:00
f0eefa575c Always sync player ped 2023-10-22 18:59:19 -03:00
3fc813b2d8 Fix bug disconnecting from server 2023-10-22 17:14:50 -03:00
fbff72ff14 Update LemonUI 2023-10-18 16:57:19 -03:00
4e52407591 Update nightly-build.yaml 2023-10-18 16:56:44 -03:00
4e6fde129d Add global limits 2023-10-18 10:41:34 -03:00
92e1a970a8 Show kill notification 2023-10-06 23:46:08 -03:00
d0eb0b7818 Bump version
Add kill message
2023-10-06 16:36:49 -03:00
14151d7b2c Add option to disable blip and nametag display 2023-08-14 14:08:30 -03:00
1f8d70a520 Fix player dying when switching characters in missions 2023-08-13 19:29:48 -03:00
2cb5baf5f7 Fix player dying when switching characters 2023-08-09 23:50:47 -03:00
34e33937e2 Merge pull request #49 from RAGECOOP/dev-nightly
Update README.md
2023-07-26 15:46:58 -03:00
9287aba0f9 Update README.md 2023-07-26 15:42:08 -03:00
e88e903096 Merge pull request #48 from RAGECOOP/dev-nightly
Dev nightly
2023-07-26 15:27:40 -03:00
99642fd40c Update SHVDN 2023-07-26 15:12:58 -03:00
2fbf06b504 Use Lidgren.Network release build 2023-07-24 10:40:33 -03:00
13b771ec9f Fix exception entering vehicle as passenger 2023-07-24 10:39:37 -03:00
3b987f59e0 Remove update menu 2023-07-14 09:43:00 -03:00
de96f29097 Don't delete peds in vehicle 2023-07-14 09:39:06 -03:00
6136cbfc14 Allow multiple servers on same address
with different ports
2023-07-14 09:38:02 -03:00
ed145aedd6 Update master server 2023-07-14 09:36:49 -03:00
3f3b5fd2d0 Closes #40 2022-09-30 23:40:14 +08:00
9173e9a99e Fix non-ambient peds get deleted 2022-09-30 23:27:37 +08:00
6e64c458df Merge branch 'dev-nightly' of https://github.com/RAGECOOP/RAGECOOP-V into dev-nightly 2022-09-09 11:24:02 +08:00
76f959abe9 Stuff 2022-09-09 11:23:46 +08:00
f2e85d66ab Update build-test.yaml 2022-09-09 11:15:27 +08:00
e30ef1f4bd Update actions 2022-09-08 20:09:52 -07:00
6e8f6e78f6 Add build test action 2022-09-08 20:05:26 -07:00
f28c83ccbd Merge pull request #38 from RAGECOOP/dev-nightly
Bump to 1.5.4
2022-09-07 22:44:48 -07:00
a83821b3d2 Version bump 2022-09-08 13:19:09 -07:00
3b5436064e Don't announce if already present in master server 2022-09-08 13:15:34 -07:00
c4b321324e Filter out white space for reload key parsing 2022-09-08 12:59:14 -07:00
ba8d525ddf Merge pull request #37 from RAGECOOP/dev-nightly
Rewrite packet system
2022-09-07 21:45:14 -07:00
884e2f39f0 Yet another code cleanup 2022-09-08 12:41:56 -07:00
76c529f1d1 Rewrote packet system to reduce heap allocation 2022-09-08 12:37:06 -07:00
df0064bd38 Update nightly-build.yaml 2022-09-07 21:01:22 -07:00
f1fc96bbd7 Fix weird projectile shooting 2022-09-07 11:08:25 +08:00
23e9326f5f Fix stuff, add listening address display and projectile shoot prediction 2022-09-07 09:52:40 +08:00
4621fb4987 Some code cleanup and formatting 2022-09-06 21:46:35 +08:00
6c82895fa7 code cleaned up 2022-09-05 13:02:09 +02:00
84b040766f Simplify GetBytesFromObject 2022-08-27 14:23:28 +08:00
f44558cd3b Add some client API 2022-08-27 14:17:10 +08:00
accdbbcbc6 blah 2022-08-27 13:53:03 +08:00
2d4107f35e Fix traffic 2022-08-27 12:40:47 +08:00
bac53fd769 Load scripts from main assembly only 2022-08-26 22:58:03 +08:00
8f63fee5b5 Delete temp directory 2022-08-25 22:34:54 +08:00
8d0ad0b600 Show runtime information 2022-08-25 22:32:01 +08:00
dc08c0c1f6 Added support for loading runtime-specific libraries 2022-08-25 21:51:09 +08:00
faaa856aa5 Instructional buttons for popup 2022-08-25 00:58:21 +08:00
eab64f9254 Check fixed data every 100 frames 2022-08-24 22:38:50 +08:00
6c936cb8f9 Show help in popup 2022-08-24 19:26:40 +08:00
83a37f8556 blah 2022-08-24 18:48:21 +08:00
bb4eacce26 Don't disable traffic if not on server 2022-08-24 18:47:59 +08:00
d5b71db5d4 💩 2022-08-23 23:21:35 +08:00
109 changed files with 3395 additions and 3572 deletions

48
.github/workflows/build-test.yaml vendored Normal file
View File

@ -0,0 +1,48 @@
name: Build test
on:
push:
branches:
- '*' # matches every branch that doesn't contain a '/'
- '*/*' # matches every branch containing a single '/'
- '**' # matches every branch
- '!main' # excludes main
- '!dev-nightly' # excludes nightly
pull_request:
branches: [ "main", "dev-nightly" ]
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
dotnet-version: ['6.0.x']
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Restore dependencies
run: dotnet restore
- name: Restore nuget packages
run: nuget restore
- name: Build client and installer
run: dotnet build RageCoop.Client.Installer/RageCoop.Client.Installer.csproj --configuration Release -o bin/Release/Client/RageCoop
- name: Build server win-x64
run: dotnet build RageCoop.Server/RageCoop.Server.csproj -o bin/Release/Server
- name: Upload server
uses: actions/upload-artifact@v3
with:
name: RageCoop.Server
path: bin/Release/Server
- name: Upload Client
uses: actions/upload-artifact@v3
with:
name: RageCoop.Client
path: bin/Release/Client
- uses: actions/checkout@v2

View File

@ -2,9 +2,7 @@ name: Nightly-build
on: on:
push: push:
branches: [ "main" ] branches: [ "dev-nightly" ]
pull_request:
branches: [ "main" ]
jobs: jobs:
build: build:
@ -30,8 +28,6 @@ jobs:
run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r win-x64 -o bin/Release/Server/win-x64 -c Release run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r win-x64 -o bin/Release/Server/win-x64 -c Release
- name: Build server linux-x64 - name: Build server linux-x64
run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r linux-x64 -o bin/Release/Server/linux-x64 -c Release run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r linux-x64 -o bin/Release/Server/linux-x64 -c Release
- name: Build server linux-arm
run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r linux-arm -o bin/Release/Server/linux-arm -c Release
- uses: vimtor/action-zip@v1 - uses: vimtor/action-zip@v1
with: with:
files: bin/Release/Client files: bin/Release/Client
@ -47,11 +43,6 @@ jobs:
files: bin/Release/Server/linux-x64 files: bin/Release/Server/linux-x64
dest: RageCoop.Server-linux-x64.zip dest: RageCoop.Server-linux-x64.zip
- uses: vimtor/action-zip@v1
with:
files: bin/Release/Server/linux-arm
dest: RageCoop.Server-linux-arm.zip
- uses: WebFreak001/deploy-nightly@v1.1.0 - uses: WebFreak001/deploy-nightly@v1.1.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions
@ -84,17 +75,3 @@ jobs:
asset_name: RageCoop.Server-linux-x64.zip asset_name: RageCoop.Server-linux-x64.zip
asset_content_type: application/zip asset_content_type: application/zip
max_releases: 7 max_releases: 7
- uses: WebFreak001/deploy-nightly@v1.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions
with:
upload_url: https://uploads.github.com/repos/RAGECOOP/RAGECOOP-V/releases/70603992/assets{?name,label}
release_id: 70603992
asset_path: RageCoop.Server-linux-arm.zip
asset_name: RageCoop.Server-linux-arm.zip
asset_content_type: application/zip
max_releases: 7
- uses: actions/checkout@v2

View File

@ -15,7 +15,7 @@ RAGECOOP brings multiplayer experience to the story mode, you can complete missi
# 👁 Requirements # 👁 Requirements
- ScriptHookV - ScriptHookV
- ScriptHookVDotNet 3.5.1 or later - ScriptHookVDotNet 3.6.0 or later
- .NET Framework 4.8 Runtime or SDK - .NET Framework 4.8 Runtime or SDK
# 📋 Building the project # 📋 Building the project
@ -49,7 +49,7 @@ Then run `dotnet build` in the solution directory, built binaries are in the `bi
5. Decent compatibility with other mods, set up a private modded server to have some fun! 5. Decent compatibility with other mods, set up a private modded server to have some fun!
6. Weaponized vehicle sync(WIP). 6. Weaponized vehicle sync(WIP).
7. Optimization for high-Ping condition, play with friends around the world! 7. Optimization for high-Ping condition, play with friends around the world!
8. Powerful scripting API and resource system, easily [add multiplayer functionality to your mod](HTTPS://docs.ragecoop.online). 8. Powerful scripting API and resource system, easily [add multiplayer functionality to your mod](HTTPS://docs.ragecoop.com).
# ⚠ Known issues # ⚠ Known issues

View File

@ -1,10 +1,4 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace RageCoop.Client.Installer namespace RageCoop.Client.Installer
{ {

View File

@ -1,27 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using RageCoop.Core;
using System.Threading;
using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using Path = System.IO.Path; using System.Windows.Input;
using MessageBox = System.Windows.MessageBox; using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog; using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using Path = System.IO.Path;
using RageCoop.Core;
namespace RageCoop.Client.Installer namespace RageCoop.Client.Installer
{ {
@ -45,7 +35,8 @@ namespace RageCoop.Client.Installer
}; };
if (od.ShowDialog() ?? false == true) if (od.ShowDialog() ?? false == true)
{ {
Task.Run(() => { Task.Run(() =>
{
try try
{ {
Install(Directory.GetParent(od.FileName).FullName); Install(Directory.GetParent(od.FileName).FullName);
@ -62,7 +53,8 @@ namespace RageCoop.Client.Installer
Environment.Exit(0); Environment.Exit(0);
} }
} }
void Install(string root)
private void Install(string root)
{ {
UpdateStatus("Checking requirements"); UpdateStatus("Checking requirements");
var shvPath = Path.Combine(root, "ScriptHookV.dll"); var shvPath = Path.Combine(root, "ScriptHookV.dll");
@ -86,10 +78,10 @@ namespace RageCoop.Client.Installer
Environment.Exit(1); Environment.Exit(1);
} }
var shvdnVer = GetVer(shvdnPath); var shvdnVer = GetVer(shvdnPath);
if (shvdnVer<new Version(3,5,1)) if (shvdnVer < new Version(3, 6, 0))
{ {
MessageBox.Show("Please update ScriptHookVDotNet to latest version!" + MessageBox.Show("Please update ScriptHookVDotNet to latest version!" +
$"\nCurrent version is {shvdnVer}, 3.5.1 or higher is required"); $"\nCurrent version is {shvdnVer}, 3.6.0 or higher is required");
Environment.Exit(1); Environment.Exit(1);
} }
if (File.Exists(lemonPath)) if (File.Exists(lemonPath))
@ -201,15 +193,18 @@ namespace RageCoop.Client.Installer
Environment.Exit(0); Environment.Exit(0);
} }
} }
void UpdateStatus(string status)
private void UpdateStatus(string status)
{ {
Dispatcher.BeginInvoke(new Action(() => Status.Content = status)); Dispatcher.BeginInvoke(new Action(() => Status.Content = status));
} }
Version GetVer(string location)
private Version GetVer(string location)
{ {
return Version.Parse(FileVersionInfo.GetVersionInfo(location).FileVersion); return Version.Parse(FileVersionInfo.GetVersionInfo(location).FileVersion);
} }
byte[] getLemon()
private byte[] getLemon()
{ {
return (byte[])Resource.ResourceManager.GetObject("LemonUI_SHVDN3"); return (byte[])Resource.ResourceManager.GetObject("LemonUI_SHVDN3");
} }

View File

@ -0,0 +1,72 @@
<Project>
<PropertyGroup>
<AssemblyName>RageCoop.Client.Installer</AssemblyName>
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<MSBuildProjectExtensionsPath>M:\SandBox-Shared\repos\RAGECOOP\RAGECOOP-V\RageCoop.Client.Installer\obj\</MSBuildProjectExtensionsPath>
<_TargetAssemblyProjectName>RageCoop.Client.Installer</_TargetAssemblyProjectName>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net48</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<None Remove="bg.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RageCoop.Client\RageCoop.Client.csproj" />
<ProjectReference Include="..\RageCoop.Core\RageCoop.Core.csproj" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<Compile Update="Resource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ReferencePath Include="C:\Users\Sardelka\.nuget\packages\sharpziplib\1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll" />
<ReferencePath Include="C:\Users\Sardelka\.nuget\packages\microsoft.extensions.objectpool\6.0.8\lib\net461\Microsoft.Extensions.ObjectPool.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\mscorlib.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\PresentationCore.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\PresentationFramework.dll" />
<ReferencePath Include="M:\SandBox-Shared\repos\RAGECOOP\RAGECOOP-V\bin\Debug\Client\RageCoop.Client.dll" />
<ReferencePath Include="M:\SandBox-Shared\repos\RAGECOOP\RAGECOOP-V\bin\Debug\Core\RageCoop.Core.dll" />
<ReferencePath Include="C:\Users\Sardelka\.nuget\packages\system.buffers\4.5.1\ref\net45\System.Buffers.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Core.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Data.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Drawing.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.IO.Compression.FileSystem.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Numerics.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Runtime.Serialization.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Windows.Controls.Ribbon.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Windows.Forms.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Xaml.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Xml.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Xml.Linq.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\UIAutomationClient.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\UIAutomationClientsideProviders.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\UIAutomationProvider.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\UIAutomationTypes.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\WindowsBase.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\WindowsFormsIntegration.dll" />
<ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\Facades\netstandard.dll" />
</ItemGroup>
<ItemGroup>
<Compile Include="M:\SandBox-Shared\repos\RAGECOOP\RAGECOOP-V\RageCoop.Client.Installer\obj\Debug\net48\MainWindow.g.cs" />
<Compile Include="M:\SandBox-Shared\repos\RAGECOOP\RAGECOOP-V\RageCoop.Client.Installer\obj\Debug\net48\App.g.cs" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

View File

@ -6,12 +6,11 @@ using RageCoop.Core;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Drawing; using System.Drawing;
using System.Linq; using System.IO;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -39,7 +38,7 @@ namespace RageCoop.Client
internal static ulong Ticked = 0; internal static ulong Ticked = 0;
internal static Vector3 PlayerPosition; internal static Vector3 PlayerPosition;
internal static Scripting.Resources Resources = null; internal static Scripting.Resources Resources = null;
private static List<Func<bool>> QueuedActions = new List<Func<bool>>(); private static readonly List<Func<bool>> QueuedActions = new List<Func<bool>>();
public static Worker Worker; public static Worker Worker;
/// <summary> /// <summary>
@ -47,9 +46,6 @@ namespace RageCoop.Client
/// </summary> /// </summary>
public Main() public Main()
{ {
#if DEBUG_HIGH_PING
Networking.SimulatedLatency=0.3f;
#endif
Worker = new Worker("RageCoop.Client.Main.Worker", Logger); Worker = new Worker("RageCoop.Client.Main.Worker", Logger);
try try
{ {
@ -100,7 +96,7 @@ namespace RageCoop.Client
KeyDown += OnKeyDown; KeyDown += OnKeyDown;
KeyDown += (s, e) => { Scripting.API.Events.InvokeKeyDown(s, e); }; KeyDown += (s, e) => { Scripting.API.Events.InvokeKeyDown(s, e); };
KeyUp += (s, e) => { Scripting.API.Events.InvokeKeyUp(s, e); }; KeyUp += (s, e) => { Scripting.API.Events.InvokeKeyUp(s, e); };
Aborted += (object sender, EventArgs e) => CleanUp(); Aborted += (object sender, EventArgs e) => Disconnected("Abort");
Util.NativeMemory(); Util.NativeMemory();
Counter.Restart(); Counter.Restart();
@ -111,24 +107,9 @@ namespace RageCoop.Client
private bool _lastDead; private bool _lastDead;
private void OnTick(object sender, EventArgs e) private void OnTick(object sender, EventArgs e)
{ {
/*
unsafe
{
var stationName = Function.Call<string>(Hash.GET_RADIO_STATION_NAME, Game.RadioStation);
//_GET_CURRENT_RADIO_TRACK_NAME
var currentTrack = Function.Call<int>((Hash)0x34D66BC058019CE0, stationName);
Function.Call(Hash.SET_RADIO_TRACK, "RADIO_03_HIPHOP_NEW", "ARM1_RADIO_STARTS");
return currentTrack;
var h1 = Function.Call<int>(Hash._GET_CURRENT_RADIO_STATION_HASH);
return $"{h1},{h2},{s},{s1}";
}
*/
P = Game.Player.Character; P = Game.Player.Character;
PlayerPosition = P.ReadPosition(); PlayerPosition = P.ReadPosition();
FPS = Game.FPS; FPS = Game.FPS;
// World.DrawMarker(MarkerType.DebugSphere, PedExtensions.RaycastEverything(default), default, default, new Vector3(0.2f, 0.2f, 0.2f), Color.AliceBlue);
if (Game.IsLoading) if (Game.IsLoading)
{ {
return; return;
@ -137,7 +118,6 @@ namespace RageCoop.Client
{ {
#if !NON_INTERACTIVE #if !NON_INTERACTIVE
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", $"Press ~g~{Main.Settings.MenuKey}~s~ to open the menu."); GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", $"Press ~g~{Main.Settings.MenuKey}~s~ to open the menu.");
WorldThread.Traffic(!Settings.DisableTraffic);
#endif #endif
} }
@ -161,7 +141,9 @@ namespace RageCoop.Client
} }
catch (Exception ex) catch (Exception ex)
{ {
#if DEBUG
Main.Logger.Error(ex); Main.Logger.Error(ex);
#endif
} }
if (Networking.ShowNetworkInfo) if (Networking.ShowNetworkInfo)
@ -188,7 +170,7 @@ namespace RageCoop.Client
P.Health = 1; P.Health = 1;
Game.Player.WantedLevel = 0; Game.Player.WantedLevel = 0;
Main.Logger.Debug("Player died."); Main.Logger.Debug("Player died.");
Scripting.API.Events.InvokePlayerDied(); Scripting.API.Events.InvokePlayerDied(KillMessage());
} }
GTA.UI.Screen.StopEffects(); GTA.UI.Screen.StopEffects();
} }
@ -199,7 +181,7 @@ namespace RageCoop.Client
} }
else if (P.IsDead && !_lastDead) else if (P.IsDead && !_lastDead)
{ {
Scripting.API.Events.InvokePlayerDied(); Scripting.API.Events.InvokePlayerDied(KillMessage());
} }
_lastDead = P.IsDead; _lastDead = P.IsDead;
@ -309,15 +291,49 @@ namespace RageCoop.Client
} }
} }
} }
public static void CleanUp() internal static void Connected()
{
Memory.ApplyPatches();
if (Settings.Voice && !Voice.WasInitialized())
{
Voice.Init();
}
QueueAction(() =>
{ {
MainChat.Clear();
Voice.ClearAll();
EntityPool.Cleanup();
PlayerList.Cleanup();
LocalPlayerID=default;
WorldThread.Traffic(!Settings.DisableTraffic); WorldThread.Traffic(!Settings.DisableTraffic);
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, true);
CoopMenu.ConnectedMenuSetting();
MainChat.Init();
GTA.UI.Notification.Show("~g~Connected!");
});
Logger.Info(">> Connected <<");
}
public static void Disconnected(string reason)
{
Logger.Info($">> Disconnected << reason: {reason}");
QueueAction(() =>
{
if (MainChat.Focused)
{
MainChat.Focused = false;
}
PlayerList.Cleanup();
MainChat.Clear();
EntityPool.Cleanup();
WorldThread.Traffic(true);
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, false); Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, false);
CoopMenu.DisconnectedMenuSetting();
if (reason != "Abort")
GTA.UI.Notification.Show("~r~Disconnected: " + reason);
LocalPlayerID = default;
});
Memory.RestorePatches();
DownloadManager.Cleanup();
Voice.ClearAll();
Resources.Unload();
} }
private static void DoQueuedActions() private static void DoQueuedActions()
{ {
@ -334,7 +350,9 @@ namespace RageCoop.Client
} }
catch (Exception ex) catch (Exception ex)
{ {
#if DEBUG
Logger.Error(ex); Logger.Error(ex);
#endif
QueuedActions.Remove(action); QueuedActions.Remove(action);
} }
} }
@ -375,5 +393,16 @@ namespace RageCoop.Client
QueueAction(a); QueueAction(a);
}); });
} }
private string KillMessage()
{
if (P.Killer != null)
{
var killer = EntityPool.GetPedByHandle(P.Killer.Handle);
if (killer != null && killer.ID == killer.Owner.ID)
return $"~h~{PlayerList.GetPlayer(LocalPlayerID).Username}~h~ was killed by ~h~{killer.Owner.Username}~h~ ({P.CauseOfDeath})";
}
return $"~h~{PlayerList.GetPlayer(LocalPlayerID).Username}~h~ died";
}
} }
} }

View File

@ -1,4 +1,5 @@
using GTA; using GTA;
using GTA.Native;
using LemonUI; using LemonUI;
using LemonUI.Menus; using LemonUI.Menus;
using LemonUI.Scaleform; using LemonUI.Scaleform;
@ -49,7 +50,7 @@ namespace RageCoop.Client.Menus
{ {
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0); Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
_usernameItem.Activated += UsernameActivated; _usernameItem.Activated += UsernameActivated;
_passwordItem.Activated += _passwordActivated; _passwordItem.Activated += _passwordActivated;
@ -66,17 +67,18 @@ namespace RageCoop.Client.Menus
Menu.AddSubMenu(SettingsMenu.Menu); Menu.AddSubMenu(SettingsMenu.Menu);
Menu.AddSubMenu(DevToolMenu.Menu); Menu.AddSubMenu(DevToolMenu.Menu);
#if DEBUG
Menu.AddSubMenu(DebugMenu.Menu); Menu.AddSubMenu(DebugMenu.Menu);
Menu.AddSubMenu(UpdateMenu.Menu); #endif
MenuPool.Add(Menu); MenuPool.Add(Menu);
MenuPool.Add(SettingsMenu.Menu); MenuPool.Add(SettingsMenu.Menu);
MenuPool.Add(DevToolMenu.Menu); MenuPool.Add(DevToolMenu.Menu);
#if DEBUG
MenuPool.Add(DebugMenu.Menu); MenuPool.Add(DebugMenu.Menu);
MenuPool.Add(DebugMenu.DiagnosticMenu); MenuPool.Add(DebugMenu.DiagnosticMenu);
#endif
MenuPool.Add(ServersMenu.Menu); MenuPool.Add(ServersMenu.Menu);
MenuPool.Add(UpdateMenu.Menu);
MenuPool.Add(PopUp); MenuPool.Add(PopUp);
Menu.Add(_aboutItem); Menu.Add(_aboutItem);
@ -96,6 +98,16 @@ namespace RageCoop.Client.Menus
{ {
Game.DisableAllControlsThisFrame(); Game.DisableAllControlsThisFrame();
MenuPool.Process(); MenuPool.Process();
var scaleform = new Scaleform("instructional_buttons");
scaleform.CallFunction("CLEAR_ALL");
scaleform.CallFunction("TOGGLE_MOUSE_BUTTONS", 0);
scaleform.CallFunction("CREATE_CONTAINER");
scaleform.CallFunction("SET_DATA_SLOT", 0, Function.Call<string>((Hash)0x0499D7B09FC9B407, 2, (int)Control.FrontendAccept, 0), "Continue");
scaleform.CallFunction("SET_DATA_SLOT", 1, Function.Call<string>((Hash)0x0499D7B09FC9B407, 2, (int)Control.FrontendCancel, 0), "Cancel");
scaleform.CallFunction("DRAW_INSTRUCTIONAL_BUTTONS", -1);
scaleform.Render2D();
if (Game.IsControlJustPressed(Control.FrontendAccept)) if (Game.IsControlJustPressed(Control.FrontendAccept))
{ {
PopUp.Visible = false; PopUp.Visible = false;
@ -107,6 +119,8 @@ namespace RageCoop.Client.Menus
return false; return false;
} }
Script.Yield(); Script.Yield();
Game.DisableAllControlsThisFrame();
} }
} }
public static void UsernameActivated(object a, System.EventArgs b) public static void UsernameActivated(object a, System.EventArgs b)

View File

@ -1,7 +1,8 @@
using GTA; #if DEBUG
using GTA;
using LemonUI.Menus; using LemonUI.Menus;
using System.Drawing;
using System; using System;
using System.Drawing;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -24,7 +25,7 @@ namespace RageCoop.Client
static DebugMenu() static DebugMenu()
{ {
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0); Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
DiagnosticMenu.Opening += (sender, e) => DiagnosticMenu.Opening += (sender, e) =>
@ -56,3 +57,4 @@ namespace RageCoop.Client
} }
} }
#endif

View File

@ -12,9 +12,9 @@ namespace RageCoop.Client
UseMouse = false, UseMouse = false,
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
}; };
private static NativeCheckboxItem enableItem = new NativeCheckboxItem("Enable"); private static readonly NativeCheckboxItem enableItem = new NativeCheckboxItem("Enable");
private static NativeCheckboxItem enableSecondaryItem = new NativeCheckboxItem("Secondary", "Enable if this vehicle have two muzzles"); private static readonly NativeCheckboxItem enableSecondaryItem = new NativeCheckboxItem("Secondary", "Enable if this vehicle have two muzzles");
public static NativeItem boneIndexItem = new NativeItem("Current bone index"); public static NativeItem boneIndexItem = new NativeItem("Current bone index");
public static NativeItem secondaryBoneIndexItem = new NativeItem("Secondary bone index"); public static NativeItem secondaryBoneIndexItem = new NativeItem("Secondary bone index");
public static NativeItem clipboardItem = new NativeItem("Copy to clipboard"); public static NativeItem clipboardItem = new NativeItem("Copy to clipboard");
@ -22,7 +22,7 @@ namespace RageCoop.Client
static DevToolMenu() static DevToolMenu()
{ {
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0); Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
enableItem.Activated += enableItem_Activated; enableItem.Activated += enableItem_Activated;
enableItem.Checked = false; enableItem.Checked = false;

View File

@ -1,12 +1,12 @@
using LemonUI.Menus; using GTA.UI;
using LemonUI.Menus;
using Newtonsoft.Json; using Newtonsoft.Json;
using RageCoop.Core;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using RageCoop.Core;
using GTA.UI;
namespace RageCoop.Client.Menus namespace RageCoop.Client.Menus
{ {
@ -30,7 +30,7 @@ namespace RageCoop.Client.Menus
static ServersMenu() static ServersMenu()
{ {
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0); Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
Menu.Opening += (object sender, System.ComponentModel.CancelEventArgs e) => Menu.Opening += (object sender, System.ComponentModel.CancelEventArgs e) =>
{ {
@ -76,7 +76,7 @@ namespace RageCoop.Client.Menus
foreach (ServerInfo server in serverList) foreach (ServerInfo server in serverList)
{ {
string address = $"{server.address}:{server.port}"; string address = $"{server.address}:{server.port}";
NativeItem tmpItem = new NativeItem($"[{server.country}] {server.name}", $"~b~{address}~s~~n~~g~Version {server.version}.x~s~") { AltTitle = $"[{server.players}/{server.maxPlayers}]" }; NativeItem tmpItem = new NativeItem($"[{server.country}] {server.name}", $"~b~{address}~s~~n~~g~Version {server.version}~s~") { AltTitle = $"[{server.players}/{server.maxPlayers}]" };
tmpItem.Activated += (object sender, EventArgs e) => tmpItem.Activated += (object sender, EventArgs e) =>
{ {
try try

View File

@ -17,16 +17,18 @@ namespace RageCoop.Client.Menus
private static readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.Settings.DisableTraffic); private static readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.Settings.DisableTraffic);
private static readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu); private static readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu);
private static readonly NativeCheckboxItem _disablePauseAlt = new NativeCheckboxItem("Disable Alternate Pause", "Don't freeze game time when Esc pressed", Main.Settings.DisableAlternatePause); private static readonly NativeCheckboxItem _disablePauseAlt = new NativeCheckboxItem("Disable Alternate Pause", "Don't freeze game time when Esc pressed", Main.Settings.DisableAlternatePause);
private static readonly NativeCheckboxItem _showBlip = new NativeCheckboxItem("Show player blip", "Show other player's blip on map", Main.Settings.ShowPlayerBlip);
private static readonly NativeCheckboxItem _showNametag = new NativeCheckboxItem("Show player nametag", "Show other player's nametag on your screen", Main.Settings.ShowPlayerNameTag);
private static readonly NativeCheckboxItem _disableVoice = new NativeCheckboxItem("Enable voice", "Check your GTA:V settings to find the right key on your keyboard for PushToTalk and talk to your friends", Main.Settings.Voice); private static readonly NativeCheckboxItem _disableVoice = new NativeCheckboxItem("Enable voice", "Check your GTA:V settings to find the right key on your keyboard for PushToTalk and talk to your friends", Main.Settings.Voice);
private static NativeItem _menuKey = new NativeItem("Menu Key", "The key to open menu", Main.Settings.MenuKey.ToString()); private static readonly NativeItem _menuKey = new NativeItem("Menu Key", "The key to open menu", Main.Settings.MenuKey.ToString());
private static NativeItem _passengerKey = new NativeItem("Passenger Key", "The key to enter a vehicle as passenger", Main.Settings.PassengerKey.ToString()); private static readonly NativeItem _passengerKey = new NativeItem("Passenger Key", "The key to enter a vehicle as passenger", Main.Settings.PassengerKey.ToString());
private static NativeItem _vehicleSoftLimit = new NativeItem("Vehicle limit (soft)", "The game won't spawn more NPC traffic if the limit is exceeded. \n-1 for unlimited (not recommended).", Main.Settings.WorldVehicleSoftLimit.ToString()); private static readonly NativeItem _vehicleSoftLimit = new NativeItem("Vehicle limit (soft)", "The game won't spawn more NPC traffic if the limit is exceeded. \n-1 for unlimited (not recommended).", Main.Settings.WorldVehicleSoftLimit.ToString());
static SettingsMenu() static SettingsMenu()
{ {
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0); Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
_disableTrafficItem.CheckboxChanged += DisableTrafficCheckboxChanged; _disableTrafficItem.CheckboxChanged += DisableTrafficCheckboxChanged;
_disablePauseAlt.CheckboxChanged += DisablePauseAltCheckboxChanged; _disablePauseAlt.CheckboxChanged += DisablePauseAltCheckboxChanged;
@ -35,6 +37,16 @@ namespace RageCoop.Client.Menus
_menuKey.Activated += ChaneMenuKey; _menuKey.Activated += ChaneMenuKey;
_passengerKey.Activated += ChangePassengerKey; _passengerKey.Activated += ChangePassengerKey;
_vehicleSoftLimit.Activated += VehicleSoftLimitActivated; _vehicleSoftLimit.Activated += VehicleSoftLimitActivated;
_showBlip.Activated += (s, e) =>
{
Main.Settings.ShowPlayerBlip = _showBlip.Checked;
Util.SaveSettings();
};
_showNametag.Activated += (s, e) =>
{
Main.Settings.ShowPlayerNameTag = _showNametag.Checked;
Util.SaveSettings();
};
Menu.Add(_disableTrafficItem); Menu.Add(_disableTrafficItem);
Menu.Add(_disablePauseAlt); Menu.Add(_disablePauseAlt);
@ -43,6 +55,8 @@ namespace RageCoop.Client.Menus
Menu.Add(_menuKey); Menu.Add(_menuKey);
Menu.Add(_passengerKey); Menu.Add(_passengerKey);
Menu.Add(_vehicleSoftLimit); Menu.Add(_vehicleSoftLimit);
Menu.Add(_showBlip);
Menu.Add(_showNametag);
} }
private static void DisableVoiceCheckboxChanged(object sender, EventArgs e) private static void DisableVoiceCheckboxChanged(object sender, EventArgs e)
@ -53,7 +67,9 @@ namespace RageCoop.Client.Menus
{ {
Voice.Init(); Voice.Init();
} }
} else { }
else
{
Voice.ClearAll(); Voice.ClearAll();
} }

View File

@ -1,105 +0,0 @@
using ICSharpCode.SharpZipLib.Zip;
using LemonUI.Menus;
using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace RageCoop.Client.Menus
{
internal class UpdateMenu
{
public static bool IsUpdating { get; private set; } = false;
private static NativeItem _updatingItem = new NativeItem("Updating...");
private static NativeItem _downloadItem = new NativeItem("Download", "Download and update to latest nightly");
private static string _downloadPath = Path.Combine(Main.Settings.DataDirectory, "RageCoop.Client.zip");
public static NativeMenu Menu = new NativeMenu("Update", "Update", "Download and install latest nightly build from GitHub")
{
UseMouse = false,
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
static UpdateMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0);
Menu.Opening+=Opening;
_downloadItem.Activated+=StartUpdate;
}
private static void StartUpdate(object sender, EventArgs e)
{
IsUpdating=true;
Menu.Clear();
Menu.Add(_updatingItem);
Task.Run(() =>
{
try
{
if (File.Exists(_downloadPath)) { File.Delete(_downloadPath); }
WebClient client = new WebClient();
// TLS only
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
client.DownloadProgressChanged += (s, e1) => { Main.QueueAction(() => { _updatingItem.AltTitle=$"{e1.ProgressPercentage}%"; }); };
client.DownloadFileCompleted +=(s, e2) => { Install(); };
client.DownloadFileAsync(new Uri("https://github.com/RAGECOOP/RAGECOOP-V/releases/download/nightly/RageCoop.Client.zip"), _downloadPath);
}
catch (Exception ex)
{
Main.Logger.Error(ex);
}
});
}
private static void Install()
{
try
{
Main.QueueAction(() =>
{
_updatingItem.AltTitle="Installing...";
});
Directory.CreateDirectory(@"Scripts\RageCoop");
foreach(var f in Directory.GetFiles(@"Scripts\RageCoop", "*.dll", SearchOption.AllDirectories))
{
try { File.Delete(f); }
catch { }
}
new FastZip().ExtractZip(_downloadPath, "Scripts", FastZip.Overwrite.Always, null, null, null, true);
try { File.Delete(_downloadPath); } catch { }
try { File.Delete(Path.Combine("Scripts","RageCoop.Client.Installer.exe")); } catch { }
Main.QueueAction(() =>
{
Util.Reload();
IsUpdating=false;
});
}
catch (Exception ex)
{
Main.Logger.Error(ex);
}
}
private static void Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
Menu.Clear();
if (Networking.IsOnServer)
{
Menu.Add(new NativeItem("Disconnect from the server first"));
}
else if (IsUpdating)
{
Menu.Add(_updatingItem);
}
else
{
Menu.Add(_downloadItem);
}
}
}
}

View File

@ -16,7 +16,7 @@ namespace RageCoop.Client
private bool CurrentFocused { get; set; } private bool CurrentFocused { get; set; }
public bool Focused public bool Focused
{ {
get { return CurrentFocused; } get => CurrentFocused;
set set
{ {
if (value && Hidden) if (value && Hidden)
@ -35,7 +35,7 @@ namespace RageCoop.Client
private bool CurrentHidden { get; set; } private bool CurrentHidden { get; set; }
private bool Hidden private bool Hidden
{ {
get { return CurrentHidden; } get => CurrentHidden;
set set
{ {
if (value) if (value)

View File

@ -122,8 +122,7 @@ namespace RageCoop.Client
{ {
lock (InProgressDownloads) lock (InProgressDownloads)
{ {
DownloadFile file; if (InProgressDownloads.TryGetValue(id, out DownloadFile file))
if (InProgressDownloads.TryGetValue(id, out file))
{ {
file.Stream.Write(chunk, 0, chunk.Length); file.Stream.Write(chunk, 0, chunk.Length);
@ -137,9 +136,8 @@ namespace RageCoop.Client
public static void Complete(int id) public static void Complete(int id)
{ {
DownloadFile f;
if (InProgressDownloads.TryGetValue(id, out f)) if (InProgressDownloads.TryGetValue(id, out DownloadFile f))
{ {
InProgressDownloads.Remove(id); InProgressDownloads.Remove(id);
f.Dispose(); f.Dispose();

View File

@ -1,12 +1,10 @@
using System; using Lidgren.Network;
using RageCoop.Core;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using RageCoop.Core;
using Lidgren.Network;
using System.Net; using System.Net;
using System.Timers;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -29,7 +27,7 @@ namespace RageCoop.Client
{ {
if (p.InternalEndPoint != null && p.ExternalEndPoint != null && (p.Connection == null || p.Connection.Status == NetConnectionStatus.Disconnected)) if (p.InternalEndPoint != null && p.ExternalEndPoint != null && (p.Connection == null || p.Connection.Status == NetConnectionStatus.Disconnected))
{ {
Main.Logger.Trace($"Sending HolePunch message to {p.InternalEndPoint},{p.ExternalEndPoint}. {p.Username}:{p.PedID}"); Main.Logger.Trace($"Sending HolePunch message to {p.InternalEndPoint},{p.ExternalEndPoint}. {p.Username}:{p.ID}");
var msg = Networking.Peer.CreateMessage(); var msg = Networking.Peer.CreateMessage();
new Packets.HolePunch new Packets.HolePunch
{ {
@ -69,7 +67,7 @@ namespace RageCoop.Client
puncher.HolePunchStatus = (byte)(p.Status + 1); puncher.HolePunchStatus = (byte)(p.Status + 1);
if (p.Status >= 3) if (p.Status >= 3)
{ {
Main.Logger.Debug("HolePunch sucess: "+from+", "+puncher.PedID); Main.Logger.Debug("HolePunch sucess: " + from + ", " + puncher.ID);
if (puncher.ConnectWhenPunched && (puncher.Connection == null || puncher.Connection.Status == NetConnectionStatus.Disconnected)) if (puncher.ConnectWhenPunched && (puncher.Connection == null || puncher.Connection.Status == NetConnectionStatus.Disconnected))
{ {
Main.Logger.Debug("Connecting to peer: " + from); Main.Logger.Debug("Connecting to peer: " + from);

View File

@ -1,12 +1,12 @@
using Lidgren.Network; using GTA.UI;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GTA.UI;
using System.Net;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -17,8 +17,8 @@ namespace RageCoop.Client
public static bool ShowNetworkInfo = false; public static bool ShowNetworkInfo = false;
public static Security Security; public static Security Security;
public static NetConnection ServerConnection; public static NetConnection ServerConnection;
private static readonly Dictionary<int, Action<PacketType, byte[]>> PendingResponses = new Dictionary<int, Action<PacketType, byte[]>>(); private static readonly Dictionary<int, Action<PacketType, NetIncomingMessage>> PendingResponses = new Dictionary<int, Action<PacketType, NetIncomingMessage>>();
internal static readonly Dictionary<PacketType, Func<byte[], Packet>> RequestHandlers = new Dictionary<PacketType, Func<byte[], Packet>>(); internal static readonly Dictionary<PacketType, Func<NetIncomingMessage, Packet>> RequestHandlers = new Dictionary<PacketType, Func<NetIncomingMessage, Packet>>();
internal static float SimulatedLatency = 0; internal static float SimulatedLatency = 0;
public static bool IsConnecting { get; private set; } public static bool IsConnecting { get; private set; }
public static IPEndPoint _targetServerEP; public static IPEndPoint _targetServerEP;
@ -30,15 +30,16 @@ namespace RageCoop.Client
public static void ToggleConnection(string address, string username = null, string password = null, PublicKey publicKey = null) public static void ToggleConnection(string address, string username = null, string password = null, PublicKey publicKey = null)
{ {
Menus.CoopMenu.Menu.Visible = false; Menus.CoopMenu.Menu.Visible = false;
Peer?.Shutdown("Bye"); if (IsConnecting)
if (IsOnServer)
{ {
// ?
}
else if (IsConnecting) {
_publicKeyReceived.Set(); _publicKeyReceived.Set();
IsConnecting = false; IsConnecting = false;
Notification.Show("Connection has been canceled"); Main.QueueAction(() => Notification.Show("Connection has been canceled"));
Peer?.Shutdown("Bye");
}
else if (IsOnServer)
{
Peer?.Shutdown("Bye");
} }
else else
{ {
@ -52,13 +53,14 @@ namespace RageCoop.Client
NetPeerConfiguration config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0") NetPeerConfiguration config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0")
{ {
AutoFlushSendQueue = false, AutoFlushSendQueue = false,
SimulatedMinimumLatency =SimulatedLatency,
SimulatedRandomLatency=0,
AcceptIncomingConnections = true, AcceptIncomingConnections = true,
MaximumConnections = 32, MaximumConnections = 32,
PingInterval = 5 PingInterval = 5
}; };
#if DEBUG
config.SimulatedMinimumLatency = SimulatedLatency;
config.SimulatedRandomLatency = 0;
#endif
config.EnableMessageType(NetIncomingMessageType.UnconnectedData); config.EnableMessageType(NetIncomingMessageType.UnconnectedData);
config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess); config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);
@ -88,24 +90,33 @@ namespace RageCoop.Client
try try
{ {
_targetServerEP = CoreUtils.StringToEndPoint(address); _targetServerEP = CoreUtils.StringToEndPoint(address);
// Ensure static constructor invocation
DownloadManager.Cleanup(); DownloadManager.Cleanup();
Peer = new CoopPeer(config); Peer = new CoopPeer(config);
Peer.OnMessageReceived += (s, m) => Peer.OnMessageReceived += (s, m) =>
{ {
try { ProcessMessage(m); } try { ProcessMessage(m); }
catch (Exception ex) { Main.Logger.Error(ex); } catch (Exception ex)
{
#if DEBUG
Main.Logger.Error(ex);
#endif
}
}; };
Main.QueueAction(() => { Notification.Show($"~y~Trying to connect..."); }); Main.QueueAction(() => { Notification.Show($"~y~Trying to connect..."); });
Menus.CoopMenu._serverConnectItem.Enabled = false; Menus.CoopMenu._serverConnectItem.Enabled = false;
Security.Regen(); Security.Regen();
if(publicKey==null){ if (publicKey == null)
{
if (!GetServerPublicKey(ip[0], int.Parse(ip[1]))) if (!GetServerPublicKey(ip[0], int.Parse(ip[1])))
{ {
Menus.CoopMenu._serverConnectItem.Enabled = true; Menus.CoopMenu._serverConnectItem.Enabled = true;
throw new TimeoutException("Failed to retrive server's public key"); throw new TimeoutException("Failed to retrive server's public key");
} }
} }
else{ else
{
Security.SetServerPublicKey(publicKey.Modulus, publicKey.Exponent); Security.SetServerPublicKey(publicKey.Modulus, publicKey.Exponent);
} }
@ -141,7 +152,7 @@ namespace RageCoop.Client
{ {
var p = new Player var p = new Player
{ {
PedID = packet.PedID, ID = packet.PedID,
Username = packet.Username, Username = packet.Username,
}; };
PlayerList.SetPlayer(packet.PedID, packet.Username); PlayerList.SetPlayer(packet.PedID, packet.Username);
@ -155,7 +166,8 @@ namespace RageCoop.Client
var player = PlayerList.GetPlayer(packet.PedID); var player = PlayerList.GetPlayer(packet.PedID);
if (player == null) { return; } if (player == null) { return; }
PlayerList.RemovePlayer(packet.PedID); PlayerList.RemovePlayer(packet.PedID);
Main.QueueAction(() => { Main.QueueAction(() =>
{
EntityPool.RemoveAllFromPlayer(packet.PedID); EntityPool.RemoveAllFromPlayer(packet.PedID);
GTA.UI.Notification.Show($"~h~{player.Username}~h~ left."); GTA.UI.Notification.Show($"~h~{player.Username}~h~ left.");
}); });

View File

@ -3,9 +3,7 @@ using Lidgren.Network;
using RageCoop.Client.Menus; using RageCoop.Client.Menus;
using RageCoop.Core; using RageCoop.Core;
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using GTA.Native;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -15,7 +13,7 @@ namespace RageCoop.Client
/// <summary> /// <summary>
/// Reduce GC pressure by reusing frequently used packets /// Reduce GC pressure by reusing frequently used packets
/// </summary> /// </summary>
static class ReceivedPackets private static class ReceivedPackets
{ {
public static Packets.PedSync PedPacket = new Packets.PedSync(); public static Packets.PedSync PedPacket = new Packets.PedSync();
public static Packets.VehicleSync VehicelPacket = new Packets.VehicleSync(); public static Packets.VehicleSync VehicelPacket = new Packets.VehicleSync();
@ -25,7 +23,7 @@ namespace RageCoop.Client
/// <summary> /// <summary>
/// Used to reslove entity handle in a <see cref="Packets.CustomEvent"/> /// Used to reslove entity handle in a <see cref="Packets.CustomEvent"/>
/// </summary> /// </summary>
private static readonly Func<byte, BitReader, object> _resolveHandle = (t, reader) => private static readonly Func<byte, NetIncomingMessage, object> _resolveHandle = (t, reader) =>
{ {
switch (t) switch (t)
{ {
@ -42,10 +40,11 @@ namespace RageCoop.Client
} }
}; };
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false); private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
private static bool _recycle;
public static void ProcessMessage(NetIncomingMessage message) public static void ProcessMessage(NetIncomingMessage message)
{ {
if (message == null) { return; } if (message == null) { return; }
_recycle = true;
switch (message.MessageType) switch (message.MessageType)
{ {
case NetIncomingMessageType.StatusChanged: case NetIncomingMessageType.StatusChanged:
@ -62,32 +61,18 @@ namespace RageCoop.Client
case NetConnectionStatus.Connected: case NetConnectionStatus.Connected:
if (message.SenderConnection == ServerConnection) if (message.SenderConnection == ServerConnection)
{ {
Memory.ApplyPatches();
var response = message.SenderConnection.RemoteHailMessage; var response = message.SenderConnection.RemoteHailMessage;
if ((PacketType)response.ReadByte() != PacketType.HandshakeSuccess) if ((PacketType)response.ReadByte() != PacketType.HandshakeSuccess)
{ {
throw new Exception("Invalid handshake response!"); throw new Exception("Invalid handshake response!");
} }
var p = new Packets.HandshakeSuccess(); var p = new Packets.HandshakeSuccess();
p.Deserialize(response.ReadBytes(response.ReadInt32())); p.Deserialize(response);
foreach (var player in p.Players) foreach (var player in p.Players)
{ {
PlayerList.SetPlayer(player.ID, player.Username); PlayerList.SetPlayer(player.ID, player.Username);
} }
Main.QueueAction(() => Main.Connected();
{
WorldThread.Traffic(!Main.Settings.DisableTraffic);
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, true);
CoopMenu.ConnectedMenuSetting();
Main.MainChat.Init();
if (Main.Settings.Voice && !Voice.WasInitialized())
{
Voice.Init();
}
GTA.UI.Notification.Show("~g~Connected!");
});
Main.Logger.Info(">> Connected <<");
} }
else else
{ {
@ -110,19 +95,7 @@ namespace RageCoop.Client
case NetConnectionStatus.Disconnected: case NetConnectionStatus.Disconnected:
if (message.SenderConnection == ServerConnection) if (message.SenderConnection == ServerConnection)
{ {
Memory.RestorePatches(); Main.Disconnected(reason);
DownloadManager.Cleanup();
if (Main.MainChat.Focused)
{
Main.MainChat.Focused = false;
}
Main.QueueAction(() => Main.CleanUp());
CoopMenu.DisconnectedMenuSetting();
Main.Logger.Info($">> Disconnected << reason: {reason}");
Main.QueueAction(() => GTA.UI.Notification.Show("~r~Disconnected: " + reason));
Main.Resources.Unload();
} }
break; break;
} }
@ -142,7 +115,7 @@ namespace RageCoop.Client
int id = message.ReadInt32(); int id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback)) if (PendingResponses.TryGetValue(id, out var callback))
{ {
callback((PacketType)message.ReadByte(), message.ReadBytes(message.ReadInt32())); callback((PacketType)message.ReadByte(), message);
PendingResponses.Remove(id); PendingResponses.Remove(id);
} }
break; break;
@ -151,57 +124,60 @@ namespace RageCoop.Client
{ {
int id = message.ReadInt32(); int id = message.ReadInt32();
var realType = (PacketType)message.ReadByte(); var realType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
if (RequestHandlers.TryGetValue(realType, out var handler)) if (RequestHandlers.TryGetValue(realType, out var handler))
{ {
var response = Peer.CreateMessage(); var response = Peer.CreateMessage();
response.Write((byte)PacketType.Response); response.Write((byte)PacketType.Response);
response.Write(id); response.Write(id);
handler(message.ReadBytes(len)).Pack(response); handler(message).Pack(response);
Peer.SendMessage(response, ServerConnection, NetDeliveryMethod.ReliableOrdered, message.SequenceChannel); Peer.SendMessage(response, ServerConnection, NetDeliveryMethod.ReliableOrdered, message.SequenceChannel);
Peer.FlushSendQueue(); Peer.FlushSendQueue();
} }
else
{
Main.Logger.Debug("Did not find a request handler of type: " + realType);
}
break; break;
} }
default: default:
{ {
byte[] data = message.ReadBytes(message.ReadInt32());
HandlePacket(packetType, data,message.SenderConnection); HandlePacket(packetType, message, message.SenderConnection, ref _recycle);
break; break;
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
#if DEBUG
Main.QueueAction(() => Main.QueueAction(() =>
{ {
GTA.UI.Notification.Show("~r~~h~Packet Error"); GTA.UI.Notification.Show($"~r~~h~Packet Error {ex.Message}");
return true; return true;
}); });
Main.Logger.Error($"[{packetType}] {ex.Message}"); Main.Logger.Error($"[{packetType}] {ex.Message}");
Main.Logger.Error(ex); Main.Logger.Error(ex);
Peer.Shutdown($"Packet Error [{packetType}]"); Peer.Shutdown($"Packet Error [{packetType}]");
#endif
_recycle = false;
} }
break; break;
} }
case NetIncomingMessageType.UnconnectedData: case NetIncomingMessageType.UnconnectedData:
{ {
var packetType = (PacketType)message.ReadByte(); var packetType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
switch (packetType) switch (packetType)
{ {
case PacketType.HolePunch: case PacketType.HolePunch:
{ {
HolePunch.Punched(data.GetPacket<Packets.HolePunch>(), message.SenderEndPoint); HolePunch.Punched(message.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
break; break;
} }
case PacketType.PublicKeyResponse: case PacketType.PublicKeyResponse:
{ {
if (message.SenderEndPoint.ToString() != _targetServerEP.ToString() || !IsConnecting) { break; } if (message.SenderEndPoint.ToString() != _targetServerEP.ToString() || !IsConnecting) { break; }
var packet = data.GetPacket<Packets.PublicKeyResponse>(); var packet = message.GetPacket<Packets.PublicKeyResponse>();
Security.SetServerPublicKey(packet.Modulus, packet.Exponent); Security.SetServerPublicKey(packet.Modulus, packet.Exponent);
_publicKeyReceived.Set(); _publicKeyReceived.Set();
break; break;
@ -218,41 +194,42 @@ namespace RageCoop.Client
default: default:
break; break;
} }
if (_recycle)
{
Peer.Recycle(message); Peer.Recycle(message);
} }
private static void HandlePacket(PacketType packetType, byte[] data, NetConnection senderConnection) }
private static void HandlePacket(PacketType packetType, NetIncomingMessage msg, NetConnection senderConnection, ref bool recycle)
{ {
switch (packetType) switch (packetType)
{ {
case PacketType.HolePunchInit: case PacketType.HolePunchInit:
HolePunch.Add(data.GetPacket<Packets.HolePunchInit>()); HolePunch.Add(msg.GetPacket<Packets.HolePunchInit>());
break; break;
case PacketType.PlayerConnect: case PacketType.PlayerConnect:
PlayerConnect(data.GetPacket<Packets.PlayerConnect>()); PlayerConnect(msg.GetPacket<Packets.PlayerConnect>());
break; break;
case PacketType.PlayerDisconnect: case PacketType.PlayerDisconnect:
PlayerDisconnect(data.GetPacket<Packets.PlayerDisconnect>()); PlayerDisconnect(msg.GetPacket<Packets.PlayerDisconnect>());
break; break;
case PacketType.PlayerInfoUpdate: case PacketType.PlayerInfoUpdate:
PlayerList.UpdatePlayer(data.GetPacket<Packets.PlayerInfoUpdate>()); PlayerList.UpdatePlayer(msg.GetPacket<Packets.PlayerInfoUpdate>());
break; break;
case PacketType.VehicleSync: case PacketType.VehicleSync:
ReceivedPackets.VehicelPacket.Deserialize(data); ReceivedPackets.VehicelPacket.Deserialize(msg);
VehicleSync(ReceivedPackets.VehicelPacket); VehicleSync(ReceivedPackets.VehicelPacket);
break; break;
case PacketType.PedSync: case PacketType.PedSync:
ReceivedPackets.PedPacket.Deserialize(data); ReceivedPackets.PedPacket.Deserialize(msg);
PedSync(ReceivedPackets.PedPacket); PedSync(ReceivedPackets.PedPacket);
break; break;
case PacketType.ProjectileSync: case PacketType.ProjectileSync:
ReceivedPackets.ProjectilePacket.Deserialize(data); ReceivedPackets.ProjectilePacket.Deserialize(msg);
ProjectileSync(ReceivedPackets.ProjectilePacket); ProjectileSync(ReceivedPackets.ProjectilePacket);
break; break;
@ -260,7 +237,7 @@ namespace RageCoop.Client
{ {
Packets.ChatMessage packet = new Packets.ChatMessage((b) => Security.Decrypt(b)); Packets.ChatMessage packet = new Packets.ChatMessage((b) => Security.Decrypt(b));
packet.Deserialize(data); packet.Deserialize(msg);
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; }); Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; });
} }
@ -271,7 +248,7 @@ namespace RageCoop.Client
if (Main.Settings.Voice) if (Main.Settings.Voice)
{ {
Packets.Voice packet = new Packets.Voice(); Packets.Voice packet = new Packets.Voice();
packet.Deserialize(data); packet.Deserialize(msg);
SyncedPed player = EntityPool.GetPedByID(packet.ID); SyncedPed player = EntityPool.GetPedByID(packet.ID);
@ -286,18 +263,20 @@ namespace RageCoop.Client
case PacketType.CustomEvent: case PacketType.CustomEvent:
{ {
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle); Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
packet.Deserialize(data); packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet); Scripting.API.Events.InvokeCustomEventReceived(packet);
} }
break; break;
case PacketType.CustomEventQueued: case PacketType.CustomEventQueued:
{ {
recycle = false;
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle); Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
Main.QueueAction(() => Main.QueueAction(() =>
{ {
packet.Deserialize(data); packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet); Scripting.API.Events.InvokeCustomEventReceived(packet);
Peer.Recycle(msg);
}); });
} }
break; break;
@ -305,7 +284,7 @@ namespace RageCoop.Client
case PacketType.FileTransferChunk: case PacketType.FileTransferChunk:
{ {
Packets.FileTransferChunk packet = new Packets.FileTransferChunk(); Packets.FileTransferChunk packet = new Packets.FileTransferChunk();
packet.Deserialize(data); packet.Deserialize(msg);
DownloadManager.Write(packet.ID, packet.FileChunk); DownloadManager.Write(packet.ID, packet.FileChunk);
} }
break; break;
@ -313,8 +292,9 @@ namespace RageCoop.Client
default: default:
if (packetType.IsSyncEvent()) if (packetType.IsSyncEvent())
{ {
recycle = false;
// Dispatch to script thread // Dispatch to script thread
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, data); return true; }); Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); return true; });
} }
break; break;
} }
@ -326,7 +306,9 @@ namespace RageCoop.Client
if (c == null) if (c == null)
{ {
// Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}"); // Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
if (EntityPool.allPeds.Length < Main.Settings.GlobalPedSoftLimit || PlayerList.Players.ContainsKey(packet.ID))
EntityPool.ThreadSafe.Add(c = new SyncedPed(packet.ID)); EntityPool.ThreadSafe.Add(c = new SyncedPed(packet.ID));
else return;
} }
PedDataFlags flags = packet.Flags; PedDataFlags flags = packet.Flags;
c.ID = packet.ID; c.ID = packet.ID;
@ -374,7 +356,9 @@ namespace RageCoop.Client
SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID); SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID);
if (v == null) if (v == null)
{ {
if (EntityPool.allVehicles.Length < Main.Settings.GlobalVehicleSoftLimit)
EntityPool.ThreadSafe.Add(v = new SyncedVehicle(packet.ID)); EntityPool.ThreadSafe.Add(v = new SyncedVehicle(packet.ID));
else return;
} }
if (v.IsLocal) { return; } if (v.IsLocal) { return; }
v.ID = packet.ID; v.ID = packet.ID;
@ -414,7 +398,9 @@ namespace RageCoop.Client
{ {
if (packet.Flags.HasProjDataFlag(ProjectileDataFlags.Exploded)) { return; } if (packet.Flags.HasProjDataFlag(ProjectileDataFlags.Exploded)) { return; }
// Main.Logger.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}"); // Main.Logger.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}");
if (EntityPool.allProjectiles.Length < Main.Settings.GlobalProjectileSoftLimit)
EntityPool.ThreadSafe.Add(p = new SyncedProjectile(packet.ID)); EntityPool.ThreadSafe.Add(p = new SyncedProjectile(packet.ID));
else return;
} }
p.Flags = packet.Flags; p.Flags = packet.Flags;
p.Position = packet.Position; p.Position = packet.Position;
@ -424,6 +410,7 @@ namespace RageCoop.Client
p.Shooter = packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle) ? p.Shooter = packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle) ?
(SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID) : EntityPool.GetPedByID(packet.ShooterID); (SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID) : EntityPool.GetPedByID(packet.ShooterID);
p.LastSynced = Main.Ticked; p.LastSynced = Main.Ticked;
p.LastSyncedStopWatch.Restart();
} }
} }
} }

View File

@ -13,7 +13,7 @@ namespace RageCoop.Client
/// <summary> /// <summary>
/// Reduce GC pressure by reusing frequently used packets /// Reduce GC pressure by reusing frequently used packets
/// </summary> /// </summary>
static class SendPackets private static class SendPackets
{ {
public static Packets.PedSync PedPacket = new Packets.PedSync(); public static Packets.PedSync PedPacket = new Packets.PedSync();
public static Packets.VehicleSync VehicelPacket = new Packets.VehicleSync(); public static Packets.VehicleSync VehicelPacket = new Packets.VehicleSync();

View File

@ -1,11 +1,11 @@
using GTA; using GTA;
using GTA.Math; using GTA.Math;
using GTA.Native; using GTA.Native;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using System.Collections.Generic; using System.Collections.Generic;
using Lidgren.Network;
using System.Net;
using System.Linq; using System.Linq;
using System.Net;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -63,16 +63,15 @@ namespace RageCoop.Client
public static void SetPlayer(int id, string username, float latency = 0) public static void SetPlayer(int id, string username, float latency = 0)
{ {
Main.Logger.Debug($"{id},{username},{latency}"); Main.Logger.Debug($"{id},{username},{latency}");
Player p; if (Players.TryGetValue(id, out Player p))
if (Players.TryGetValue(id, out p))
{ {
p.Username = username; p.Username = username;
p.PedID=id; p.ID = id;
p._latencyToServer = latency; p._latencyToServer = latency;
} }
else else
{ {
p = new Player { PedID=id, Username=username, _latencyToServer=latency }; p = new Player { ID = id, Username = username, _latencyToServer = latency };
Players.Add(id, p); Players.Add(id, p);
} }
} }
@ -90,7 +89,7 @@ namespace RageCoop.Client
{ {
p.FakeBlip = World.CreateBlip(p.Position); p.FakeBlip = World.CreateBlip(p.Position);
} }
if (EntityPool.PedExists(p.PedID)) if (EntityPool.PedExists(p.ID))
{ {
p.FakeBlip.DisplayType = BlipDisplayType.NoDisplay; p.FakeBlip.DisplayType = BlipDisplayType.NoDisplay;
} }
@ -108,8 +107,7 @@ namespace RageCoop.Client
} }
public static Player GetPlayer(int id) public static Player GetPlayer(int id)
{ {
Player p; Players.TryGetValue(id, out Player p);
Players.TryGetValue(id, out p);
return p; return p;
} }
public static Player GetPlayer(SyncedPed p) public static Player GetPlayer(SyncedPed p)
@ -139,32 +137,32 @@ namespace RageCoop.Client
} }
} }
internal class Player public class Player
{ {
public byte HolePunchStatus { get; set; } = 1; public byte HolePunchStatus { get; internal set; } = 1;
public bool IsHost; public bool IsHost { get; internal set; }
public string Username { get; internal set; } public string Username { get; internal set; }
/// <summary> /// <summary>
/// Universal character ID. /// Universal ped ID.
/// </summary> /// </summary>
public int PedID public int ID
{ {
get; internal set; get; internal set;
} }
public IPEndPoint InternalEndPoint { get; set; } public IPEndPoint InternalEndPoint { get; internal set; }
public IPEndPoint ExternalEndPoint { get; set; } public IPEndPoint ExternalEndPoint { get; internal set; }
public bool ConnectWhenPunched { get; set; } internal bool ConnectWhenPunched { get; set; }
public Blip FakeBlip { get; set; } public Blip FakeBlip { get; internal set; }
public Vector3 Position { get; set; } public Vector3 Position { get; internal set; }
public SyncedPed Character { get; set; } public SyncedPed Character { get; internal set; }
/// <summary> /// <summary>
/// Player round-trip time in seconds, will be the latency to server if not using P2P connection. /// Player round-trip time in seconds, will be the rtt to server if not using P2P connection.
/// </summary> /// </summary>
public float Ping => Main.LocalPlayerID==PedID ? Networking.Latency*2 : (HasDirectConnection ? Connection.AverageRoundtripTime : _latencyToServer*2); public float Ping => Main.LocalPlayerID == ID ? Networking.Latency * 2 : (HasDirectConnection ? Connection.AverageRoundtripTime : _latencyToServer * 2);
public float PacketTravelTime => HasDirectConnection ? Connection.AverageRoundtripTime / 2 : Networking.Latency + _latencyToServer; public float PacketTravelTime => HasDirectConnection ? Connection.AverageRoundtripTime / 2 : Networking.Latency + _latencyToServer;
public float _latencyToServer = 0; internal float _latencyToServer = 0;
public bool DisplayNameTag { get; set; } = true; public bool DisplayNameTag { get; set; } = true;
public NetConnection Connection { get; set; } public NetConnection Connection { get; internal set; }
public bool HasDirectConnection => Connection?.Status == NetConnectionStatus.Connected; public bool HasDirectConnection => Connection?.Status == NetConnectionStatus.Connected;
} }
} }

View File

@ -15,8 +15,8 @@ using System.Resources;
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Version informationr( // Version information
[assembly: AssemblyVersion("1.5.3.124")] [assembly: AssemblyVersion("1.5.4.6")]
[assembly: AssemblyFileVersion("1.5.3.124")] [assembly: AssemblyFileVersion("1.5.4.6")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )] [assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -21,6 +21,7 @@
<OutPutPath>..\bin\Debug\Client</OutPutPath> <OutPutPath>..\bin\Debug\Client</OutPutPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>DEBUG</DefineConstants> <DefineConstants>DEBUG</DefineConstants>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
<OutPutPath>..\bin\Release\Client</OutPutPath> <OutPutPath>..\bin\Release\Client</OutPutPath>
@ -35,7 +36,6 @@
<Compile Include="Menus\Sub\DevToolMenu.cs" /> <Compile Include="Menus\Sub\DevToolMenu.cs" />
<Compile Include="Menus\Sub\ServersMenu.cs" /> <Compile Include="Menus\Sub\ServersMenu.cs" />
<Compile Include="Menus\Sub\SettingsMenu.cs" /> <Compile Include="Menus\Sub\SettingsMenu.cs" />
<Compile Include="Menus\Sub\UpdateMenu.cs" />
<Compile Include="Networking\Chat.cs" /> <Compile Include="Networking\Chat.cs" />
<Compile Include="Networking\DownloadManager.cs" /> <Compile Include="Networking\DownloadManager.cs" />
<Compile Include="Networking\HolePunch.cs" /> <Compile Include="Networking\HolePunch.cs" />
@ -55,6 +55,7 @@
<Compile Include="Scripting\Resources.cs" /> <Compile Include="Scripting\Resources.cs" />
<Compile Include="Security.cs" /> <Compile Include="Security.cs" />
<Compile Include="Settings.cs" /> <Compile Include="Settings.cs" />
<Compile Include="Sync\Entities\Ped\SyncedPed.Members.cs" />
<Compile Include="Sync\Entities\Ped\SyncedPed.Animations.cs" /> <Compile Include="Sync\Entities\Ped\SyncedPed.Animations.cs" />
<Compile Include="Sync\Entities\SyncedEntity.cs" /> <Compile Include="Sync\Entities\SyncedEntity.cs" />
<Compile Include="Sync\Entities\Ped\SyncedPed.cs" /> <Compile Include="Sync\Entities\Ped\SyncedPed.cs" />
@ -65,6 +66,7 @@
<Compile Include="Sync\EntityPool.cs" /> <Compile Include="Sync\EntityPool.cs" />
<Compile Include="Sync\SyncEvents.cs" /> <Compile Include="Sync\SyncEvents.cs" />
<Compile Include="Sync\Voice.cs" /> <Compile Include="Sync\Voice.cs" />
<Compile Include="Util\AddOnDataProvider.cs" />
<Compile Include="Util\Memory.cs" /> <Compile Include="Util\Memory.cs" />
<Compile Include="Util\NativeCaller.cs" /> <Compile Include="Util\NativeCaller.cs" />
<Compile Include="Util\PedConfigFlags.cs" /> <Compile Include="Util\PedConfigFlags.cs" />
@ -88,7 +90,7 @@
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL"> <Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath> <HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference> </Reference>
<Reference Include="LemonUI.SHVDN3, Version=1.7.0.0, Culture=neutral, processorArchitecture=AMD64"> <Reference Include="LemonUI.SHVDN3, Version=1.10.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\libs\LemonUI.SHVDN3.dll</HintPath> <HintPath>..\libs\LemonUI.SHVDN3.dll</HintPath>
</Reference> </Reference>

View File

@ -1,5 +1,6 @@
#undef DEBUG #undef DEBUG
using GTA; using GTA;
using Newtonsoft.Json;
using RageCoop.Core; using RageCoop.Core;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -39,7 +40,7 @@ namespace RageCoop.Client.Scripting
/// </summary> /// </summary>
public static string Username public static string Username
{ {
get { return Main.Settings.Username; } get => Main.Settings.Username;
set set
{ {
if (Networking.IsOnServer || string.IsNullOrEmpty(value)) if (Networking.IsOnServer || string.IsNullOrEmpty(value))
@ -90,7 +91,7 @@ namespace RageCoop.Client.Scripting
/// <summary> /// <summary>
/// The local player is dead /// The local player is dead
/// </summary> /// </summary>
public static event EmptyEvent OnPlayerDied; public static event EventHandler<string> OnPlayerDied;
/// <summary> /// <summary>
/// A local vehicle is spawned /// A local vehicle is spawned
@ -132,7 +133,7 @@ namespace RageCoop.Client.Scripting
internal static void InvokeVehicleDeleted(SyncedVehicle v) { OnVehicleDeleted?.Invoke(null, v); } internal static void InvokeVehicleDeleted(SyncedVehicle v) { OnVehicleDeleted?.Invoke(null, v); }
internal static void InvokePedSpawned(SyncedPed p) { OnPedSpawned?.Invoke(null, p); } internal static void InvokePedSpawned(SyncedPed p) { OnPedSpawned?.Invoke(null, p); }
internal static void InvokePedDeleted(SyncedPed p) { OnPedDeleted?.Invoke(null, p); } internal static void InvokePedDeleted(SyncedPed p) { OnPedDeleted?.Invoke(null, p); }
internal static void InvokePlayerDied() { OnPlayerDied?.Invoke(); } internal static void InvokePlayerDied(string m) { OnPlayerDied?.Invoke(null, m); }
internal static void InvokeTick() { OnTick?.Invoke(); } internal static void InvokeTick() { OnTick?.Invoke(); }
internal static void InvokeKeyDown(object s, KeyEventArgs e) { OnKeyDown?.Invoke(s, e); } internal static void InvokeKeyDown(object s, KeyEventArgs e) { OnKeyDown?.Invoke(s, e); }
@ -145,8 +146,7 @@ namespace RageCoop.Client.Scripting
// Main.Logger.Debug($"CustomEvent:\n"+args.Args.DumpWithType()); // Main.Logger.Debug($"CustomEvent:\n"+args.Args.DumpWithType());
List<Action<CustomEventReceivedArgs>> handlers; if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
{ {
handlers.ForEach((x) => { x.Invoke(args); }); handlers.ForEach((x) => { x.Invoke(args); });
} }
@ -160,65 +160,48 @@ namespace RageCoop.Client.Scripting
/// Get the local player's ID /// Get the local player's ID
/// </summary> /// </summary>
/// <returns>PlayerID</returns> /// <returns>PlayerID</returns>
public static int LocalPlayerID public static int LocalPlayerID => Main.LocalPlayerID;
{
get { return Main.LocalPlayerID; }
}
/// <summary> /// <summary>
/// Check if player is connected to a server /// Check if player is connected to a server
/// </summary> /// </summary>
public static bool IsOnServer { get { return Networking.IsOnServer; } } public static bool IsOnServer => Networking.IsOnServer;
/// <summary> /// <summary>
/// Get an <see cref="System.Net.IPEndPoint"/> that the player is currently connected to, or null if not connected to the server /// Get an <see cref="System.Net.IPEndPoint"/> that the player is currently connected to, or null if not connected to the server
/// </summary> /// </summary>
public static System.Net.IPEndPoint ServerEndPoint { get { return Networking.IsOnServer ? Networking.ServerConnection?.RemoteEndPoint : null; } } public static System.Net.IPEndPoint ServerEndPoint => Networking.IsOnServer ? Networking.ServerConnection?.RemoteEndPoint : null;
/// <summary> /// <summary>
/// Check if a RAGECOOP menu is visible /// Check if a RAGECOOP menu is visible
/// </summary> /// </summary>
public static bool IsMenuVisible public static bool IsMenuVisible => Menus.CoopMenu.MenuPool.AreAnyVisible;
{
get { return Menus.CoopMenu.MenuPool.AreAnyVisible; }
}
/// <summary> /// <summary>
/// Check if the RAGECOOP chat is visible /// Check if the RAGECOOP chat is visible
/// </summary> /// </summary>
public static bool IsChatFocused public static bool IsChatFocused => Main.MainChat.Focused;
{
get { return Main.MainChat.Focused; }
}
/// <summary> /// <summary>
/// Check if the RAGECOOP list of players is visible /// Check if the RAGECOOP list of players is visible
/// </summary> /// </summary>
public static bool IsPlayerListVisible public static bool IsPlayerListVisible => Util.GetTickCount64() - PlayerList.Pressed < 5000;
{
get { return Util.GetTickCount64() - PlayerList.Pressed < 5000; }
}
/// <summary> /// <summary>
/// Get the version of RAGECOOP /// Get the version of RAGECOOP
/// </summary> /// </summary>
public static Version CurrentVersion public static Version CurrentVersion => Main.Version;
{
get { return Main.Version; }
}
/// <summary> /// <summary>
/// Get a <see cref="Core.Logger"/> that RAGECOOP is currently using. /// Get a <see cref="Core.Logger"/> that RAGECOOP is currently using.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static Logger Logger public static Logger Logger => Main.Logger;
{ /// <summary>
get /// Get all players indexed by their ID
{ /// </summary>
return Main.Logger; public static Dictionary<int, Player> Players => new Dictionary<int, Player>(PlayerList.Players);
}
}
#endregion #endregion
#region FUNCTIONS #region FUNCTIONS
@ -246,6 +229,15 @@ namespace RageCoop.Client.Scripting
} }
} }
/// <summary>
/// List all servers from master server address
/// </summary>
/// <returns></returns>
public static List<ServerInfo> ListServers()
{
return JsonConvert.DeserializeObject<List<ServerInfo>>(HttpHelper.DownloadString(Main.Settings.MasterServer));
}
/// <summary> /// <summary>
/// Send a local chat message to this player /// Send a local chat message to this player
/// </summary> /// </summary>

View File

@ -16,7 +16,7 @@ namespace RageCoop.Client.Scripting
{ {
API.Events.OnPedDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnPedDeleted, p.ID); }; API.Events.OnPedDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnPedDeleted, p.ID); };
API.Events.OnVehicleDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnVehicleDeleted, p.ID); }; API.Events.OnVehicleDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnVehicleDeleted, p.ID); };
API.Events.OnPlayerDied+=() => { API.SendCustomEvent(CustomEvents.OnPlayerDied); }; API.Events.OnPlayerDied += (s, m) => { API.SendCustomEvent(CustomEvents.OnPlayerDied, m); };
API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn, SetAutoRespawn); API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn, SetAutoRespawn);
API.RegisterCustomEventHandler(CustomEvents.SetDisplayNameTag, SetDisplayNameTag); API.RegisterCustomEventHandler(CustomEvents.SetDisplayNameTag, SetDisplayNameTag);
@ -31,7 +31,7 @@ namespace RageCoop.Client.Scripting
API.RegisterCustomEventHandler(CustomEvents.UpdatePedBlip, UpdatePedBlip); API.RegisterCustomEventHandler(CustomEvents.UpdatePedBlip, UpdatePedBlip);
API.RegisterCustomEventHandler(CustomEvents.IsHost, (e) => { _isHost = (bool)e.Args[0]; }); API.RegisterCustomEventHandler(CustomEvents.IsHost, (e) => { _isHost = (bool)e.Args[0]; });
API.RegisterCustomEventHandler(CustomEvents.WeatherTimeSync, WeatherTimeSync); API.RegisterCustomEventHandler(CustomEvents.WeatherTimeSync, WeatherTimeSync);
API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) => { GTA.UI.Notification.Show($"~h~{e.Args[0]}~h~ died."); }); API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) => { GTA.UI.Notification.Show((string)e.Args[0]); });
Task.Run(() => Task.Run(() =>
{ {
while (true) while (true)
@ -46,7 +46,7 @@ namespace RageCoop.Client.Scripting
int weather1 = default(int); int weather1 = default(int);
int weather2 = default(int); int weather2 = default(int);
float percent2 = default(float); float percent2 = default(float);
Function.Call(Hash._GET_WEATHER_TYPE_TRANSITION, &weather1, &weather2, &percent2); Function.Call(Hash.GET_CURR_WEATHER_STATE, &weather1, &weather2, &percent2);
API.SendCustomEvent(CustomEvents.WeatherTimeSync, time.Hours, time.Minutes, time.Seconds, weather1, weather2, percent2); API.SendCustomEvent(CustomEvents.WeatherTimeSync, time.Hours, time.Minutes, time.Seconds, weather1, weather2, percent2);
} }
}); });
@ -60,7 +60,7 @@ namespace RageCoop.Client.Scripting
private void WeatherTimeSync(CustomEventReceivedArgs e) private void WeatherTimeSync(CustomEventReceivedArgs e)
{ {
World.CurrentTimeOfDay = new TimeSpan((int)e.Args[0], (int)e.Args[1], (int)e.Args[2]); World.CurrentTimeOfDay = new TimeSpan((int)e.Args[0], (int)e.Args[1], (int)e.Args[2]);
Function.Call(Hash._SET_WEATHER_TYPE_TRANSITION, (int)e.Args[3], (int)e.Args[4], (float)e.Args[5]); Function.Call(Hash.SET_CURR_WEATHER_STATE, (int)e.Args[3], (int)e.Args[4], (float)e.Args[5]);
} }
private void SetDisplayNameTag(CustomEventReceivedArgs e) private void SetDisplayNameTag(CustomEventReceivedArgs e)
@ -127,8 +127,7 @@ namespace RageCoop.Client.Scripting
var pos = (Vector3)obj.Args[4]; var pos = (Vector3)obj.Args[4];
int rot = (int)obj.Args[5]; int rot = (int)obj.Args[5];
var name = (string)obj.Args[6]; var name = (string)obj.Args[6];
Blip blip; if (!EntityPool.ServerBlips.TryGetValue(id, out Blip blip))
if (!EntityPool.ServerBlips.TryGetValue(id, out blip))
{ {
EntityPool.ServerBlips.Add(id, blip = World.CreateBlip(pos)); EntityPool.ServerBlips.Add(id, blip = World.CreateBlip(pos));
} }

View File

@ -30,7 +30,7 @@ namespace RageCoop.Client.Scripting
/// <summary> /// <summary>
/// Eqivalent of <see cref="ClientResource.Logger"/> in <see cref="CurrentResource"/> /// Eqivalent of <see cref="ClientResource.Logger"/> in <see cref="CurrentResource"/>
/// </summary> /// </summary>
public Core.Logger Logger { get { return CurrentResource.Logger; } } public Core.Logger Logger => CurrentResource.Logger;
} }
} }

View File

@ -38,9 +38,11 @@ namespace RageCoop.Client.Scripting
} }
internal class Resources internal class Resources
{ {
private readonly List<ClientResource> LoadedResources = new List<ClientResource>();
private const string BaseScriptType = "RageCoop.Client.Scripting.ClientScript";
private Logger Logger { get; set; }
public Resources() public Resources()
{ {
BaseScriptType = "RageCoop.Client.Scripting.ClientScript";
Logger = Main.Logger; Logger = Main.Logger;
} }
private void StartAll() private void StartAll()
@ -106,9 +108,6 @@ namespace RageCoop.Client.Scripting
} }
LoadedResources.Clear(); LoadedResources.Clear();
} }
private List<ClientResource> LoadedResources = new List<ClientResource>();
private string BaseScriptType;
public Logger Logger { get; set; }
private void LoadResource(ZipFile file, string dataFolderRoot) private void LoadResource(ZipFile file, string dataFolderRoot)
{ {

View File

@ -7,7 +7,7 @@ namespace RageCoop.Client
{ {
public RSA ServerRSA { get; set; } public RSA ServerRSA { get; set; }
public Aes ClientAes { get; set; } = Aes.Create(); public Aes ClientAes { get; set; } = Aes.Create();
private Logger Logger; private readonly Logger Logger;
public Security(Logger logger) public Security(Logger logger)
{ {
Logger = logger; Logger = logger;

View File

@ -22,7 +22,7 @@ namespace RageCoop.Client
/// <summary> /// <summary>
/// Don't use it! /// Don't use it!
/// </summary> /// </summary>
public string MasterServer { get; set; } = "https://masterserver.ragecoop.online/"; public string MasterServer { get; set; } = "https://masterserver.ragecoop.com/";
/// <summary> /// <summary>
/// Don't use it! /// Don't use it!
/// </summary> /// </summary>
@ -51,7 +51,7 @@ namespace RageCoop.Client
/// <summary> /// <summary>
/// Disable world NPC traffic, mission entities won't be affected /// Disable world NPC traffic, mission entities won't be affected
/// </summary> /// </summary>
public bool DisableTraffic { get; set; } = true; public bool DisableTraffic { get; set; } = false;
/// <summary> /// <summary>
/// Bring up pause menu but don't freeze time when FrontEndPauseAlternate(Esc) is pressed. /// Bring up pause menu but don't freeze time when FrontEndPauseAlternate(Esc) is pressed.
@ -67,6 +67,22 @@ namespace RageCoop.Client
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended). /// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
/// </summary> /// </summary>
public int WorldPedSoftLimit { get; set; } = 30; public int WorldPedSoftLimit { get; set; } = 30;
/// <summary>
/// The mod won't sync more vehicles if the limit is exceeded.
/// </summary>
public int GlobalVehicleSoftLimit { get; set; } = 100;
/// <summary>
/// The mod won't sync more peds if the limit is exceeded.
/// </summary>
public int GlobalPedSoftLimit { get; set; } = 100;
/// <summary>
/// The mod won't sync more projectiles if the limit is exceeded.
/// </summary>
public int GlobalProjectileSoftLimit { get; set; } = 100;
/// <summary> /// <summary>
/// The directory where log and resources downloaded from server will be placed. /// The directory where log and resources downloaded from server will be placed.
/// </summary> /// </summary>
@ -76,5 +92,15 @@ namespace RageCoop.Client
/// Show the owner name of the entity you're aiming at /// Show the owner name of the entity you're aiming at
/// </summary> /// </summary>
public bool ShowEntityOwnerName { get; set; } = false; public bool ShowEntityOwnerName { get; set; } = false;
/// <summary>
/// Show other player's nametag on your screen
/// </summary>
public bool ShowPlayerNameTag { get; set; } = true;
/// <summary>
/// Show other player's blip on map
/// </summary>
public bool ShowPlayerBlip { get; set; } = true;
} }
} }

View File

@ -116,10 +116,10 @@ namespace RageCoop.Client
case unchecked((uint)-1357824103): case unchecked((uint)-1357824103):
case unchecked((uint)-1074790547): case unchecked((uint)-1074790547):
case unchecked((uint)2132975508): case unchecked(2132975508):
case unchecked((uint)-2084633992): case unchecked((uint)-2084633992):
case unchecked((uint)-952879014): case unchecked((uint)-952879014):
case unchecked((uint)100416529): case unchecked(100416529):
case unchecked((uint)WeaponHash.Gusenberg): case unchecked((uint)WeaponHash.Gusenberg):
case unchecked((uint)WeaponHash.MG): case unchecked((uint)WeaponHash.MG):
case unchecked((uint)WeaponHash.CombatMG): case unchecked((uint)WeaponHash.CombatMG):

View File

@ -0,0 +1,81 @@
using GTA;
using GTA.Math;
using RageCoop.Core;
using System.Collections.Generic;
namespace RageCoop.Client
{
/// <summary>
/// ?
/// </summary>
public partial class SyncedPed : SyncedEntity
{
internal Blip PedBlip = null;
internal BlipColor BlipColor = (BlipColor)255;
internal BlipSprite BlipSprite = 0;
internal float BlipScale = 1;
internal int VehicleID
{
get => CurrentVehicle?.ID ?? 0;
set
{
if (CurrentVehicle == null || value != CurrentVehicle?.ID)
{
CurrentVehicle = EntityPool.GetVehicleByID(value);
}
}
}
internal SyncedVehicle CurrentVehicle { get; private set; }
internal VehicleSeat Seat;
public bool IsPlayer { get => OwnerID == ID && ID != 0; }
public Ped MainPed { get; internal set; }
internal int Health { get; set; }
internal Vector3 HeadPosition { get; set; }
internal Vector3 RightFootPosition { get; set; }
internal Vector3 LeftFootPosition { get; set; }
internal byte WeaponTint { get; set; }
private bool _lastRagdoll = false;
private ulong _lastRagdollTime = 0;
private bool _lastInCover = false;
private byte[] _lastClothes = null;
internal byte[] Clothes { get; set; }
internal float Heading { get; set; }
internal ulong LastSpeakingTime { get; set; } = 0;
internal bool IsSpeaking { get; set; } = false;
public byte Speed { get; set; }
private bool _lastIsJumping = false;
internal PedDataFlags Flags;
internal bool IsAiming => Flags.HasPedFlag(PedDataFlags.IsAiming);
internal bool _lastDriveBy;
internal bool IsReloading => Flags.HasPedFlag(PedDataFlags.IsReloading);
internal bool IsJumping => Flags.HasPedFlag(PedDataFlags.IsJumping);
internal bool IsRagdoll => Flags.HasPedFlag(PedDataFlags.IsRagdoll);
internal bool IsOnFire => Flags.HasPedFlag(PedDataFlags.IsOnFire);
internal bool IsInParachuteFreeFall => Flags.HasPedFlag(PedDataFlags.IsInParachuteFreeFall);
internal bool IsParachuteOpen => Flags.HasPedFlag(PedDataFlags.IsParachuteOpen);
internal bool IsOnLadder => Flags.HasPedFlag(PedDataFlags.IsOnLadder);
internal bool IsVaulting => Flags.HasPedFlag(PedDataFlags.IsVaulting);
internal bool IsInCover => Flags.HasPedFlag(PedDataFlags.IsInCover);
internal bool IsInLowCover => Flags.HasPedFlag(PedDataFlags.IsInLowCover);
internal bool IsInCoverFacingLeft => Flags.HasPedFlag(PedDataFlags.IsInCoverFacingLeft);
internal bool IsBlindFiring => Flags.HasPedFlag(PedDataFlags.IsBlindFiring);
internal bool IsInStealthMode => Flags.HasPedFlag(PedDataFlags.IsInStealthMode);
internal Prop ParachuteProp { get; set; } = null;
internal uint CurrentWeaponHash { get; set; }
private Dictionary<uint, bool> _lastWeaponComponents = null;
internal Dictionary<uint, bool> WeaponComponents { get; set; } = null;
private Entity _weaponObj;
internal Vector3 AimCoords { get; set; }
private readonly string[] _currentAnimation = new string[2] { "", "" };
private bool LastMoving;
}
}

View File

@ -15,7 +15,6 @@ namespace RageCoop.Client
/// </summary> /// </summary>
public partial class SyncedPed : SyncedEntity public partial class SyncedPed : SyncedEntity
{ {
#region CONSTRUCTORS
/// <summary> /// <summary>
/// Create a local entity (outgoing sync) /// Create a local entity (outgoing sync)
@ -29,7 +28,7 @@ namespace RageCoop.Client
MainPed = p; MainPed = p;
OwnerID = Main.LocalPlayerID; OwnerID = Main.LocalPlayerID;
Function.Call(Hash._SET_PED_CAN_PLAY_INJURED_ANIMS, false); //Function.Call(Hash.SET_PED_IS_IGNORED_BY_AUTO_OPEN_DOORS, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true); MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
// MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableMelee, true); // MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableMelee, true);
@ -43,75 +42,6 @@ namespace RageCoop.Client
ID = id; ID = id;
LastSynced = Main.Ticked; LastSynced = Main.Ticked;
} }
#endregion
internal Blip PedBlip = null;
internal BlipColor BlipColor = (BlipColor)255;
internal BlipSprite BlipSprite = 0;
internal float BlipScale = 1;
internal int VehicleID
{
get => CurrentVehicle?.ID ?? 0;
set
{
if (CurrentVehicle == null || value != CurrentVehicle?.ID)
{
CurrentVehicle=EntityPool.GetVehicleByID(value);
}
}
}
internal SyncedVehicle CurrentVehicle { get; private set; }
internal VehicleSeat Seat;
public bool IsPlayer { get => OwnerID == ID && ID != 0; }
public Ped MainPed { get; internal set; }
internal int Health { get; set; }
internal Vector3 HeadPosition { get; set; }
internal Vector3 RightFootPosition { get; set; }
internal Vector3 LeftFootPosition { get; set; }
internal byte WeaponTint { get; set; }
internal Vehicle _lastVehicle { get; set; }
internal int _lastVehicleID { get; set; }
private bool _lastRagdoll = false;
private ulong _lastRagdollTime = 0;
private bool _lastInCover = false;
private byte[] _lastClothes = null;
internal byte[] Clothes { get; set; }
internal float Heading { get; set; }
internal ulong LastSpeakingTime { get; set; } = 0;
internal bool IsSpeaking { get; set; } = false;
#region -- VARIABLES --
public byte Speed { get; set; }
private bool _lastIsJumping = false;
internal PedDataFlags Flags;
internal bool IsAiming => Flags.HasPedFlag(PedDataFlags.IsAiming);
internal bool _lastDriveBy;
internal bool IsReloading => Flags.HasPedFlag(PedDataFlags.IsReloading);
internal bool IsJumping => Flags.HasPedFlag(PedDataFlags.IsJumping);
internal bool IsRagdoll => Flags.HasPedFlag(PedDataFlags.IsRagdoll);
internal bool IsOnFire => Flags.HasPedFlag(PedDataFlags.IsOnFire);
internal bool IsInParachuteFreeFall => Flags.HasPedFlag(PedDataFlags.IsInParachuteFreeFall);
internal bool IsParachuteOpen => Flags.HasPedFlag(PedDataFlags.IsParachuteOpen);
internal bool IsOnLadder => Flags.HasPedFlag(PedDataFlags.IsOnLadder);
internal bool IsVaulting => Flags.HasPedFlag(PedDataFlags.IsVaulting);
internal bool IsInCover => Flags.HasPedFlag(PedDataFlags.IsInCover);
internal bool IsInLowCover => Flags.HasPedFlag(PedDataFlags.IsInLowCover);
internal bool IsInCoverFacingLeft => Flags.HasPedFlag(PedDataFlags.IsInCoverFacingLeft);
internal bool IsBlindFiring => Flags.HasPedFlag(PedDataFlags.IsBlindFiring);
internal bool IsInStealthMode => Flags.HasPedFlag(PedDataFlags.IsInStealthMode);
internal Prop ParachuteProp { get; set; } = null;
internal uint CurrentWeaponHash { get; set; }
private Dictionary<uint, bool> _lastWeaponComponents = null;
internal Dictionary<uint, bool> WeaponComponents { get; set; } = null;
private Entity _weaponObj;
#endregion
internal Vector3 AimCoords { get; set; }
private WeaponAsset WeaponAsset { get; set; }
internal override void Update() internal override void Update()
{ {
@ -146,12 +76,13 @@ namespace RageCoop.Client
} }
} }
if (((byte)BlipColor==255) && (PedBlip!=null)) if (!Main.Settings.ShowPlayerBlip && (byte)BlipColor != 255) BlipColor = (BlipColor)255;
if ((byte)BlipColor == 255 && PedBlip != null)
{ {
PedBlip.Delete(); PedBlip.Delete();
PedBlip = null; PedBlip = null;
} }
else if (((byte)BlipColor != 255) && PedBlip==null) else if ((byte)BlipColor != 255 && PedBlip == null)
{ {
PedBlip = MainPed.AddBlip(); PedBlip = MainPed.AddBlip();
@ -240,7 +171,7 @@ namespace RageCoop.Client
private void RenderNameTag() private void RenderNameTag()
{ {
if (!Owner.DisplayNameTag || (MainPed==null) || !MainPed.IsVisible || !MainPed.IsInRange(Main.PlayerPosition, 40f)) if (!Owner.DisplayNameTag || !Main.Settings.ShowPlayerNameTag || MainPed == null || !MainPed.IsVisible || !MainPed.IsInRange(Main.PlayerPosition, 40f))
{ {
return; return;
} }
@ -305,7 +236,7 @@ namespace RageCoop.Client
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED_BY_PLAYER, MainPed.Handle, Game.Player, true); Function.Call(Hash.SET_PED_CAN_BE_TARGETTED_BY_PLAYER, MainPed.Handle, Game.Player, true);
Function.Call(Hash.SET_PED_GET_OUT_UPSIDE_DOWN_VEHICLE, MainPed.Handle, false); Function.Call(Hash.SET_PED_GET_OUT_UPSIDE_DOWN_VEHICLE, MainPed.Handle, false);
Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, MainPed.Handle, true, true); Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, MainPed.Handle, true, true);
Function.Call(Hash._SET_PED_CAN_PLAY_INJURED_ANIMS, false); Function.Call(Hash.SET_PED_IS_IGNORED_BY_AUTO_OPEN_DOORS, false);
Function.Call(Hash.SET_PED_CAN_EVASIVE_DIVE, MainPed.Handle, false); Function.Call(Hash.SET_PED_CAN_EVASIVE_DIVE, MainPed.Handle, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DrownsInWater, false); MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DrownsInWater, false);
@ -343,9 +274,6 @@ namespace RageCoop.Client
} }
#region ONFOOT
private string[] _currentAnimation = new string[2] { "", "" };
private void DisplayOnFoot() private void DisplayOnFoot()
{ {
@ -506,8 +434,6 @@ namespace RageCoop.Client
} }
return; return;
} }
else
{
if (MainPed.IsRagdoll) if (MainPed.IsRagdoll)
{ {
if (Speed == 0) if (Speed == 0)
@ -518,10 +444,8 @@ namespace RageCoop.Client
{ {
MainPed.Task.ClearAllImmediately(); MainPed.Task.ClearAllImmediately();
} }
return;
}
_lastRagdoll = false; _lastRagdoll = false;
return;
} }
if (IsReloading) if (IsReloading)
@ -581,12 +505,12 @@ namespace RageCoop.Client
} }
} }
#region WEAPON
private void CheckCurrentWeapon() private void CheckCurrentWeapon()
{ {
if (MainPed.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash || !WeaponComponents.Compare(_lastWeaponComponents) || (Speed <= 3 && _weaponObj?.IsVisible != true)) if (MainPed.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash || !WeaponComponents.Compare(_lastWeaponComponents) || (Speed <= 3 && _weaponObj?.IsVisible != true))
{ {
WeaponAsset=new WeaponAsset(CurrentWeaponHash); new WeaponAsset(CurrentWeaponHash).Request();
MainPed.Weapons.RemoveAll(); MainPed.Weapons.RemoveAll();
_weaponObj = Entity.FromHandle(Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0)); _weaponObj = Entity.FromHandle(Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0));
if (_weaponObj == null) { return; } if (_weaponObj == null) { return; }
@ -627,9 +551,7 @@ namespace RageCoop.Client
} }
SmoothTransition(); SmoothTransition();
} }
#endregion
private bool LastMoving;
private void WalkTo() private void WalkTo()
{ {
MainPed.Task.ClearAll(); MainPed.Task.ClearAll();
@ -676,6 +598,8 @@ namespace RageCoop.Client
MainPed.Task.StandStill(2000); MainPed.Task.StandStill(2000);
LastMoving = false; LastMoving = false;
} }
if (MainPed.IsTaskActive(TaskType.CTaskDiveToGround)) MainPed.Task.ClearAll();
break; break;
} }
SmoothTransition(); SmoothTransition();
@ -750,10 +674,6 @@ namespace RageCoop.Client
} }
} }
#endregion
private void DisplayInVehicle() private void DisplayInVehicle()
{ {
if (CurrentVehicle?.MainVehicle == null) { return; } if (CurrentVehicle?.MainVehicle == null) { return; }
@ -796,7 +716,7 @@ namespace RageCoop.Client
case 5: case 5:
if (MainPed.VehicleTryingToEnter != CurrentVehicle.MainVehicle || MainPed.GetSeatTryingToEnter() != Seat) if (MainPed.VehicleTryingToEnter != CurrentVehicle.MainVehicle || MainPed.GetSeatTryingToEnter() != Seat)
{ {
MainPed.Task.EnterVehicle(CurrentVehicle.MainVehicle,Seat,-1,5,EnterVehicleFlags.AllowJacking); MainPed.Task.EnterVehicle(CurrentVehicle.MainVehicle, Seat, -1, 5, EnterVehicleFlags.JackAnyone);
} }
break; break;
case 6: case 6:

View File

@ -36,7 +36,8 @@ namespace RageCoop.Client
if (value == _ownerID && Owner != null) { return; } if (value == _ownerID && Owner != null) { return; }
_ownerID = value; _ownerID = value;
Owner = PlayerList.GetPlayer(value); Owner = PlayerList.GetPlayer(value);
if(this is SyncedPed && Owner!=null){ if (this is SyncedPed && Owner != null)
{
Owner.Character = ((SyncedPed)this); Owner.Character = ((SyncedPed)this);
} }
} }
@ -83,7 +84,7 @@ namespace RageCoop.Client
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
internal protected bool _lastFrozen = false; protected internal bool _lastFrozen = false;
internal Model Model { get; set; } internal Model Model { get; set; }
internal Vector3 Position { get; set; } internal Vector3 Position { get; set; }
internal Vector3 Rotation { get; set; } internal Vector3 Rotation { get; set; }

View File

@ -1,7 +1,7 @@
using GTA; using GTA;
using GTA.Math; using GTA.Math;
using RageCoop.Core;
using GTA.Native; using GTA.Native;
using RageCoop.Core;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -19,12 +19,11 @@ namespace RageCoop.Client
public SyncedEntity Shooter { get; set; } public SyncedEntity Shooter { get; set; }
public bool Exploded => Flags.HasProjDataFlag(ProjectileDataFlags.Exploded); public bool Exploded => Flags.HasProjDataFlag(ProjectileDataFlags.Exploded);
internal override Player Owner => Shooter.Owner;
/// <summary> /// <summary>
/// Invalid property for projectile. /// Invalid property for projectile.
/// </summary> /// </summary>
private new int OwnerID { set { } } private new int OwnerID { set { } }
internal override Player Owner => Shooter.Owner;
public WeaponHash WeaponHash { get; set; } public WeaponHash WeaponHash { get; set; }
private WeaponAsset Asset { get; set; } private WeaponAsset Asset { get; set; }
public void ExtractData(ref Packets.ProjectileSync p) public void ExtractData(ref Packets.ProjectileSync p)
@ -101,7 +100,7 @@ namespace RageCoop.Client
CreateProjectile(); CreateProjectile();
return; return;
} }
MainProjectile.Velocity=Velocity+(Position+Shooter.Owner.PacketTravelTime*Velocity-MainProjectile.Position); MainProjectile.Velocity = Velocity + 10 * (Predict(Position) - MainProjectile.Position);
MainProjectile.Rotation = Rotation; MainProjectile.Rotation = Rotation;
LastUpdated = Main.Ticked; LastUpdated = Main.Ticked;
} }
@ -113,15 +112,14 @@ namespace RageCoop.Client
if (Shooter == null) { return; } if (Shooter == null) { return; }
Entity owner; Entity owner;
owner = (Shooter as SyncedPed)?.MainPed ?? (Entity)(Shooter as SyncedVehicle)?.MainVehicle; owner = (Shooter as SyncedPed)?.MainPed ?? (Entity)(Shooter as SyncedVehicle)?.MainVehicle;
Position = (Owner.PacketTravelTime + 0.001f * LastSyncedStopWatch.ElapsedMilliseconds) * Shooter.Velocity + Position;
var end = Position + Velocity; var end = Position + Velocity;
Function.Call(Hash.SHOOT_SINGLE_BULLET_BETWEEN_COORDS_IGNORE_ENTITY, Position.X, Position.Y, Position.Z, end.X, end.Y, end.Z, 0, 1, WeaponHash, owner?.Handle ?? 0, 1, 0, -1,owner); Function.Call(Hash.SHOOT_SINGLE_BULLET_BETWEEN_COORDS_IGNORE_ENTITY, Position.X, Position.Y, Position.Z, end.X, end.Y, end.Z, 0, 1, WeaponHash, owner?.Handle ?? 0, 1, 0, -1);
var ps = World.GetAllProjectiles(); var ps = World.GetAllProjectiles();
MainProjectile = ps[ps.Length - 1]; MainProjectile = ps[ps.Length - 1];
MainProjectile.IsCollisionEnabled=false;
MainProjectile.Position = Position; MainProjectile.Position = Position;
MainProjectile.Rotation = Rotation; MainProjectile.Rotation = Rotation;
MainProjectile.Velocity = Velocity; MainProjectile.Velocity = Velocity;
Main.Delay(()=>MainProjectile.IsCollisionEnabled=true, 100);
EntityPool.Add(this); EntityPool.Add(this);
} }
} }

View File

@ -1,13 +1,12 @@
using System;
using RageCoop.Core;
using GTA; using GTA;
using System.Diagnostics;
using System.Collections.Generic;
using GTA.Math; using GTA.Math;
using GTA.Native; using RageCoop.Core;
using System.Collections.Generic;
namespace RageCoop.Client{ namespace RageCoop.Client
public partial class SyncedVehicle{ {
public partial class SyncedVehicle
{
public Vehicle MainVehicle { get; internal set; } public Vehicle MainVehicle { get; internal set; }
@ -68,11 +67,9 @@ namespace RageCoop.Client{
private bool _lastHornActive = false; private bool _lastHornActive = false;
private bool _lastTransformed = false; private bool _lastTransformed = false;
internal int _lastLivery = -1; internal int _lastLivery = -1;
List<Vector3> _predictedTrace = new List<Vector3>(); private readonly List<Vector3> _predictedTrace = new List<Vector3>();
List<Vector3> _orgTrace = new List<Vector3>(); private readonly List<Vector3> _orgTrace = new List<Vector3>();
private Vector3 _predictedPosition; private Vector3 _predictedPosition;
float _elapsed;
#endregion #endregion
#region OUTGOING #region OUTGOING

View File

@ -4,8 +4,6 @@ using GTA.Native;
using RageCoop.Core; using RageCoop.Core;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -31,7 +29,9 @@ namespace RageCoop.Client
SetUpFixedData(); SetUpFixedData();
} }
private void SetUpFixedData(){ internal void SetUpFixedData()
{
if (MainVehicle == null) { return; }
IsAircraft = MainVehicle.IsAircraft; IsAircraft = MainVehicle.IsAircraft;
IsMotorcycle = MainVehicle.IsMotorcycle; IsMotorcycle = MainVehicle.IsMotorcycle;
@ -149,8 +149,6 @@ namespace RageCoop.Client
MainVehicle.AreHighBeamsOn = HighBeamsOn; MainVehicle.AreHighBeamsOn = HighBeamsOn;
} }
if (IsAircraft) if (IsAircraft)
{ {
if (LandingGear != (byte)MainVehicle.LandingGearState) if (LandingGear != (byte)MainVehicle.LandingGearState)
@ -184,10 +182,12 @@ namespace RageCoop.Client
MainVehicle.RoofState = RoofState; MainVehicle.RoofState = RoofState;
} }
if(HasRocketBoost && Flags.HasFlag(VehicleDataFlags.IsRocketBoostActive) != MainVehicle.IsRocketBoostActive()){ if (HasRocketBoost && Flags.HasFlag(VehicleDataFlags.IsRocketBoostActive) != MainVehicle.IsRocketBoostActive())
{
MainVehicle.SetRocketBoostActive(Flags.HasFlag(VehicleDataFlags.IsRocketBoostActive)); MainVehicle.SetRocketBoostActive(Flags.HasFlag(VehicleDataFlags.IsRocketBoostActive));
} }
if(HasParachute && Flags.HasFlag(VehicleDataFlags.IsParachuteActive) != MainVehicle.IsParachuteActive()){ if (HasParachute && Flags.HasFlag(VehicleDataFlags.IsParachuteActive) != MainVehicle.IsParachuteActive())
{
MainVehicle.SetParachuteActive(Flags.HasFlag(VehicleDataFlags.IsParachuteActive)); MainVehicle.SetParachuteActive(Flags.HasFlag(VehicleDataFlags.IsParachuteActive));
} }
if (IsSubmarineCar) if (IsSubmarineCar)
@ -197,13 +197,13 @@ namespace RageCoop.Client
if (!_lastTransformed) if (!_lastTransformed)
{ {
_lastTransformed = true; _lastTransformed = true;
Function.Call(Hash._TRANSFORM_VEHICLE_TO_SUBMARINE, MainVehicle.Handle, false); Function.Call(Hash.TRANSFORM_TO_SUBMARINE, MainVehicle.Handle, false);
} }
} }
else if (_lastTransformed) else if (_lastTransformed)
{ {
_lastTransformed = false; _lastTransformed = false;
Function.Call(Hash._TRANSFORM_SUBMARINE_TO_VEHICLE, MainVehicle.Handle, false); Function.Call(Hash.TRANSFORM_TO_CAR, MainVehicle.Handle, false);
} }
} }
else if (IsDeluxo) else if (IsDeluxo)
@ -260,7 +260,8 @@ namespace RageCoop.Client
} }
LastUpdated = Main.Ticked; LastUpdated = Main.Ticked;
} }
void DisplayVehicle()
private void DisplayVehicle()
{ {
_predictedPosition = Predict(Position); _predictedPosition = Predict(Position);
var current = MainVehicle.ReadPosition(); var current = MainVehicle.ReadPosition();
@ -274,7 +275,7 @@ namespace RageCoop.Client
MainVehicle.Quaternion = Quaternion; MainVehicle.Quaternion = Quaternion;
return; return;
} }
else if (dist > 0.03) if (dist > 0.03)
{ {
MainVehicle.Velocity = Velocity + cali; MainVehicle.Velocity = Velocity + cali;
} }
@ -286,11 +287,8 @@ namespace RageCoop.Client
MainVehicle.RotationVelocity = RotationVelocity; MainVehicle.RotationVelocity = RotationVelocity;
return; return;
} }
else
{
MainVehicle.RotationVelocity = RotationVelocity + calirot * 0.2f; MainVehicle.RotationVelocity = RotationVelocity + calirot * 0.2f;
} }
}
private Vector3 GetCalibrationRotation() private Vector3 GetCalibrationRotation()
{ {
var rot = Quaternion.LookRotation(Quaternion * Vector3.RelativeFront, Quaternion * Vector3.RelativeTop).ToEulerAngles(); var rot = Quaternion.LookRotation(Quaternion * Vector3.RelativeFront, Quaternion * Vector3.RelativeTop).ToEulerAngles();
@ -316,7 +314,7 @@ namespace RageCoop.Client
// GTA.UI.Notification.Show($"~r~(Vehicle)Model ({CurrentVehicleModelHash}) cannot be loaded!"); // GTA.UI.Notification.Show($"~r~(Vehicle)Model ({CurrentVehicleModelHash}) cannot be loaded!");
return false; return false;
} }
else if (MainVehicle==null) if (MainVehicle == null)
{ {
Model.Request(); Model.Request();
return false; return false;
@ -366,7 +364,7 @@ namespace RageCoop.Client
private void StartPedalingAnim(bool fast) private void StartPedalingAnim(bool fast)
{ {
MainVehicle.Driver?.Task.PlayAnimation(PedalingAnimDict(), PedalingAnimName(fast), 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.AllowRotation, 1.0f); MainVehicle.Driver?.Task.PlayAnimation(PedalingAnimDict(), PedalingAnimName(fast), 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.Secondary, 1.0f);
} }
@ -375,7 +373,5 @@ namespace RageCoop.Client
MainVehicle.Driver.Task.ClearAnimation(PedalingAnimDict(), PedalingAnimName(fast)); MainVehicle.Driver.Task.ClearAnimation(PedalingAnimDict(), PedalingAnimName(fast));
} }
#endregion #endregion
} }
} }

View File

@ -1,18 +1,17 @@
using GTA; using GTA;
using GTA.Native; using GTA.Native;
using Lidgren.Network;
using RageCoop.Client.Scripting; using RageCoop.Client.Scripting;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using Lidgren.Network;
namespace RageCoop.Client namespace RageCoop.Client
{ {
internal class EntityPool internal class EntityPool
{ {
public static object PedsLock = new object(); public static object PedsLock = new object();
public static int CharactersCount { get { return PedsByID.Count; } }
#if BENCHMARK #if BENCHMARK
private static Stopwatch PerfCounter=new Stopwatch(); private static Stopwatch PerfCounter=new Stopwatch();
private static Stopwatch PerfCounter2=Stopwatch.StartNew(); private static Stopwatch PerfCounter2=Stopwatch.StartNew();
@ -44,10 +43,10 @@ namespace RageCoop.Client
#endregion #endregion
public static void Cleanup(bool keepPlayer = true, bool keepMine = true) public static void Cleanup(bool keepPlayer = true, bool keepMine = true)
{ {
foreach (int id in new List<int>(PedsByID.Keys)) foreach (var ped in PedsByID.Values.ToArray())
{ {
if (keepPlayer && (id==Main.LocalPlayerID)|| keepMine && (PedsByID[id].OwnerID == Main.LocalPlayerID)) { continue; } if ((keepPlayer && (ped.ID == Main.LocalPlayerID)) || (keepMine && (ped.OwnerID == Main.LocalPlayerID))) { continue; }
RemovePed(id); RemovePed(ped.ID);
} }
PedsByID.Clear(); PedsByID.Clear();
PedsByHandle.Clear(); PedsByHandle.Clear();
@ -278,8 +277,8 @@ namespace RageCoop.Client
{ {
ProjectilesByHandle.Remove(p.Handle); ProjectilesByHandle.Remove(p.Handle);
} }
Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}"); //Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
p.Explode(); if (sp.Exploded) p.Explode();
} }
ProjectilesByID.Remove(id); ProjectilesByID.Remove(id);
} }
@ -289,11 +288,11 @@ namespace RageCoop.Client
public static bool VehicleExists(int id) => VehiclesByID.ContainsKey(id); public static bool VehicleExists(int id) => VehiclesByID.ContainsKey(id);
public static bool ProjectileExists(int id) => ProjectilesByID.ContainsKey(id); public static bool ProjectileExists(int id) => ProjectilesByID.ContainsKey(id);
#endregion #endregion
static int vehStateIndex; private static int vehStateIndex;
static int pedStateIndex; private static int pedStateIndex;
static int vehStatesPerFrame; private static int vehStatesPerFrame;
static int pedStatesPerFrame; private static int pedStatesPerFrame;
static int i; private static int i;
public static Ped[] allPeds = new Ped[0]; public static Ped[] allPeds = new Ped[0];
public static Vehicle[] allVehicles = new Vehicle[0]; public static Vehicle[] allVehicles = new Vehicle[0];
public static Projectile[] allProjectiles = new Projectile[0]; public static Projectile[] allProjectiles = new Projectile[0];
@ -310,17 +309,6 @@ namespace RageCoop.Client
allProjectiles = World.GetAllProjectiles(); allProjectiles = World.GetAllProjectiles();
vehStatesPerFrame = allVehicles.Length * 2 / (int)Game.FPS + 1; vehStatesPerFrame = allVehicles.Length * 2 / (int)Game.FPS + 1;
pedStatesPerFrame = allPeds.Length * 2 / (int)Game.FPS + 1; pedStatesPerFrame = allPeds.Length * 2 / (int)Game.FPS + 1;
/*
if (Main.Ticked%50==0)
{
bool flag1 = allVehicles.Length>Main.Settings.WorldVehicleSoftLimit && Main.Settings.WorldVehicleSoftLimit>-1;
bool flag2 = allPeds.Length>Main.Settings.WorldPedSoftLimit && Main.Settings.WorldPedSoftLimit>-1;
if ((flag1||flag2) && _trafficSpawning)
{ SetBudget(0); _trafficSpawning=false; }
else if(!_trafficSpawning)
{ SetBudget(1); _trafficSpawning=true; }
}
*/
#if BENCHMARK #if BENCHMARK
Debug.TimeStamps[TimeStamp.GetAllEntities]=PerfCounter.ElapsedTicks; Debug.TimeStamps[TimeStamp.GetAllEntities]=PerfCounter.ElapsedTicks;
@ -345,7 +333,7 @@ namespace RageCoop.Client
if (p.MainProjectile.AttachedEntity == null) if (p.MainProjectile.AttachedEntity == null)
{ {
// Prevent projectiles from exploding next to vehicle // Prevent projectiles from exploding next to vehicle
if (p.WeaponHash==(WeaponHash)VehicleWeaponHash.Tank || p.MainProjectile.Position.DistanceTo(p.Origin)<2) if (p.WeaponHash == (WeaponHash)VehicleWeaponHash.Tank || (p.MainProjectile.OwnerEntity?.EntityType == EntityType.Vehicle && p.MainProjectile.Position.DistanceTo(p.Origin) < 2))
{ {
continue; continue;
} }
@ -370,14 +358,15 @@ namespace RageCoop.Client
lock (PedsLock) lock (PedsLock)
{ {
EntityPool.AddPlayer(); AddPlayer();
foreach (Ped p in allPeds) foreach (Ped p in allPeds)
{ {
SyncedPed c = EntityPool.GetPedByHandle(p.Handle); SyncedPed c = GetPedByHandle(p.Handle);
if (c==null && (p!=Game.Player.Character)) List<PedHash> mainCharacters = new List<PedHash> { PedHash.Michael, PedHash.Franklin, PedHash.Franklin02, PedHash.Trevor };
if (c == null && p != Game.Player.Character && !mainCharacters.Contains((PedHash)p.Model.Hash))
{ {
if (allPeds.Length>Main.Settings.WorldPedSoftLimit && p.PopulationType != EntityPopulationType.RandomAmbient) if (allPeds.Length > Main.Settings.WorldPedSoftLimit && p.PopulationType == EntityPopulationType.RandomAmbient && !p.IsInVehicle())
{ {
p.Delete(); p.Delete();
continue; continue;
@ -385,7 +374,7 @@ namespace RageCoop.Client
// Main.Logger.Trace($"Creating SyncEntity for ped, handle:{p.Handle}"); // Main.Logger.Trace($"Creating SyncEntity for ped, handle:{p.Handle}");
c = new SyncedPed(p); c = new SyncedPed(p);
EntityPool.Add(c); Add(c);
} }
} }
#if BENCHMARK #if BENCHMARK
@ -404,7 +393,7 @@ namespace RageCoop.Client
i++; i++;
if ((c.MainPed != null) && (!c.MainPed.Exists())) if ((c.MainPed != null) && (!c.MainPed.Exists()))
{ {
EntityPool.RemovePed(c.ID, "non-existent"); RemovePed(c.ID, "non-existent");
continue; continue;
} }
@ -441,9 +430,8 @@ namespace RageCoop.Client
Debug.TimeStamps[TimeStamp.PedTotal]=PerfCounter.ElapsedTicks; Debug.TimeStamps[TimeStamp.PedTotal]=PerfCounter.ElapsedTicks;
#endif #endif
} }
var check = Main.Ticked % 100 == 0;
i = -1; i = -1;
lock (VehiclesLock) lock (VehiclesLock)
{ {
foreach (Vehicle veh in allVehicles) foreach (Vehicle veh in allVehicles)
@ -458,10 +446,10 @@ namespace RageCoop.Client
foreach (var p in veh.Occupants) foreach (var p in veh.Occupants)
{ {
p.Delete(); p.Delete();
var c = EntityPool.GetPedByHandle(p.Handle); var c = GetPedByHandle(p.Handle);
if (c != null) if (c != null)
{ {
EntityPool.RemovePed(c.ID, "ThrottleTraffic"); RemovePed(c.ID, "ThrottleTraffic");
} }
} }
veh.Delete(); veh.Delete();
@ -488,10 +476,13 @@ namespace RageCoop.Client
i++; i++;
if ((v.MainVehicle != null) && (!v.MainVehicle.Exists())) if ((v.MainVehicle != null) && (!v.MainVehicle.Exists()))
{ {
EntityPool.RemoveVehicle(v.ID, "non-existent"); RemoveVehicle(v.ID, "non-existent");
continue; continue;
} }
if (check)
{
v.SetUpFixedData();
}
// Outgoing sync // Outgoing sync
if (v.IsLocal) if (v.IsLocal)
{ {
@ -516,7 +507,8 @@ namespace RageCoop.Client
} }
Networking.Peer.FlushSendQueue(); Networking.Peer.FlushSendQueue();
} }
static void UpdateTargets()
private static void UpdateTargets()
{ {
Networking.Targets = new List<NetConnection>(PlayerList.Players.Count) { Networking.ServerConnection }; Networking.Targets = new List<NetConnection>(PlayerList.Players.Count) { Networking.ServerConnection };
foreach (var p in PlayerList.Players.Values.ToArray()) foreach (var p in PlayerList.Players.Values.ToArray())
@ -581,21 +573,21 @@ namespace RageCoop.Client
{ {
public static void Add(SyncedVehicle v) public static void Add(SyncedVehicle v)
{ {
lock (EntityPool.VehiclesLock) lock (VehiclesLock)
{ {
EntityPool.Add(v); EntityPool.Add(v);
} }
} }
public static void Add(SyncedPed p) public static void Add(SyncedPed p)
{ {
lock (EntityPool.PedsLock) lock (PedsLock)
{ {
EntityPool.Add(p); EntityPool.Add(p);
} }
} }
public static void Add(SyncedProjectile sp) public static void Add(SyncedProjectile sp)
{ {
lock (EntityPool.ProjectilesLock) lock (ProjectilesLock)
{ {
EntityPool.Add(sp); EntityPool.Add(sp);
} }

View File

@ -1,10 +1,8 @@
using GTA; using GTA;
using GTA.Math; using GTA.Math;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using System; using System;
using System.Threading;
using System.Threading.Tasks;
using Lidgren.Network;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -73,9 +71,8 @@ namespace RageCoop.Client
#region HANDLE #region HANDLE
public static ParticleEffectAsset CorePFXAsset = new ParticleEffectAsset("core"); public static ParticleEffectAsset CorePFXAsset = new ParticleEffectAsset("core");
private static WeaponAsset _weaponAsset = default;
static WeaponAsset _weaponAsset = default; private static uint _lastWeaponHash;
static uint _lastWeaponHash;
private static void HandlePedKilled(Packets.PedKilled p) private static void HandlePedKilled(Packets.PedKilled p)
{ {
@ -129,7 +126,7 @@ namespace RageCoop.Client
} }
var p = EntityPool.GetPedByID(ownerID)?.MainPed; var p = EntityPool.GetPedByID(ownerID)?.MainPed;
if (p == null) { p=Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); } if (p == null) { return; /* p = Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); */ }
if (!CorePFXAsset.IsLoaded) { CorePFXAsset.Request(); } if (!CorePFXAsset.IsLoaded) { CorePFXAsset.Request(); }
if (_lastWeaponHash != weaponHash) if (_lastWeaponHash != weaponHash)
{ {
@ -162,44 +159,39 @@ namespace RageCoop.Client
WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash), WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash),
b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1); b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1);
} }
public static void HandleEvent(PacketType type, byte[] data) public static void HandleEvent(PacketType type, NetIncomingMessage msg)
{ {
switch (type) switch (type)
{ {
case PacketType.BulletShot: case PacketType.BulletShot:
{ {
Packets.BulletShot p = new Packets.BulletShot(); Packets.BulletShot p = new Packets.BulletShot();
p.Deserialize(data); p.Deserialize(msg);
HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID); HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID);
break; break;
} }
case PacketType.VehicleBulletShot: case PacketType.VehicleBulletShot:
{ {
HandleVehicleBulletShot(data.GetPacket<Packets.VehicleBulletShot>()); HandleVehicleBulletShot(msg.GetPacket<Packets.VehicleBulletShot>());
break; break;
} }
case PacketType.OwnerChanged: case PacketType.OwnerChanged:
{ {
Packets.OwnerChanged packet = new Packets.OwnerChanged(); HandleOwnerChanged(msg.GetPacket<Packets.OwnerChanged>());
packet.Deserialize(data);
HandleOwnerChanged(packet);
} }
break; break;
case PacketType.PedKilled: case PacketType.PedKilled:
{ {
var packet = new Packets.PedKilled(); HandlePedKilled(msg.GetPacket<Packets.PedKilled>());
packet.Deserialize(data);
HandlePedKilled(packet);
} }
break; break;
case PacketType.NozzleTransform: case PacketType.NozzleTransform:
{ {
var packet = new Packets.NozzleTransform(); HandleNozzleTransform(msg.GetPacket<Packets.NozzleTransform>());
packet.Deserialize(data);
HandleNozzleTransform(packet);
break; break;
} }
} }
Networking.Peer.Recycle(msg);
} }
#endregion #endregion

View File

@ -1,6 +1,5 @@
using System.Threading; using NAudio.Wave;
using System.Threading;
using NAudio.Wave;
namespace RageCoop.Client namespace RageCoop.Client
{ {

View File

@ -0,0 +1,64 @@
using GTA;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Client
{
/// <summary>
/// Class providing support for addon mods
/// </summary>
internal class AddOnDataProvider
{
public static int GetMuzzleIndex(Model model)
{
switch (model.Hash)
{
// f14a2
case -848721350:
return 48;
// f15e
case 881261972:
return 32;
// f16c
case -2051171080:
return 25;
// F22A
case 2061630439:
return 14;
// f35c
case -343547392:
return 44;
// mig29a
case 513887552:
return 18;
// su30sm
case -733985185:
return 34;
// su33
case -722216722:
return 34;
// su35s
case -268602544:
return 28;
// su57
case 1490050781:
return 21;
default:
return -1;
}
}
}
}

View File

@ -1,18 +1,19 @@
 
using GTA;
using GTA.Math;
using RageCoop.Core;
using SHVDN;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GTA.Math;
using GTA;
using SHVDN;
using RageCoop.Core;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace RageCoop.Client namespace RageCoop.Client
{ {
internal unsafe class MemPatch{ internal unsafe class MemPatch
private byte[] _data; {
private byte[] _orginal; private readonly byte[] _data;
private IntPtr _address; private readonly byte[] _orginal;
private readonly IntPtr _address;
public MemPatch(byte* address, byte[] data) public MemPatch(byte* address, byte[] data)
{ {
_data = data; _data = data;
@ -68,8 +69,8 @@ internal static unsafe class Memory
public const int MatrixOffset = 96; public const int MatrixOffset = 96;
#endregion #endregion
#region OPCODE #region OPCODE
const byte XOR_32_64 = 0x31; private const byte XOR_32_64 = 0x31;
const byte RET = 0xC3; private const byte RET = 0xC3;
#endregion #endregion
public static Vector3 ReadPosition(this Entity e) => ReadVector3(e.MemoryAddress + PositionOffset); public static Vector3 ReadPosition(this Entity e) => ReadVector3(e.MemoryAddress + PositionOffset);
public static Quaternion ReadQuaternion(this Entity e) => Quaternion.RotationMatrix(e.Matrix); public static Quaternion ReadQuaternion(this Entity e) => Quaternion.RotationMatrix(e.Matrix);

View File

@ -1,14 +1,7 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA;
using GTA.Native; using GTA.Native;
using GTA.Math; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using LemonUI.Elements;
using System.Drawing;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -68,16 +61,16 @@ namespace RageCoop.Client
{ {
// These are borrowed from ScriptHookVDotNet's // These are borrowed from ScriptHookVDotNet's
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeInit@@YAX_K@Z")] [DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeInit@@YAX_K@Z")]
static extern void NativeInit(ulong hash); private static extern void NativeInit(ulong hash);
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativePush64@@YAX_K@Z")] [DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativePush64@@YAX_K@Z")]
static extern void NativePush64(ulong val); private static extern void NativePush64(ulong val);
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeCall@@YAPEA_KXZ")] [DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeCall@@YAPEA_KXZ")]
static extern unsafe ulong* NativeCall(); private static extern unsafe ulong* NativeCall();
// These are from ScriptHookV's nativeCaller.h // These are from ScriptHookV's nativeCaller.h
static unsafe void NativePush<T>(T val) where T : unmanaged private static unsafe void NativePush<T>(T val) where T : unmanaged
{ {
ulong val64 = 0; ulong val64 = 0;
*(T*)(&val64) = val; *(T*)(&val64) = val;
@ -106,7 +99,7 @@ namespace RageCoop.Client
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
static unsafe ulong[] ConvertPrimitiveArguments(object[] args) private static unsafe ulong[] ConvertPrimitiveArguments(object[] args)
{ {
var result = new ulong[args.Length]; var result = new ulong[args.Length];
for (int i = 0; i < args.Length; ++i) for (int i = 0; i < args.Length; ++i)
@ -118,7 +111,7 @@ namespace RageCoop.Client
} }
if (args[i] is byte valueByte) if (args[i] is byte valueByte)
{ {
result[i] = (ulong)valueByte; result[i] = valueByte;
continue; continue;
} }
if (args[i] is int valueInt32) if (args[i] is int valueInt32)

View File

@ -2,8 +2,8 @@
using GTA.Math; using GTA.Math;
using GTA.Native; using GTA.Native;
using RageCoop.Core; using RageCoop.Core;
using System.Collections.Generic;
using System; using System;
using System.Collections.Generic;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -146,7 +146,8 @@ namespace RageCoop.Client
{ {
flags |= PedDataFlags.IsInCover; flags |= PedDataFlags.IsInCover;
} }
if (!Function.Call<bool>(Hash.IS_PED_IN_HIGH_COVER, ped)){ if (!Function.Call<bool>(Hash.IS_PED_IN_HIGH_COVER, ped))
{
flags |= PedDataFlags.IsInLowCover; flags |= PedDataFlags.IsInLowCover;
} }
if (ped.IsTaskActive(TaskType.CTaskAimGunBlindFire)) if (ped.IsTaskActive(TaskType.CTaskAimGunBlindFire))
@ -295,7 +296,7 @@ namespace RageCoop.Client
{ {
result = true; result = true;
} }
else else if (veh.GetPedOnSeat(seat) != null)
{ {
bool isDead = veh.GetPedOnSeat(seat).IsDead; bool isDead = veh.GetPedOnSeat(seat).IsDead;

View File

@ -6,13 +6,10 @@ using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using System.Xml.Serialization; using System.Xml.Serialization;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")] [assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
namespace RageCoop.Client namespace RageCoop.Client
@ -219,7 +216,7 @@ namespace RageCoop.Client
#region WIN32 #region WIN32
const UInt32 WM_KEYDOWN = 0x0100; private const UInt32 WM_KEYDOWN = 0x0100;
public static void Reload() public static void Reload()
{ {
string reloadKey = "None"; string reloadKey = "None";
@ -238,6 +235,7 @@ namespace RageCoop.Client
foreach (var l in lines) foreach (var l in lines)
{ {
var ss = l.Split('='); var ss = l.Split('=');
ss.ForEach(s => s.Replace(" ", ""));
if (ss.Length > 0 && ss[0] == "ReloadKey") if (ss.Length > 0 && ss[0] == "ReloadKey")
{ {
reloadKey = ss[1]; reloadKey = ss[1];
@ -268,7 +266,7 @@ namespace RageCoop.Client
} }
[DllImport("user32.dll")] [DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); private static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]

View File

@ -50,47 +50,54 @@ namespace RageCoop.Client
flags |= VehicleDataFlags.IsHornActive; flags |= VehicleDataFlags.IsHornActive;
} }
if (v.IsSubmarineCar && Function.Call<bool>(Hash._GET_IS_SUBMARINE_VEHICLE_TRANSFORMED, veh.Handle)) if (v.IsSubmarineCar && Function.Call<bool>(Hash.IS_VEHICLE_IN_SUBMARINE_MODE, veh.Handle))
{ {
flags |= VehicleDataFlags.IsTransformed; flags |= VehicleDataFlags.IsTransformed;
} }
if (v.IsAircraft) if (v.IsAircraft)
{ {
flags |= VehicleDataFlags.IsAircraft; flags |= VehicleDataFlags.IsAircraft;
} }
if (v.IsDeluxo && veh.IsDeluxoHovering()) if (v.IsDeluxo && veh.IsDeluxoHovering())
{ {
flags |= VehicleDataFlags.IsDeluxoHovering; flags |= VehicleDataFlags.IsDeluxoHovering;
} }
if (v.HasRoof) if (v.HasRoof)
{ {
flags |= VehicleDataFlags.HasRoof; flags |= VehicleDataFlags.HasRoof;
} }
if (v.HasRocketBoost && veh.IsRocketBoostActive()) if (v.HasRocketBoost && veh.IsRocketBoostActive())
{ {
flags |= VehicleDataFlags.IsRocketBoostActive; flags |= VehicleDataFlags.IsRocketBoostActive;
} }
if(v.HasParachute && veh.IsParachuteActive()){
if (v.HasParachute && veh.IsParachuteActive())
{
flags |= VehicleDataFlags.IsParachuteActive; flags |= VehicleDataFlags.IsParachuteActive;
} }
if (veh.IsOnFire) if (veh.IsOnFire)
{ {
flags |= VehicleDataFlags.IsOnFire; flags |= VehicleDataFlags.IsOnFire;
} }
return flags; return flags;
} }
public static bool IsRocketBoostActive(this Vehicle veh) public static bool IsRocketBoostActive(this Vehicle veh)
{ {
return Function.Call<bool>(Hash._IS_VEHICLE_ROCKET_BOOST_ACTIVE,veh); return Function.Call<bool>(Hash.IS_ROCKET_BOOST_ACTIVE, veh);
} }
public static bool IsParachuteActive(this Vehicle veh){ public static bool IsParachuteActive(this Vehicle veh)
{
return Function.Call<bool>((Hash)0x3DE51E9C80B116CF, veh); return Function.Call<bool>((Hash)0x3DE51E9C80B116CF, veh);
} }
public static void SetRocketBoostActive(this Vehicle veh, bool toggle) public static void SetRocketBoostActive(this Vehicle veh, bool toggle)
{ {
Function.Call(Hash._SET_VEHICLE_ROCKET_BOOST_ACTIVE,veh,toggle); Function.Call(Hash.SET_ROCKET_BOOST_ACTIVE, veh, toggle);
} }
public static void SetParachuteActive(this Vehicle veh, bool toggle) public static void SetParachuteActive(this Vehicle veh, bool toggle)
{ {
@ -133,7 +140,6 @@ namespace RageCoop.Client
} }
} }
// Bursted tires // Bursted tires
short burstedTires = 0; short burstedTires = 0;
foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels()) foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels())
@ -228,16 +234,15 @@ namespace RageCoop.Client
{ {
if (p.IsSittingInVehicle()) if (p.IsSittingInVehicle())
{ {
ps.Add((int)p.SeatIndex, (int)p.GetSyncEntity().ID); ps.Add((int)p.SeatIndex, p.GetSyncEntity().ID);
} }
} }
return ps; return ps;
} }
public static void SetDeluxoHoverState(this Vehicle deluxo, bool hover) public static void SetDeluxoHoverState(this Vehicle deluxo, bool hover)
{ {
Function.Call(Hash._SET_VEHICLE_HOVER_TRANSFORM_PERCENTAGE, deluxo, hover ? 1f : 0f); Function.Call(Hash.SET_SPECIAL_FLIGHT_MODE_TARGET_RATIO, deluxo, hover ? 1f : 0f);
} }
public static bool IsDeluxoHovering(this Vehicle deluxo) public static bool IsDeluxoHovering(this Vehicle deluxo)
{ {
@ -245,7 +250,7 @@ namespace RageCoop.Client
} }
public static void SetDeluxoWingRatio(this Vehicle v, float ratio) public static void SetDeluxoWingRatio(this Vehicle v, float ratio)
{ {
Function.Call(Hash._SET_SPECIALFLIGHT_WING_RATIO, v, ratio); Function.Call(Hash.SET_HOVER_MODE_WING_RATIO, v, ratio);
} }
public static float GetDeluxoWingRatio(this Vehicle v) public static float GetDeluxoWingRatio(this Vehicle v)
{ {
@ -253,7 +258,7 @@ namespace RageCoop.Client
} }
public static float GetNozzleAngel(this Vehicle plane) public static float GetNozzleAngel(this Vehicle plane)
{ {
return Function.Call<float>(Hash._GET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane); return Function.Call<float>(Hash.GET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane);
} }
public static bool HasNozzle(this Vehicle v) public static bool HasNozzle(this Vehicle v)
{ {
@ -283,8 +288,6 @@ namespace RageCoop.Client
{ {
Function.Call(Hash.SET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane, ratio); Function.Call(Hash.SET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane, ratio);
} }
#endregion #endregion
} }
} }

View File

@ -2,7 +2,6 @@
using GTA.Math; using GTA.Math;
using GTA.Native; using GTA.Native;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -46,7 +45,8 @@ namespace RageCoop.Client
} }
return p.Bones[Bone.SkelRightHand].Position; return p.Bones[Bone.SkelRightHand].Position;
} }
static long BulletsShot = 0;
private static long BulletsShot = 0;
public static float GetWeaponDamage(this Ped P, uint hash) public static float GetWeaponDamage(this Ped P, uint hash)
{ {
@ -362,7 +362,7 @@ namespace RageCoop.Client
return 30; return 30;
default: default:
return -1; return AddOnDataProvider.GetMuzzleIndex(v.Model.Hash);
} }
} }
public static bool IsUsingProjectileWeapon(this Ped p) public static bool IsUsingProjectileWeapon(this Ped p)
@ -371,18 +371,12 @@ namespace RageCoop.Client
var type = Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, vp); var type = Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, vp);
if (vp != VehicleWeaponHash.Invalid) if (vp != VehicleWeaponHash.Invalid)
{ {
if (type==3) return type == 3 ? false : VehicleProjectileWeapons.Contains(vp) || (type == 5 && !ExplosiveBullets.Contains((uint)vp));
{
return false;
} }
return VehicleProjectileWeapons.Contains(vp) || (type==5 && !ExplosiveBullets.Contains((uint)vp));
}
else
{
var w = p.Weapons.Current; var w = p.Weapons.Current;
return w.Group == WeaponGroup.Thrown || ProjectileWeapons.Contains(w.Hash); return w.Group == WeaponGroup.Thrown || ProjectileWeapons.Contains(w.Hash);
} }
}
public static readonly HashSet<uint> ExplosiveBullets = new HashSet<uint> public static readonly HashSet<uint> ExplosiveBullets = new HashSet<uint>
{ {
@ -460,7 +454,6 @@ namespace RageCoop.Client
}; };
public static readonly HashSet<WeaponHash> ProjectileWeapons = new HashSet<WeaponHash> { public static readonly HashSet<WeaponHash> ProjectileWeapons = new HashSet<WeaponHash> {
WeaponHash.HomingLauncher, WeaponHash.HomingLauncher,
WeaponHash.RPG, WeaponHash.RPG,

View File

@ -1,8 +1,6 @@
using GTA; using GTA;
using GTA.Native; using GTA.Native;
using System; using System;
using System.Threading.Tasks;
using System.Threading;
namespace RageCoop.Client namespace RageCoop.Client
{ {
@ -22,28 +20,11 @@ namespace RageCoop.Client
{ {
ChangeTraffic(true); ChangeTraffic(true);
}; };
Task.Run(() =>
{
while (true)
{
Thread.Sleep(5000);
Main.QueueAction(() => { ChangeTraffic(_trafficEnabled); });
} }
});
} private static bool _trafficEnabled;
static bool _trafficEnabled;
private void OnTick(object sender, EventArgs e) private void OnTick(object sender, EventArgs e)
{ {
if (!_trafficEnabled)
{
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, 0);
Function.Call(Hash.SET_PED_POPULATION_BUDGET, 0);
Function.Call(Hash.SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
Function.Call(Hash.SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
Function.Call(Hash.SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
Function.Call(Hash.SUPPRESS_SHOCKING_EVENTS_NEXT_FRAME);
Function.Call(Hash.SUPPRESS_AGITATION_EVENTS_NEXT_FRAME);
}
if (Game.IsLoading || !Networking.IsOnServer) if (Game.IsLoading || !Networking.IsOnServer)
{ {
return; return;
@ -84,6 +65,16 @@ namespace RageCoop.Client
} }
} }
} }
if (!_trafficEnabled)
{
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, 0);
Function.Call(Hash.SET_PED_POPULATION_BUDGET, 0);
Function.Call(Hash.SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
Function.Call(Hash.SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
Function.Call(Hash.SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
Function.Call(Hash.SUPPRESS_SHOCKING_EVENTS_NEXT_FRAME);
Function.Call(Hash.SUPPRESS_AGITATION_EVENTS_NEXT_FRAME);
}
} }
public static void Traffic(bool enable) public static void Traffic(bool enable)
{ {
@ -94,7 +85,7 @@ namespace RageCoop.Client
{ {
if (enable) if (enable)
{ {
// Function.Call(Hash.REMOVE_SCENARIO_BLOCKING_AREAS); Function.Call(Hash.REMOVE_SCENARIO_BLOCKING_AREAS);
Function.Call(Hash.SET_CREATE_RANDOM_COPS, true); Function.Call(Hash.SET_CREATE_RANDOM_COPS, true);
Function.Call(Hash.SET_RANDOM_TRAINS, true); Function.Call(Hash.SET_RANDOM_TRAINS, true);
Function.Call(Hash.SET_RANDOM_BOATS, true); Function.Call(Hash.SET_RANDOM_BOATS, true);
@ -107,9 +98,9 @@ namespace RageCoop.Client
Function.Call(Hash.SET_DISTANT_CARS_ENABLED, true); Function.Call(Hash.SET_DISTANT_CARS_ENABLED, true);
Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, false); Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, false);
} }
else else if (Networking.IsOnServer)
{ {
// Function.Call(Hash.ADD_SCENARIO_BLOCKING_AREA, -10000.0f, -10000.0f, -1000.0f, 10000.0f, 10000.0f, 1000.0f, 0, 1, 1, 1); Function.Call(Hash.ADD_SCENARIO_BLOCKING_AREA, -10000.0f, -10000.0f, -1000.0f, 10000.0f, 10000.0f, 1000.0f, 0, 1, 1, 1);
Function.Call(Hash.SET_CREATE_RANDOM_COPS, false); Function.Call(Hash.SET_CREATE_RANDOM_COPS, false);
Function.Call(Hash.SET_RANDOM_TRAINS, false); Function.Call(Hash.SET_RANDOM_TRAINS, false);
Function.Call(Hash.SET_RANDOM_BOATS, false); Function.Call(Hash.SET_RANDOM_BOATS, false);
@ -122,29 +113,24 @@ namespace RageCoop.Client
Function.Call(Hash.SET_NUMBER_OF_PARKED_VEHICLES, 0); Function.Call(Hash.SET_NUMBER_OF_PARKED_VEHICLES, 0);
Function.Call(Hash.SET_DISTANT_CARS_ENABLED, false); Function.Call(Hash.SET_DISTANT_CARS_ENABLED, false);
Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, true); Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, true);
if (Networking.IsOnServer)
{
foreach (Ped ped in World.GetAllPeds()) foreach (Ped ped in World.GetAllPeds())
{ {
if (ped == Game.Player.Character) { continue; }
SyncedPed c = EntityPool.GetPedByHandle(ped.Handle); SyncedPed c = EntityPool.GetPedByHandle(ped.Handle);
if ((c == null) || (c.IsLocal && (ped.Handle != Game.Player.Character.Handle) && ped.PopulationType != EntityPopulationType.Mission)) if ((c == null) || (c.IsLocal && (ped.Handle != Game.Player.Character.Handle) && ped.PopulationType != EntityPopulationType.Mission))
{ {
if (ped.Handle == Game.Player.Character.Handle) { continue; }
// Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic"); Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic");
ped.CurrentVehicle?.Delete(); ped.CurrentVehicle?.Delete();
ped.Kill(); ped.Kill();
ped.Delete(); ped.Delete();
} }
} }
foreach (Vehicle veh in World.GetAllVehicles()) foreach (Vehicle veh in World.GetAllVehicles())
{ {
SyncedVehicle v = veh.GetSyncEntity(); SyncedVehicle v = veh.GetSyncEntity();
if (v.MainVehicle == Game.Player.LastVehicle) if (v.MainVehicle == Game.Player.LastVehicle || v.MainVehicle == Game.Player.Character.CurrentVehicle)
{ {
// Don't delete player's vehicle // Don't delete player's vehicle
continue; continue;
@ -157,32 +143,6 @@ namespace RageCoop.Client
} }
} }
} }
else
{
foreach (Ped ped in World.GetAllPeds())
{
if ((ped != Game.Player.Character) && (ped.PopulationType != EntityPopulationType.Mission))
{
// Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic");
ped.CurrentVehicle?.Delete();
ped.Kill();
ped.Delete();
}
}
var last = Game.Player.Character.LastVehicle;
var current = Game.Player.Character.CurrentVehicle;
foreach (Vehicle veh in World.GetAllVehicles())
{
if (veh.PopulationType != EntityPopulationType.Mission && veh != last && veh!=current)
{
// Main.Logger.Debug($"Removing Vehicle {veh.Handle}. Reason:ClearTraffic");
veh.Delete();
}
}
}
}
} }
} }
} }

View File

@ -1,8 +1,6 @@
using System; using GTA.Math;
using System.Text;
using System.Linq;
using GTA.Math;
using System.IO; using System.IO;
using System.Text;
namespace RageCoop.Core namespace RageCoop.Core
{ {

View File

@ -1,17 +1,18 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA.Math;
using System.Security.Cryptography;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.IO;
using System.Runtime.CompilerServices;
using Lidgren.Network; using Lidgren.Network;
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
[assembly: InternalsVisibleTo("RageCoop.Server")] [assembly: InternalsVisibleTo("RageCoop.Server")]
[assembly: InternalsVisibleTo("RageCoop.Client")] [assembly: InternalsVisibleTo("RageCoop.Client")]
@ -33,43 +34,44 @@ namespace RageCoop.Core
{ {
return ToIgnore.Contains(name); return ToIgnore.Contains(name);
} }
public static (byte, byte[]) GetBytesFromObject(object obj) public static void GetBytesFromObject(object obj, NetOutgoingMessage m)
{ {
switch (obj) switch (obj)
{ {
case byte _: case byte value:
return (0x01, new byte[] { (byte)obj }); m.Write((byte)0x01); m.Write(value); break;
case short _: case short value:
return (0x02, BitConverter.GetBytes((short)obj)); m.Write((byte)0x02); m.Write(value); break;
case ushort _: case ushort value:
return (0x03, BitConverter.GetBytes((ushort)obj)); m.Write((byte)0x03); m.Write(value); break;
case int _: case int value:
return (0x04, BitConverter.GetBytes((int)obj)); m.Write((byte)0x04); m.Write(value); break;
case uint _: case uint value:
return (0x05, BitConverter.GetBytes((uint)obj)); m.Write((byte)0x05); m.Write(value); break;
case long _: case long value:
return (0x06, BitConverter.GetBytes((long)obj)); m.Write((byte)0x06); m.Write(value); break;
case ulong _: case ulong value:
return (0x07, BitConverter.GetBytes((ulong)obj)); m.Write((byte)0x07); m.Write(value); break;
case float _: case float value:
return (0x08, BitConverter.GetBytes((float)obj)); m.Write((byte)0x08); m.Write(value); break;
case bool _: case bool value:
return (0x09, BitConverter.GetBytes((bool)obj)); m.Write((byte)0x09); m.Write(value); break;
case string _: case string value:
return (0x10, ((string)obj).GetBytesWithLength()); m.Write((byte)0x10); m.Write(value); break;
case Vector3 _: case Vector3 value:
return (0x11,((Vector3)obj).GetBytes()); m.Write((byte)0x11); m.Write(value); break;
case Quaternion _: case Quaternion value:
return (0x12, ((Quaternion)obj).GetBytes()); m.Write((byte)0x12); m.Write(value); break;
case GTA.Model _: case GTA.Model value:
return (0x13, BitConverter.GetBytes((GTA.Model)obj)); m.Write((byte)0x13); m.Write(value); break;
case Vector2 _: case Vector2 value:
return (0x14, ((Vector2)obj).GetBytes()); m.Write((byte)0x14); m.Write(value); break;
case Tuple<byte, byte[]> _: case byte[] value:
var tup = (Tuple<byte, byte[]>)obj; m.Write((byte)0x15); m.WriteByteArray(value); break;
return (tup.Item1, tup.Item2); case Tuple<byte, byte[]> value:
m.Write(value.Item1); m.Write(value.Item2); break;
default: default:
return (0x0, null); throw new Exception("Unsupported object type: " + obj.GetType());
} }
} }
public static IPEndPoint StringToEndPoint(string endpointstring) public static IPEndPoint StringToEndPoint(string endpointstring)
@ -136,9 +138,8 @@ namespace RageCoop.Core
private static int getPort(string p) private static int getPort(string p)
{ {
int port;
if (!int.TryParse(p, out port) if (!int.TryParse(p, out int port)
|| port < IPEndPoint.MinPort || port < IPEndPoint.MinPort
|| port > IPEndPoint.MaxPort) || port > IPEndPoint.MaxPort)
{ {
@ -190,7 +191,40 @@ namespace RageCoop.Core
foreach (FileInfo file in source.GetFiles()) foreach (FileInfo file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name), true); file.CopyTo(Path.Combine(target.FullName, file.Name), true);
} }
public static string GetInvariantRID()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return "win-" + RuntimeInformation.OSArchitecture.ToString().ToLower();
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "linux-" + RuntimeInformation.OSArchitecture.ToString().ToLower();
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return "osx-" + RuntimeInformation.OSArchitecture.ToString().ToLower();
}
return "unknown";
}
/// <summary>
/// Get local ip addresses on all network interfaces
/// </summary>
/// <returns></returns>
public static List<IPAddress> GetLocalAddress()
{
var addresses = new List<IPAddress>();
foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
{
IPInterfaceProperties ipProps = netInterface.GetIPProperties();
foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses)
{
addresses.Add(addr.Address);
}
}
return addresses;
}
} }
internal class IpInfo internal class IpInfo
{ {
@ -202,74 +236,10 @@ namespace RageCoop.Core
} }
internal static class Extensions internal static class Extensions
{ {
public static void AddVector3(this List<byte> bytes, Vector3 vec3)
{
bytes.AddRange(BitConverter.GetBytes(vec3.X));
bytes.AddRange(BitConverter.GetBytes(vec3.Y));
bytes.AddRange(BitConverter.GetBytes(vec3.Z));
}
public static void AddQuaternion(this List<byte> bytes, Quaternion quat)
{
bytes.AddRange(BitConverter.GetBytes(quat.X));
bytes.AddRange(BitConverter.GetBytes(quat.Y));
bytes.AddRange(BitConverter.GetBytes(quat.Z));
bytes.AddRange(BitConverter.GetBytes(quat.W));
}
public static void AddInt(this List<byte> bytes,int i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUint(this List<byte> bytes, uint i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddShort(this List<byte> bytes, short i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUshort(this List<byte> bytes, ushort i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddLong(this List<byte> bytes, long i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUlong(this List<byte> bytes, ulong i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddFloat(this List<byte> bytes, float i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddBool(this List<byte> bytes, bool b)
{
bytes.Add(b? (byte)1 :(byte)0);
}
public static void AddString(this List<byte> bytes, string s)
{
var sb = Encoding.UTF8.GetBytes(s);
bytes.AddInt(sb.Length);
bytes.AddRange(sb);
}
public static void AddArray(this List<byte> bytes, byte[] toadd)
{
bytes.AddInt(toadd.Length);
bytes.AddRange(toadd);
}
public static byte[] GetBytes(this string s) public static byte[] GetBytes(this string s)
{ {
return Encoding.UTF8.GetBytes(s); return Encoding.UTF8.GetBytes(s);
} }
public static byte[] GetBytesWithLength(this string s)
{
var data = new List<byte>(100);
var sb = Encoding.UTF8.GetBytes(s);
data.AddInt(sb.Length);
data.AddRange(sb);
return data.ToArray();
}
public static string GetString(this byte[] data) public static string GetString(this byte[] data)
{ {
return Encoding.UTF8.GetString(data); return Encoding.UTF8.GetString(data);
@ -296,17 +266,10 @@ namespace RageCoop.Core
// 16 bytes // 16 bytes
return new List<byte[]>() { BitConverter.GetBytes(qua.X), BitConverter.GetBytes(qua.Y), BitConverter.GetBytes(qua.Z), BitConverter.GetBytes(qua.W) }.Join(4); return new List<byte[]>() { BitConverter.GetBytes(qua.X), BitConverter.GetBytes(qua.Y), BitConverter.GetBytes(qua.Z), BitConverter.GetBytes(qua.W) }.Join(4);
} }
public static T GetPacket<T>(this NetIncomingMessage msg) where T : Packet, new()
public static T GetPacket<T>(this NetIncomingMessage msg, T existingPacket = null) where T : Packet, new()
{ {
msg.ReadByte(); var p = new T();
return GetPacket<T>(msg.ReadBytes(msg.ReadInt32()),existingPacket); p.Deserialize(msg);
}
public static T GetPacket<T>(this byte[] data, T existingPacket=null) where T : Packet, new()
{
var p = existingPacket??new T();
p.Deserialize(data);
return p; return p;
} }
public static bool HasPedFlag(this PedDataFlags flagToCheck, PedDataFlags flag) public static bool HasPedFlag(this PedDataFlags flagToCheck, PedDataFlags flag)
@ -399,7 +362,7 @@ namespace RageCoop.Core
} }
public static string Dump<T>(this IEnumerable<T> objects) public static string Dump<T>(this IEnumerable<T> objects)
{ {
return "{"+string.Join(",",objects)+"}"; return $"{{{string.Join(",", objects)}}}";
} }
public static void ForEach<T>(this IEnumerable<T> objects, Action<T> action) public static void ForEach<T>(this IEnumerable<T> objects, Action<T> action)
{ {
@ -482,5 +445,6 @@ namespace RageCoop.Core
{ {
return IPAddress.Parse(ip); return IPAddress.Parse(ip);
} }
} }
} }

View File

@ -1,8 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Text;
using System.Threading; using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
@ -32,9 +31,9 @@ namespace RageCoop.Core
private StreamWriter logWriter; private StreamWriter logWriter;
private string Buffer = ""; private string Buffer = "";
private Thread LoggerThread; private readonly Thread LoggerThread;
private bool Stopping = false; private bool Stopping = false;
private bool FlushImmediately; private readonly bool FlushImmediately;
internal Logger(bool flushImmediately = false, bool overwrite = true) internal Logger(bool flushImmediately = false, bool overwrite = true)
{ {

View File

@ -1,9 +1,8 @@
using System; using GTA.Math;
using GTA.Math; using System;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal static class MathExtensions internal static class MathExtensions
{ {
public const float Deg2Rad = (float)(Math.PI * 2) / 360; public const float Deg2Rad = (float)(Math.PI * 2) / 360;
@ -82,14 +81,14 @@ namespace RageCoop.Core
vect = vect.ToRadians(); vect = vect.ToRadians();
float rollOver2 = vect.Z * 0.5f; float rollOver2 = vect.Z * 0.5f;
float sinRollOver2 = (float)Math.Sin((double)rollOver2); float sinRollOver2 = (float)Math.Sin(rollOver2);
float cosRollOver2 = (float)Math.Cos((double)rollOver2); float cosRollOver2 = (float)Math.Cos(rollOver2);
float pitchOver2 = vect.Y * 0.5f; float pitchOver2 = vect.Y * 0.5f;
float sinPitchOver2 = (float)Math.Sin((double)pitchOver2); float sinPitchOver2 = (float)Math.Sin(pitchOver2);
float cosPitchOver2 = (float)Math.Cos((double)pitchOver2); float cosPitchOver2 = (float)Math.Cos(pitchOver2);
float yawOver2 = vect.X * 0.5f; // pitch float yawOver2 = vect.X * 0.5f; // pitch
float sinYawOver2 = (float)Math.Sin((double)yawOver2); float sinYawOver2 = (float)Math.Sin(yawOver2);
float cosYawOver2 = (float)Math.Cos((double)yawOver2); float cosYawOver2 = (float)Math.Cos(yawOver2);
Quaternion result = new Quaternion() Quaternion result = new Quaternion()
{ {
X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2, X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2,
@ -146,16 +145,12 @@ namespace RageCoop.Core
} }
private static float CopySign(double x, double y) private static float CopySign(double x, double y)
{ {
bool isPositive = y>=0; if (y >= 0)
if (isPositive)
{ {
if (x>=0) { return (float)x; } else { return (float)-x; } return x >= 0 ? (float)x : (float)-x;
} }
else
{
if (x>=0) { return (float)-x; } else { return (float)x; }
} return x >= 0 ? (float)-x : (float)x;
} }
public static double AngelTo(this Vector3 v1, Vector3 v2) public static double AngelTo(this Vector3 v1, Vector3 v2)
{ {
@ -163,7 +158,6 @@ namespace RageCoop.Core
} }
public static float GetCosTheta(this Vector3 v1, Vector3 v2) public static float GetCosTheta(this Vector3 v1, Vector3 v2)
{ {
return Vector3.Dot(v1, v2) / (v1.Length() * v2.Length()); return Vector3.Dot(v1, v2) / (v1.Length() * v2.Length());
} }

View File

@ -1,7 +1,6 @@
using System; using Lidgren.Network;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using System.Threading; using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
@ -57,6 +56,5 @@ namespace RageCoop.Core
p.Pack(outgoingMessage); p.Pack(outgoingMessage);
SendMessage(outgoingMessage, cons, method, (int)channel); SendMessage(outgoingMessage, cons, method, (int)channel);
} }
} }
} }

View File

@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.IO;
using System.Text;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.IO;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -32,7 +30,9 @@ namespace RageCoop.Core
{ {
// TLS only // TLS only
ServicePointManager.Expect100Continue = true; ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
WebClient client = new WebClient(); WebClient client = new WebClient();

View File

@ -1,17 +1,17 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal class PublicKey{ internal class PublicKey
public PublicKey(){ {
public PublicKey()
{
} }
public static PublicKey FromServerInfo(ServerInfo info){ public static PublicKey FromServerInfo(ServerInfo info)
return new PublicKey{ {
return new PublicKey
{
Modulus = Convert.FromBase64String(info.publicKeyModulus), Modulus = Convert.FromBase64String(info.publicKeyModulus),
Exponent = Convert.FromBase64String(info.publicKeyExponent) Exponent = Convert.FromBase64String(info.publicKeyExponent)
}; };

View File

@ -1,13 +1,11 @@
using System; namespace RageCoop.Core
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace RageCoop.Core
{ {
/// <summary>
internal class ServerInfo /// A json object representing a server's information as annouced to master server.
/// </summary>
public class ServerInfo
{ {
#pragma warning disable 1591
public string address { get; set; } public string address { get; set; }
public string port { get; set; } public string port { get; set; }
public string name { get; set; } public string name { get; set; }

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;
using System.Net;
using Newtonsoft.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace RageCoop.Core namespace RageCoop.Core
@ -93,7 +91,8 @@ namespace RageCoop.Core
} }
public static Dictionary<string, ZeroTierNetwork> Networks public static Dictionary<string, ZeroTierNetwork> Networks
{ {
get { get
{
Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>(); Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>();
var p = Run("listnetworks"); var p = Run("listnetworks");
var lines = Regex.Split(p.StandardOutput.ReadToEnd(), "\n").Skip(1); var lines = Regex.Split(p.StandardOutput.ReadToEnd(), "\n").Skip(1);

View File

@ -0,0 +1,71 @@
using GTA.Math;
using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Text;
namespace RageCoop.Core
{
internal static class PacketExtensions
{
#region MESSAGE-READ
public static Vector3 ReadVector3(this NetIncomingMessage m)
{
return new Vector3
{
X = m.ReadFloat(),
Y = m.ReadFloat(),
Z = m.ReadFloat(),
};
}
public static Vector2 ReadVector2(this NetIncomingMessage m)
{
return new Vector2
{
X = m.ReadFloat(),
Y = m.ReadFloat(),
};
}
public static Quaternion ReadQuaternion(this NetIncomingMessage m)
{
return new Quaternion
{
X = m.ReadFloat(),
Y = m.ReadFloat(),
Z = m.ReadFloat(),
W = m.ReadFloat(),
};
}
public static byte[] ReadByteArray(this NetIncomingMessage m)
{
return m.ReadBytes(m.ReadInt32());
}
#endregion
#region MESSAGE-WRITE
public static void Write(this NetOutgoingMessage m, Vector3 v)
{
m.Write(v.X);
m.Write(v.Y);
m.Write(v.Z);
}
public static void Write(this NetOutgoingMessage m, Quaternion q)
{
m.Write(q.X);
m.Write(q.Y);
m.Write(q.Z);
m.Write(q.W);
}
public static void WriteByteArray(this NetOutgoingMessage m, byte[] b)
{
m.Write(b.Length);
m.Write(b);
}
#endregion
internal static bool IsSyncEvent(this PacketType p)
{
return (30 <= (byte)p) && ((byte)p <= 40);
}
}
}

View File

@ -1,6 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -11,8 +10,8 @@ namespace RageCoop.Core
internal class ChatMessage : Packet internal class ChatMessage : Packet
{ {
public override PacketType Type => PacketType.ChatMessage; public override PacketType Type => PacketType.ChatMessage;
private Func<string, byte[]> crypt; private readonly Func<string, byte[]> crypt;
private Func<byte[], byte[]> decrypt; private readonly Func<byte[], byte[]> decrypt;
public ChatMessage(Func<string, byte[]> crypter) public ChatMessage(Func<string, byte[]> crypter)
{ {
crypt = crypter; crypt = crypter;
@ -25,33 +24,31 @@ namespace RageCoop.Core
public string Message { get; set; } public string Message { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// Write Username // Write Username
byteArray.AddString(Username); m.Write(Username);
// Write Message // Write Message
byteArray.AddArray(crypt(Message)); m.WriteByteArray(crypt(Message));
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read username // Read username
Username = reader.ReadString(); Username = m.ReadString();
Message = decrypt(reader.ReadByteArray()).GetString(); Message = decrypt(m.ReadByteArray()).GetString();
#endregion #endregion
} }
} }

View File

@ -1,7 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal partial class Packets internal partial class Packets
@ -10,85 +8,78 @@ namespace RageCoop.Core
internal class CustomEvent : Packet internal class CustomEvent : Packet
{ {
public override PacketType Type => (_queued ? PacketType.CustomEventQueued : PacketType.CustomEvent); public override PacketType Type => (_queued ? PacketType.CustomEventQueued : PacketType.CustomEvent);
public CustomEvent(Func<byte,BitReader,object> onResolve = null,bool queued=false) public CustomEvent(Func<byte, NetIncomingMessage, object> onResolve = null, bool queued = false)
{ {
_resolve = onResolve; _resolve = onResolve;
_queued = queued; _queued = queued;
} }
private bool _queued; private readonly bool _queued;
private Func<byte, BitReader, object> _resolve { get; set; } private Func<byte, NetIncomingMessage, object> _resolve { get; set; }
public int Hash { get; set; } public int Hash { get; set; }
public object[] Args { get; set; } public object[] Args { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
Args = Args ?? new object[] { }; Args = Args ?? new object[] { };
List<byte> result = new List<byte>(); m.Write(Hash);
result.AddInt(Hash); m.Write(Args.Length);
result.AddInt(Args.Length);
(byte, byte[]) tup;
foreach (var arg in Args) foreach (var arg in Args)
{ {
tup=CoreUtils.GetBytesFromObject(arg); CoreUtils.GetBytesFromObject(arg, m);
if (tup.Item1==0||tup.Item2==null)
{
throw new ArgumentException($"Object of type {arg.GetType()} is not supported");
} }
result.Add(tup.Item1);
result.AddRange(tup.Item2);
}
return result.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
BitReader reader = new BitReader(array);
Hash = reader.ReadInt32();
var len=reader.ReadInt32(); Hash = m.ReadInt32();
var len = m.ReadInt32();
Args = new object[len]; Args = new object[len];
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
byte type = reader.ReadByte(); byte type = m.ReadByte();
switch (type) switch (type)
{ {
case 0x01: case 0x01:
Args[i]=reader.ReadByte(); break; Args[i] = m.ReadByte(); break;
case 0x02: case 0x02:
Args[i]=reader.ReadInt32(); break; Args[i] = m.ReadInt32(); break;
case 0x03: case 0x03:
Args[i]=reader.ReadUInt16(); break; Args[i] = m.ReadUInt16(); break;
case 0x04: case 0x04:
Args[i]=reader.ReadInt32(); break; Args[i] = m.ReadInt32(); break;
case 0x05: case 0x05:
Args[i]=reader.ReadUInt32(); break; Args[i] = m.ReadUInt32(); break;
case 0x06: case 0x06:
Args[i]=reader.ReadInt64(); break; Args[i] = m.ReadInt64(); break;
case 0x07: case 0x07:
Args[i]=reader.ReadUInt64(); break; Args[i] = m.ReadUInt64(); break;
case 0x08: case 0x08:
Args[i]=reader.ReadSingle(); break; Args[i] = m.ReadFloat(); break;
case 0x09: case 0x09:
Args[i]=reader.ReadBoolean(); break; Args[i] = m.ReadBoolean(); break;
case 0x10: case 0x10:
Args[i]=reader.ReadString(); break; Args[i] = m.ReadString(); break;
case 0x11: case 0x11:
Args[i]=reader.ReadVector3(); break; Args[i] = m.ReadVector3(); break;
case 0x12: case 0x12:
Args[i]=reader.ReadQuaternion(); break; Args[i] = m.ReadQuaternion(); break;
case 0x13: case 0x13:
Args[i]=(GTA.Model)reader.ReadInt32(); break; Args[i] = (GTA.Model)m.ReadInt32(); break;
case 0x14: case 0x14:
Args[i]=reader.ReadVector2(); break; Args[i] = m.ReadVector2(); break;
case 0x15:
Args[i] = m.ReadByteArray(); break;
default: default:
if (_resolve == null) if (_resolve == null)
{ {
throw new InvalidOperationException($"Unexpected type:{type}\r\n{array.Dump()}"); throw new InvalidOperationException($"Unexpected type: {type}");
} }
else else
{ {
Args[i]=_resolve(type, reader); break; Args[i] = _resolve(type, m); break;
} }
} }
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -25,34 +22,30 @@ namespace RageCoop.Core
public long FileLength { get; set; } public long FileLength { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// The ID from the download // The ID from the download
byteArray.AddInt(ID); m.Write(ID);
// The name of the file // The name of the file
byte[] nameBytes = Encoding.UTF8.GetBytes(Name); m.Write(Name);
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
byteArray.AddRange(nameBytes);
// The length of the file // The length of the file
byteArray.AddRange(BitConverter.GetBytes(FileLength)); m.Write(FileLength);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
Name = reader.ReadString(); ID = m.ReadInt32();
FileLength = reader.ReadInt64(); Name = m.ReadString();
FileLength = m.ReadInt64();
} }
} }
@ -61,25 +54,21 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.FileTransferResponse; public override PacketType Type => PacketType.FileTransferResponse;
public int ID { get; set; } public int ID { get; set; }
public FileResponse Response { get; set; } public FileResponse Response { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// The ID from the download // The ID from the download
byteArray.AddInt(ID); m.Write(ID);
byteArray.Add((byte)Response); m.Write((byte)Response);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
BitReader reader = new BitReader(array);
ID = reader.ReadInt32(); ID = m.ReadInt32();
Response = (FileResponse)reader.ReadByte(); Response = (FileResponse)m.ReadByte();
} }
} }
@ -90,27 +79,21 @@ namespace RageCoop.Core
public byte[] FileChunk { get; set; } public byte[] FileChunk { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// The ID from the download // The ID from the download
byteArray.AddInt(ID); m.Write(ID);
m.WriteByteArray(FileChunk);
// The chunk of the file
byteArray.AddInt(FileChunk.Length);
byteArray.AddRange(FileChunk);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
BitReader reader = new BitReader(array);
ID = reader.ReadInt32(); ID = m.ReadInt32();
FileChunk = reader.ReadByteArray(); FileChunk = m.ReadByteArray();
} }
} }
@ -119,22 +102,20 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.FileTransferComplete; public override PacketType Type => PacketType.FileTransferComplete;
public int ID { get; set; } public int ID { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// The ID for the download // The ID for the download
byteArray.AddInt(ID); m.Write(ID);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
ID = m.ReadInt32();
} }
} }
internal class AllResourcesSent : Packet internal class AllResourcesSent : Packet

View File

@ -1,6 +1,4 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -14,26 +12,26 @@ namespace RageCoop.Core
public string TargetInternal { get; set; } public string TargetInternal { get; set; }
public string TargetExternal { get; set; } public string TargetExternal { get; set; }
public bool Connect { get; set; } public bool Connect { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddInt(TargetID); m.Write(TargetID);
byteArray.AddString(TargetInternal); m.Write(TargetInternal);
byteArray.AddString(TargetExternal); m.Write(TargetExternal);
byteArray.AddBool(Connect); m.Write(Connect);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
TargetID = reader.ReadInt32(); TargetID = m.ReadInt32();
TargetInternal = reader.ReadString(); TargetInternal = m.ReadString();
TargetExternal = reader.ReadString(); TargetExternal = m.ReadString();
Connect=reader.ReadBoolean(); Connect = m.ReadBoolean();
#endregion #endregion
} }
} }
@ -46,22 +44,22 @@ namespace RageCoop.Core
/// 1:initial, 2:acknowledged, 3:confirmed /// 1:initial, 2:acknowledged, 3:confirmed
/// </summary> /// </summary>
public byte Status { get; set; } public byte Status { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddInt(Puncher); m.Write(Puncher);
byteArray.Add(Status); m.Write(Status);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
Puncher = reader.ReadInt32(); Puncher = m.ReadInt32();
Status = reader.ReadByte(); Status = m.ReadByte();
#endregion #endregion
} }
} }

View File

@ -1,4 +1,4 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System.Collections.Generic;
namespace RageCoop.Core namespace RageCoop.Core
@ -12,16 +12,15 @@ namespace RageCoop.Core
{ {
public int TargetID { get; set; } public int TargetID { get; set; }
public override PacketType Type => PacketType.ConnectionRequest; public override PacketType Type => PacketType.ConnectionRequest;
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
var data = new List<byte>(10); var data = new List<byte>(10);
data.AddInt(TargetID); m.Write(TargetID);
return data.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
var reader=new BitReader(array);
TargetID = reader.ReadInt32(); TargetID = m.ReadInt32();
} }
} }
@ -33,16 +32,16 @@ namespace RageCoop.Core
{ {
public int ID { get; set; } public int ID { get; set; }
public override PacketType Type => PacketType.P2PConnect; public override PacketType Type => PacketType.P2PConnect;
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
var data = new List<byte>(10); var data = new List<byte>(10);
data.AddInt(ID); m.Write(ID);
return data.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
var reader = new BitReader(array);
ID = reader.ReadInt32(); ID = m.ReadInt32();
} }
} }
} }

View File

@ -1,9 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System;
using System.Text;
using Lidgren.Network;
using Newtonsoft.Json;
using GTA.Math;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -55,14 +51,6 @@ namespace RageCoop.Core
Unknown = 255 Unknown = 255
} }
internal static class PacketExtensions
{
internal static bool IsSyncEvent(this PacketType p)
{
return (30<=(byte)p)&&((byte)p<=40);
}
}
internal enum ConnectionChannel internal enum ConnectionChannel
{ {
Default = 0, Default = 0,
@ -153,25 +141,19 @@ namespace RageCoop.Core
internal interface IPacket internal interface IPacket
{ {
PacketType Type { get; } PacketType Type { get; }
byte[] Serialize();
void Deserialize(byte[] data); void Deserialize(NetIncomingMessage m);
} }
internal abstract class Packet : IPacket internal abstract class Packet : IPacket
{ {
public abstract PacketType Type { get; } public abstract PacketType Type { get; }
public virtual byte[] Serialize() public void Pack(NetOutgoingMessage m)
{ {
return new byte[0]; m.Write((byte)Type);
} Serialize(m);
public virtual void Deserialize(byte[] array) { }
public void Pack(NetOutgoingMessage message)
{
var d=Serialize();
message.Write((byte)Type);
message.Write(d.Length);
message.Write(d);
} }
protected virtual void Serialize(NetOutgoingMessage m) { }
public virtual void Deserialize(NetIncomingMessage m) { }
} }
} }

View File

@ -1,9 +1,7 @@
using System; using GTA;
using System.Collections.Generic;
using System.Text;
using GTA.Math; using GTA.Math;
using GTA;
using Lidgren.Network; using Lidgren.Network;
using System.Collections.Generic;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -61,92 +59,92 @@ namespace RageCoop.Core
public float BlipScale { get; set; } = 1; public float BlipScale { get; set; } = 1;
#endregion #endregion
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddInt(ID); m.Write(ID);
byteArray.AddInt(OwnerID); m.Write(OwnerID);
byteArray.AddRange(BitConverter.GetBytes((ushort)Flags)); m.Write((ushort)Flags);
byteArray.AddRange(BitConverter.GetBytes(Health)); m.Write(Health);
byteArray.Add(Speed); m.Write(Speed);
if (Flags.HasPedFlag(PedDataFlags.IsRagdoll)) if (Flags.HasPedFlag(PedDataFlags.IsRagdoll))
{ {
byteArray.AddVector3(HeadPosition); m.Write(HeadPosition);
byteArray.AddVector3(RightFootPosition); m.Write(RightFootPosition);
byteArray.AddVector3(LeftFootPosition); m.Write(LeftFootPosition);
} }
else else
{ {
if (Speed >= 4) if (Speed >= 4)
{ {
byteArray.AddInt(VehicleID); m.Write(VehicleID);
byteArray.Add((byte)(Seat+3)); m.Write((byte)(Seat + 3));
} }
byteArray.AddVector3(Position); m.Write(Position);
} }
byteArray.AddVector3(Rotation); m.Write(Rotation);
byteArray.AddVector3(Velocity); m.Write(Velocity);
if (Flags.HasPedFlag(PedDataFlags.IsAiming)) if (Flags.HasPedFlag(PedDataFlags.IsAiming))
{ {
byteArray.AddVector3(AimCoords); m.Write(AimCoords);
} }
byteArray.AddFloat(Heading); m.Write(Heading);
if (Flags.HasPedFlag(PedDataFlags.IsFullSync)) if (Flags.HasPedFlag(PedDataFlags.IsFullSync))
{ {
byteArray.AddInt(ModelHash); m.Write(ModelHash);
byteArray.AddUint(CurrentWeaponHash); m.Write(CurrentWeaponHash);
byteArray.AddRange(Clothes); m.Write(Clothes);
if (WeaponComponents != null) if (WeaponComponents != null)
{ {
byteArray.Add(0x01); m.Write(true);
byteArray.AddRange(BitConverter.GetBytes((ushort)WeaponComponents.Count)); m.Write((ushort)WeaponComponents.Count);
foreach (KeyValuePair<uint, bool> component in WeaponComponents) foreach (KeyValuePair<uint, bool> component in WeaponComponents)
{ {
byteArray.AddRange(BitConverter.GetBytes(component.Key)); m.Write(component.Key);
byteArray.AddRange(BitConverter.GetBytes(component.Value)); m.Write(component.Value);
} }
} }
else else
{ {
// Player weapon doesn't have any components // Player weapon doesn't have any components
byteArray.Add(0x00); m.Write(false);
} }
byteArray.Add(WeaponTint); m.Write(WeaponTint);
byteArray.Add((byte)BlipColor); m.Write((byte)BlipColor);
if ((byte)BlipColor != 255) if ((byte)BlipColor != 255)
{ {
byteArray.AddUshort((ushort)BlipSprite); m.Write((ushort)BlipSprite);
byteArray.AddFloat(BlipScale); m.Write(BlipScale);
} }
} }
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
OwnerID=reader.ReadInt32(); ID = m.ReadInt32();
Flags = (PedDataFlags)reader.ReadUInt16(); OwnerID = m.ReadInt32();
Health = reader.ReadInt32(); Flags = (PedDataFlags)m.ReadUInt16();
Speed = reader.ReadByte(); Health = m.ReadInt32();
Speed = m.ReadByte();
if (Flags.HasPedFlag(PedDataFlags.IsRagdoll)) if (Flags.HasPedFlag(PedDataFlags.IsRagdoll))
{ {
HeadPosition=reader.ReadVector3(); HeadPosition = m.ReadVector3();
RightFootPosition=reader.ReadVector3(); RightFootPosition = m.ReadVector3();
LeftFootPosition=reader.ReadVector3(); LeftFootPosition = m.ReadVector3();
Position = HeadPosition; Position = HeadPosition;
} }
else else
@ -154,54 +152,54 @@ namespace RageCoop.Core
// Vehicle related // Vehicle related
if (Speed >= 4) if (Speed >= 4)
{ {
VehicleID=reader.ReadInt32(); VehicleID = m.ReadInt32();
Seat=(VehicleSeat)(reader.ReadByte()-3); Seat = (VehicleSeat)(m.ReadByte() - 3);
} }
// Read player position // Read player position
Position = reader.ReadVector3(); Position = m.ReadVector3();
} }
Rotation = reader.ReadVector3(); Rotation = m.ReadVector3();
Velocity = reader.ReadVector3(); Velocity = m.ReadVector3();
if (Flags.HasPedFlag(PedDataFlags.IsAiming)) if (Flags.HasPedFlag(PedDataFlags.IsAiming))
{ {
// Read player aim coords // Read player aim coords
AimCoords = reader.ReadVector3(); AimCoords = m.ReadVector3();
} }
Heading=reader.ReadSingle(); Heading = m.ReadFloat();
if (Flags.HasPedFlag(PedDataFlags.IsFullSync)) if (Flags.HasPedFlag(PedDataFlags.IsFullSync))
{ {
// Read player model hash // Read player model hash
ModelHash = reader.ReadInt32(); ModelHash = m.ReadInt32();
// Read player weapon hash // Read player weapon hash
CurrentWeaponHash = reader.ReadUInt32(); CurrentWeaponHash = m.ReadUInt32();
// Read player clothes // Read player clothes
Clothes =reader.ReadBytes(36); Clothes = m.ReadBytes(36);
// Read player weapon components // Read player weapon components
if (reader.ReadBoolean()) if (m.ReadBoolean())
{ {
WeaponComponents = new Dictionary<uint, bool>(); WeaponComponents = new Dictionary<uint, bool>();
ushort comCount = reader.ReadUInt16(); ushort comCount = m.ReadUInt16();
for (ushort i = 0; i < comCount; i++) for (ushort i = 0; i < comCount; i++)
{ {
WeaponComponents.Add(reader.ReadUInt32(), reader.ReadBoolean()); WeaponComponents.Add(m.ReadUInt32(), m.ReadBoolean());
} }
} }
WeaponTint=reader.ReadByte(); WeaponTint = m.ReadByte();
BlipColor=(BlipColor)reader.ReadByte(); BlipColor = (BlipColor)m.ReadByte();
if ((byte)BlipColor != 255) if ((byte)BlipColor != 255)
{ {
BlipSprite=(BlipSprite)reader.ReadUInt16(); BlipSprite = (BlipSprite)m.ReadUInt16();
BlipScale=reader.ReadSingle(); BlipScale = m.ReadFloat();
} }
} }
#endregion #endregion

View File

@ -1,7 +1,5 @@
using System; using GTA.Math;
using System.Collections.Generic; using Lidgren.Network;
using System.Text;
using GTA.Math;
using System.Net; using System.Net;
namespace RageCoop.Core namespace RageCoop.Core
@ -38,62 +36,55 @@ namespace RageCoop.Core
public byte[] PasswordEncrypted { get; set; } public byte[] PasswordEncrypted { get; set; }
public IPEndPoint InternalEndPoint { get; set; } public IPEndPoint InternalEndPoint { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// Write Player Ped ID // Write Player Ped ID
byteArray.AddRange(BitConverter.GetBytes(PedID)); m.Write(PedID);
// Write Username // Write Username
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username); m.Write(Username);
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
byteArray.AddRange(usernameBytes);
// Write ModVersion // Write ModVersion
byte[] modVersionBytes = Encoding.UTF8.GetBytes(ModVersion); m.Write(ModVersion);
byteArray.AddRange(BitConverter.GetBytes(modVersionBytes.Length));
byteArray.AddRange(modVersionBytes);
byteArray.AddString(InternalEndPoint.ToString()); m.Write(InternalEndPoint.ToString());
// Write AesKeyCrypted // Write AesKeyCrypted
byteArray.AddArray(AesKeyCrypted); m.WriteByteArray(AesKeyCrypted);
// Write AesIVCrypted // Write AesIVCrypted
byteArray.AddArray(AesIVCrypted); m.WriteByteArray(AesIVCrypted);
// Write PassHash // Write PassHash
byteArray.AddArray(PasswordEncrypted); m.WriteByteArray(PasswordEncrypted);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle // Read player netHandle
PedID = reader.ReadInt32(); PedID = m.ReadInt32();
// Read Username // Read Username
Username = reader.ReadString(); Username = m.ReadString();
// Read ModVersion // Read ModVersion
ModVersion = reader.ReadString(); ModVersion = m.ReadString();
InternalEndPoint=CoreUtils.StringToEndPoint(reader.ReadString()); InternalEndPoint = CoreUtils.StringToEndPoint(m.ReadString());
AesKeyCrypted=reader.ReadByteArray(); AesKeyCrypted = m.ReadByteArray();
AesIVCrypted=reader.ReadByteArray(); AesIVCrypted = m.ReadByteArray();
PasswordEncrypted=reader.ReadByteArray(); PasswordEncrypted = m.ReadByteArray();
#endregion #endregion
} }
} }
@ -101,27 +92,25 @@ namespace RageCoop.Core
{ {
public PlayerData[] Players { get; set; } public PlayerData[] Players { get; set; }
public override PacketType Type => PacketType.HandshakeSuccess; public override PacketType Type => PacketType.HandshakeSuccess;
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
var data = new List<byte>(); m.Write(Players.Length);
data.AddInt(Players.Length);
foreach (var p in Players) foreach (var p in Players)
{ {
data.AddInt(p.ID); m.Write(p.ID);
data.AddString(p.Username); m.Write(p.Username);
} }
return data.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
var reader = new BitReader(array);
Players=new PlayerData[reader.ReadInt32()]; Players = new PlayerData[m.ReadInt32()];
for (int i = 0; i < Players.Length; i++) for (int i = 0; i < Players.Length; i++)
{ {
Players[i] = new PlayerData() Players[i] = new PlayerData()
{ {
ID=reader.ReadInt32(), ID = m.ReadInt32(),
Username=reader.ReadString(), Username = m.ReadString(),
}; };
} }
} }
@ -133,36 +122,24 @@ namespace RageCoop.Core
public string Username { get; set; } public string Username { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// Write NetHandle // Write NetHandle
byteArray.AddRange(BitConverter.GetBytes(PedID)); m.Write(PedID);
// Get Username bytes m.Write(Username);
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
// Write UsernameLength
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
// Write Username
byteArray.AddRange(usernameBytes);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle // Read player netHandle
PedID = reader.ReadInt32(); PedID = m.ReadInt32();
// Read Username // Read Username
Username = reader.ReadString(); Username = m.ReadString();
#endregion #endregion
} }
} }
@ -172,22 +149,18 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.PlayerDisconnect; public override PacketType Type => PacketType.PlayerDisconnect;
public int PedID { get; set; } public int PedID { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>(); m.Write(PedID);
byteArray.AddRange(BitConverter.GetBytes(PedID));
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
PedID = reader.ReadInt32(); PedID = m.ReadInt32();
#endregion #endregion
} }
} }
@ -203,42 +176,38 @@ namespace RageCoop.Core
public float Latency { get; set; } public float Latency { get; set; }
public Vector3 Position { get; set; } public Vector3 Position { get; set; }
public bool IsHost; public bool IsHost;
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// Write ID // Write ID
byteArray.AddRange(BitConverter.GetBytes(PedID)); m.Write(PedID);
// Write Username // Write Username
byteArray.AddString(Username); m.Write(Username);
// Write Latency // Write Latency
byteArray.AddFloat(Latency); m.Write(Latency);
byteArray.AddVector3(Position); m.Write(Position);
byteArray.AddBool(IsHost); m.Write(IsHost);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
BitReader reader = new BitReader(array);
// Read player ID // Read player ID
PedID = reader.ReadInt32(); PedID = m.ReadInt32();
// Read Username // Read Username
Username = reader.ReadString(); Username = m.ReadString();
Latency=reader.ReadSingle(); Latency = m.ReadFloat();
Position=reader.ReadVector3(); Position = m.ReadVector3();
IsHost=reader.ReadBoolean(); IsHost = m.ReadBoolean();
} }
} }
@ -249,24 +218,24 @@ namespace RageCoop.Core
public byte[] Modulus; public byte[] Modulus;
public byte[] Exponent; public byte[] Exponent;
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddArray(Modulus);
byteArray.AddArray(Exponent);
return byteArray.ToArray(); m.WriteByteArray(Modulus);
m.WriteByteArray(Exponent);
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
var reader=new BitReader(array);
Modulus=reader.ReadByteArray(); Modulus = m.ReadByteArray();
Exponent=reader.ReadByteArray(); Exponent = m.ReadByteArray();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -26,57 +23,57 @@ namespace RageCoop.Core
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// Write id // Write id
byteArray.AddInt(ID); m.Write(ID);
// Write ShooterID // Write ShooterID
byteArray.AddInt(ShooterID); m.Write(ShooterID);
byteArray.AddUint(WeaponHash); m.Write(WeaponHash);
// Write position // Write position
byteArray.AddVector3(Position); m.Write(Position);
// Write rotation // Write rotation
byteArray.AddVector3(Rotation); m.Write(Rotation);
// Write velocity // Write velocity
byteArray.AddVector3(Velocity); m.Write(Velocity);
byteArray.Add((byte)Flags); m.Write((byte)Flags);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read id // Read id
ID = reader.ReadInt32(); ID = m.ReadInt32();
// Read ShooterID // Read ShooterID
ShooterID= reader.ReadInt32(); ShooterID = m.ReadInt32();
WeaponHash= reader.ReadUInt32(); WeaponHash = m.ReadUInt32();
// Read position // Read position
Position = reader.ReadVector3(); Position = m.ReadVector3();
// Read rotation // Read rotation
Rotation = reader.ReadVector3(); Rotation = m.ReadVector3();
// Read velocity // Read velocity
Velocity =reader.ReadVector3(); Velocity = m.ReadVector3();
Flags=(ProjectileDataFlags)reader.ReadByte(); Flags = (ProjectileDataFlags)m.ReadByte();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -19,44 +16,44 @@ namespace RageCoop.Core
public Vector3 StartPosition { get; set; } public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; } public Vector3 EndPosition { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
// Write OwnerID // Write OwnerID
byteArray.AddRange(BitConverter.GetBytes(OwnerID)); m.Write(OwnerID);
// Write weapon hash // Write weapon hash
byteArray.AddRange(BitConverter.GetBytes(WeaponHash)); m.Write(WeaponHash);
// Write StartPosition // Write StartPosition
byteArray.AddVector3(StartPosition); m.Write(StartPosition);
// Write EndPosition // Write EndPosition
byteArray.AddVector3(EndPosition); m.Write(EndPosition);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read OwnerID // Read OwnerID
OwnerID=reader.ReadInt32(); OwnerID = m.ReadInt32();
// Read WeponHash // Read WeponHash
WeaponHash=reader.ReadUInt32(); WeaponHash = m.ReadUInt32();
// Read StartPosition // Read StartPosition
StartPosition=reader.ReadVector3(); StartPosition = m.ReadVector3();
// Read EndPosition // Read EndPosition
EndPosition=reader.ReadVector3(); EndPosition = m.ReadVector3();
#endregion #endregion
} }
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -15,24 +12,24 @@ namespace RageCoop.Core
public bool Hover { get; set; } public bool Hover { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddInt(VehicleID);
byteArray.AddBool(Hover);
return byteArray.ToArray(); m.Write(VehicleID);
m.Write(Hover);
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
VehicleID=reader.ReadInt32(); VehicleID = m.ReadInt32();
Hover=reader.ReadBoolean(); Hover = m.ReadBoolean();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -16,24 +13,19 @@ namespace RageCoop.Core
public int NewOwnerID { get; set; } public int NewOwnerID { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
m.Write(ID);
List<byte> byteArray = new List<byte>(); m.Write(NewOwnerID);
byteArray.AddInt(ID);
byteArray.AddInt(NewOwnerID);
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID=reader.ReadInt32();
NewOwnerID=reader.ReadInt32(); ID = m.ReadInt32();
NewOwnerID = m.ReadInt32();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -14,22 +11,22 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.PedKilled; public override PacketType Type => PacketType.PedKilled;
public int VictimID { get; set; } public int VictimID { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddInt(VictimID);
return byteArray.ToArray(); m.Write(VictimID);
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
VictimID=reader.ReadInt32();
VictimID = m.ReadInt32();
#endregion #endregion
} }

View File

@ -1,7 +1,5 @@
using System; using GTA.Math;
using System.Collections.Generic; using Lidgren.Network;
using System.Text;
using GTA.Math;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -18,31 +16,31 @@ namespace RageCoop.Core
public Vector3 StartPosition { get; set; } public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; } public Vector3 EndPosition { get; set; }
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>();
byteArray.AddInt(OwnerID);
byteArray.AddUshort(Bone);
byteArray.AddUint(WeaponHash);
byteArray.AddVector3(StartPosition);
byteArray.AddVector3(EndPosition);
return byteArray.ToArray(); m.Write(OwnerID);
m.Write(Bone);
m.Write(WeaponHash);
m.Write(StartPosition);
m.Write(EndPosition);
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
OwnerID=reader.ReadInt32();
Bone=reader.ReadUInt16(); OwnerID = m.ReadInt32();
WeaponHash=reader.ReadUInt32(); Bone = m.ReadUInt16();
StartPosition=reader.ReadVector3(); WeaponHash = m.ReadUInt32();
EndPosition=reader.ReadVector3(); StartPosition = m.ReadVector3();
EndPosition = m.ReadVector3();
#endregion #endregion
} }
} }

View File

@ -1,10 +1,7 @@
using System; using GTA;
using System.Collections.Generic;
using System.Text;
using GTA;
using GTA.Math; using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
using System.Linq; using System.Collections.Generic;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -58,200 +55,170 @@ namespace RageCoop.Core
public string LicensePlate { get; set; } public string LicensePlate { get; set; }
#endregion #endregion
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
List<byte> byteArray = new List<byte>(100);
byteArray.AddInt(ID); m.Write(ID);
byteArray.AddInt(OwnerID); m.Write(OwnerID);
byteArray.AddUshort((ushort)Flags); m.Write((ushort)Flags);
byteArray.AddVector3(Position); m.Write(Position);
byteArray.AddQuaternion(Quaternion); m.Write(Quaternion);
byteArray.AddVector3(Velocity); m.Write(Velocity);
byteArray.AddVector3(RotationVelocity); m.Write(RotationVelocity);
byteArray.AddFloat(ThrottlePower); m.Write(ThrottlePower);
byteArray.AddFloat(BrakePower); m.Write(BrakePower);
byteArray.AddFloat(SteeringAngle); m.Write(SteeringAngle);
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering)) if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering))
{ {
byteArray.AddFloat(DeluxoWingRatio); m.Write(DeluxoWingRatio);
} }
if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync)) if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
{ {
byteArray.AddInt(ModelHash); m.Write(ModelHash);
byteArray.AddFloat(EngineHealth); m.Write(EngineHealth);
// Check // Check
if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft)) if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft))
{ {
// Write the vehicle landing gear // Write the vehicle landing gear
byteArray.Add(LandingGear); m.Write(LandingGear);
} }
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof)) if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
{ {
byteArray.Add(RoofState); m.Write(RoofState);
} }
// Write vehicle colors // Write vehicle colors
byteArray.Add(Colors[0]); m.Write(Colors[0]);
byteArray.Add(Colors[1]); m.Write(Colors[1]);
// Write vehicle mods // Write vehicle mods
// Write the count of mods // Write the count of mods
byteArray.AddRange(BitConverter.GetBytes((short)Mods.Count)); m.Write((short)Mods.Count);
// Loop the dictionary and add the values // Loop the dictionary and add the values
foreach (KeyValuePair<int, int> mod in Mods) foreach (KeyValuePair<int, int> mod in Mods)
{ {
// Write the mod value // Write the mod value
byteArray.AddRange(BitConverter.GetBytes(mod.Key)); m.Write(mod.Key);
byteArray.AddRange(BitConverter.GetBytes(mod.Value)); m.Write(mod.Value);
} }
if (!DamageModel.Equals(default(VehicleDamageModel))) if (!DamageModel.Equals(default(VehicleDamageModel)))
{ {
// Write boolean = true // Write boolean = true
byteArray.Add(0x01); m.Write(true);
// Write vehicle damage model // Write vehicle damage model
byteArray.Add(DamageModel.BrokenDoors); m.Write(DamageModel.BrokenDoors);
byteArray.Add(DamageModel.OpenedDoors); m.Write(DamageModel.OpenedDoors);
byteArray.Add(DamageModel.BrokenWindows); m.Write(DamageModel.BrokenWindows);
byteArray.AddRange(BitConverter.GetBytes(DamageModel.BurstedTires)); m.Write(DamageModel.BurstedTires);
byteArray.Add(DamageModel.LeftHeadLightBroken); m.Write(DamageModel.LeftHeadLightBroken);
byteArray.Add(DamageModel.RightHeadLightBroken); m.Write(DamageModel.RightHeadLightBroken);
} }
else else
{ {
// Write boolean = false // Write boolean = false
byteArray.Add(0x00); m.Write(false);
} }
// Write LockStatus // Write LockStatus
byteArray.Add((byte)LockStatus); m.Write((byte)LockStatus);
// Write RadioStation // Write RadioStation
byteArray.Add(RadioStation); m.Write(RadioStation);
// Write LicensePlate // Write LicensePlate
while (LicensePlate.Length<8) m.Write(LicensePlate);
{
LicensePlate+=" ";
}
if (LicensePlate.Length>8)
{
LicensePlate=new string(LicensePlate.Take(8).ToArray());
}
byteArray.AddRange(Encoding.ASCII.GetBytes(LicensePlate));
byteArray.Add((byte)(Livery+1)); m.Write((byte)(Livery + 1));
} }
return byteArray.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read vehicle id ID = m.ReadInt32();
ID = reader.ReadInt32(); OwnerID = m.ReadInt32();
Flags = (VehicleDataFlags)m.ReadUInt16();
OwnerID = reader.ReadInt32(); Position = m.ReadVector3();
Quaternion = m.ReadQuaternion();
Flags=(VehicleDataFlags)reader.ReadUInt16(); Velocity = m.ReadVector3();
RotationVelocity = m.ReadVector3();
// Read position ThrottlePower = m.ReadFloat();
Position = reader.ReadVector3(); BrakePower = m.ReadFloat();
SteeringAngle = m.ReadFloat();
// Read quaternion
Quaternion=reader.ReadQuaternion();
// Read velocity
Velocity =reader.ReadVector3();
// Read rotation velocity
RotationVelocity=reader.ReadVector3();
// Read throttle power
ThrottlePower=reader.ReadSingle();
// Read brake power
BrakePower=reader.ReadSingle();
// Read steering angle
SteeringAngle = reader.ReadSingle();
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering)) if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering))
{ {
DeluxoWingRatio = reader.ReadSingle(); DeluxoWingRatio = m.ReadFloat();
} }
if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync)) if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
{ {
// Read vehicle model hash // Read vehicle model hash
ModelHash = reader.ReadInt32(); ModelHash = m.ReadInt32();
// Read vehicle engine health // Read vehicle engine health
EngineHealth = reader.ReadSingle(); EngineHealth = m.ReadFloat();
// Check // Check
if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft)) if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft))
{ {
// Read vehicle landing gear // Read vehicle landing gear
LandingGear = reader.ReadByte(); LandingGear = m.ReadByte();
} }
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof)) if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
{ {
RoofState=reader.ReadByte(); RoofState = m.ReadByte();
} }
// Read vehicle colors // Read vehicle colors
byte vehColor1 = reader.ReadByte(); byte vehColor1 = m.ReadByte();
byte vehColor2 = reader.ReadByte(); byte vehColor2 = m.ReadByte();
Colors = new byte[] { vehColor1, vehColor2 }; Colors = new byte[] { vehColor1, vehColor2 };
// Read vehicle mods // Read vehicle mods
// Create new Dictionary // Create new Dictionary
Mods = new Dictionary<int, int>(); Mods = new Dictionary<int, int>();
// Read count of mods // Read count of mods
short vehModCount = reader.ReadInt16(); short vehModCount = m.ReadInt16();
// Loop // Loop
for (int i = 0; i < vehModCount; i++) for (int i = 0; i < vehModCount; i++)
{ {
// Read the mod value // Read the mod value
Mods.Add(reader.ReadInt32(), reader.ReadInt32()); Mods.Add(m.ReadInt32(), m.ReadInt32());
} }
if (reader.ReadBoolean()) if (m.ReadBoolean())
{ {
// Read vehicle damage model // Read vehicle damage model
DamageModel = new VehicleDamageModel() DamageModel = new VehicleDamageModel()
{ {
BrokenDoors = reader.ReadByte(), BrokenDoors = m.ReadByte(),
OpenedDoors=reader.ReadByte(), OpenedDoors = m.ReadByte(),
BrokenWindows = reader.ReadByte(), BrokenWindows = m.ReadByte(),
BurstedTires = reader.ReadInt16(), BurstedTires = m.ReadInt16(),
LeftHeadLightBroken = reader.ReadByte(), LeftHeadLightBroken = m.ReadByte(),
RightHeadLightBroken = reader.ReadByte() RightHeadLightBroken = m.ReadByte()
}; };
} }
// Read LockStatus // Read LockStatus
LockStatus=(VehicleLockStatus)reader.ReadByte(); LockStatus = (VehicleLockStatus)m.ReadByte();
// Read RadioStation // Read RadioStation
RadioStation=reader.ReadByte(); RadioStation = m.ReadByte();
LicensePlate=Encoding.ASCII.GetString(reader.ReadBytes(8)); LicensePlate = m.ReadString();
Livery=(int)(reader.ReadByte()-1); Livery = m.ReadByte() - 1;
} }
#endregion #endregion
} }

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -10,20 +10,19 @@ namespace RageCoop.Core
public byte[] Buffer { get; set; } public byte[] Buffer { get; set; }
public int Recorded { get; set; } public int Recorded { get; set; }
public override PacketType Type => PacketType.Voice; public override PacketType Type => PacketType.Voice;
public override byte[] Serialize() protected override void Serialize(NetOutgoingMessage m)
{ {
var data = new List<byte>(); m.Write(ID);
data.AddInt(ID); m.Write(Buffer);
data.AddArray(Buffer); m.Write(Recorded);
data.AddInt(Recorded);
return data.ToArray();
} }
public override void Deserialize(byte[] array) public override void Deserialize(NetIncomingMessage m)
{ {
var reader = new BitReader(array);
ID = reader.ReadInt32(); ID = m.ReadInt32();
Buffer = reader.ReadByteArray(); Buffer = m.ReadByteArray();
Recorded = reader.ReadInt32(); Recorded = m.ReadInt32();
} }
} }
} }

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text;
namespace RageCoop.Core.Scripting namespace RageCoop.Core.Scripting
{ {
@ -10,8 +10,8 @@ namespace RageCoop.Core.Scripting
/// </summary> /// </summary>
public static class CustomEvents public static class CustomEvents
{ {
static MD5 Hasher = MD5.Create(); private static readonly MD5 Hasher = MD5.Create();
static Dictionary<int,string> Hashed=new Dictionary<int,string>(); private static readonly Dictionary<int, string> Hashed = new Dictionary<int, string>();
internal static readonly int OnPlayerDied = Hash("RageCoop.OnPlayerDied"); internal static readonly int OnPlayerDied = Hash("RageCoop.OnPlayerDied");
internal static readonly int SetWeather = Hash("RageCoop.SetWeather"); internal static readonly int SetWeather = Hash("RageCoop.SetWeather");
internal static readonly int OnPedDeleted = Hash("RageCoop.OnPedDeleted"); internal static readonly int OnPedDeleted = Hash("RageCoop.OnPedDeleted");
@ -40,26 +40,21 @@ namespace RageCoop.Core.Scripting
public static int Hash(string s) public static int Hash(string s)
{ {
var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0); var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0);
string name;
lock (Hashed) lock (Hashed)
{ {
if (Hashed.TryGetValue(hash, out name)) if (Hashed.TryGetValue(hash, out string name))
{ {
if (name != s) if (name != s)
{ {
throw new ArgumentException($"Hashed value has collision with another name:{name}, hashed value:{hash}"); throw new ArgumentException($"Hashed value has collision with another name:{name}, hashed value:{hash}");
} }
else
{
return hash; return hash;
} }
}
else
{
Hashed.Add(hash, s); Hashed.Add(hash, s);
return hash; return hash;
} }
} }
} }
} }
}

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
namespace RageCoop.Core.Scripting namespace RageCoop.Core.Scripting

View File

@ -1,6 +1,6 @@
using System; using System;
using System.Threading;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -9,8 +9,8 @@ namespace RageCoop.Core
/// </summary> /// </summary>
public class Worker : IDisposable public class Worker : IDisposable
{ {
private SemaphoreSlim _semaphoreSlim; private readonly SemaphoreSlim _semaphoreSlim;
private Thread _workerThread; private readonly Thread _workerThread;
private bool _stopping = false; private bool _stopping = false;
/// <summary> /// <summary>
/// Name of the worker /// Name of the worker
@ -81,6 +81,6 @@ namespace RageCoop.Core
Stop(); Stop();
_semaphoreSlim.Dispose(); _semaphoreSlim.Dispose();
} }
private ConcurrentQueue<Action> Jobs=new ConcurrentQueue<Action>(); private readonly ConcurrentQueue<Action> Jobs = new ConcurrentQueue<Action>();
} }
} }

View File

@ -1,12 +1,12 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using RageCoop.Core; using RageCoop.Core;
using Lidgren.Network;
using System.Diagnostics;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System.Security.Cryptography;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net; using System.Net;
using System.Security.Cryptography;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -28,7 +28,7 @@ namespace RageCoop.Server
/// <summary> /// <summary>
/// Th client's IP address and port. /// Th client's IP address and port.
/// </summary> /// </summary>
public IPEndPoint EndPoint { get { return Connection?.RemoteEndPoint; } } public IPEndPoint EndPoint => Connection?.RemoteEndPoint;
/// <summary> /// <summary>
/// Internal(LAN) address of this client, used for NAT hole-punching /// Internal(LAN) address of this client, used for NAT hole-punching
@ -62,23 +62,25 @@ namespace RageCoop.Server
/// <summary> /// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped. /// Gets or sets whether to enable automatic respawn for this client's main ped.
/// </summary> /// </summary>
public bool EnableAutoRespawn { public bool EnableAutoRespawn
get { return _autoRespawn; } {
set { get => _autoRespawn;
set
{
BaseScript.SetAutoRespawn(this, value); BaseScript.SetAutoRespawn(this, value);
_autoRespawn = value; _autoRespawn = value;
} }
} }
private bool _displayNameTag = true; private bool _displayNameTag = true;
private Stopwatch _latencyWatch = new Stopwatch(); private readonly Stopwatch _latencyWatch = new Stopwatch();
/// <summary> /// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped. /// Gets or sets whether to enable automatic respawn for this client's main ped.
/// </summary> /// </summary>
public bool DisplayNameTag public bool DisplayNameTag
{ {
get { return _displayNameTag; } get => _displayNameTag;
set set
{ {
Server.BaseScript.SetNameTag(this, value); Server.BaseScript.SetNameTag(this, value);

View File

@ -1,10 +1,4 @@
using System; namespace RageCoop.Server
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Server
{ {
internal class FileTransfer internal class FileTransfer
{ {

View File

@ -1,12 +1,4 @@
using System; namespace RageCoop.Server
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using RageCoop.Core;
namespace RageCoop.Server
{ {
internal class HolePunch internal class HolePunch
{ {

View File

@ -1,25 +1,23 @@
using System; using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
using Newtonsoft.Json;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Server.Scripting;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using Newtonsoft.Json;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
using System.Threading;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO; using System.Text;
using ICSharpCode.SharpZipLib.Zip; using System.Threading;
using System.Diagnostics;
namespace RageCoop.Server namespace RageCoop.Server
{ {
public partial class Server public partial class Server
{ {
const string _versionURL = "https://raw.githubusercontent.com/RAGECOOP/RAGECOOP-V/main/RageCoop.Server/Properties/AssemblyInfo.cs"; private const string _versionURL = "https://raw.githubusercontent.com/RAGECOOP/RAGECOOP-V/main/RageCoop.Server/Properties/AssemblyInfo.cs";
private void SendPlayerUpdate() private void SendPlayerUpdate()
{ {
foreach (var c in ClientsByNetHandle.Values.ToArray()) foreach (var c in ClientsByNetHandle.Values.ToArray())
@ -44,6 +42,7 @@ namespace RageCoop.Server
} }
} }
private IpInfo IpInfo = null; private IpInfo IpInfo = null;
private bool CanAnnounce = false;
private void Announce() private void Announce()
{ {
HttpResponseMessage response = null; HttpResponseMessage response = null;
@ -54,7 +53,10 @@ namespace RageCoop.Server
{ {
// TLS only // TLS only
ServicePointManager.Expect100Continue = true; ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 |
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
try try
@ -77,6 +79,19 @@ namespace RageCoop.Server
Logger?.Error($"MasterServer: {ex.Message}"); Logger?.Error($"MasterServer: {ex.Message}");
} }
} }
if (!CanAnnounce)
{
var existing = JsonConvert.DeserializeObject<List<ServerInfo>>(HttpHelper.DownloadString(Util.GetFinalRedirect(Settings.MasterServer))).Where(x => x.address == IpInfo.Address && x.port == Settings.Port.ToString()).FirstOrDefault();
if(existing != null)
{
Logger.Warning("Server info already present in master server, waiting for 10 seconds...");
return;
}
else
{
CanAnnounce = true;
}
}
try try
{ {
Security.GetPublicKey(out var pModulus, out var pExpoenet); Security.GetPublicKey(out var pModulus, out var pExpoenet);
@ -144,7 +159,7 @@ namespace RageCoop.Server
Thread.Sleep(10 * 60 * 1000); Thread.Sleep(10 * 60 * 1000);
API.SendChatMessage("downloading update..."); API.SendChatMessage("downloading update...");
var downloadURL = $"https://github.com/RAGECOOP/RAGECOOP-V/releases/download/nightly/RageCoop.Server-{GetRID()}.zip"; var downloadURL = $"https://github.com/RAGECOOP/RAGECOOP-V/releases/download/nightly/RageCoop.Server-{CoreUtils.GetInvariantRID()}.zip";
if (Directory.Exists("Update")) { Directory.Delete("Update", true); } if (Directory.Exists("Update")) { Directory.Delete("Update", true); }
HttpHelper.DownloadFile(downloadURL, "Update.zip", null); HttpHelper.DownloadFile(downloadURL, "Update.zip", null);
Logger?.Info("Installing update"); Logger?.Info("Installing update");
@ -161,23 +176,12 @@ namespace RageCoop.Server
Logger?.Error("Update", ex); Logger?.Error("Update", ex);
} }
} }
static string GetRID()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return "win-"+RuntimeInformation.OSArchitecture.ToString().ToLower();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "linux-"+RuntimeInformation.OSArchitecture.ToString().ToLower();
}
return "unknown";
}
private void KickAssholes() private void KickAssholes()
{ {
foreach (var c in ClientsByNetHandle.Values.ToArray()) foreach (var c in ClientsByNetHandle.Values.ToArray())
{ {
if (c.EntitiesCount > 100 && Settings.KickSpamming) if (c.EntitiesCount > Settings.SpamLimit && Settings.KickSpamming)
{ {
c.Kick("Bye bye asshole: spamming"); c.Kick("Bye bye asshole: spamming");
API.SendChatMessage($"Asshole {c.Username} was kicked: Spamming"); API.SendChatMessage($"Asshole {c.Username} was kicked: Spamming");

View File

@ -1,12 +1,10 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
using System.Linq;
using System.Text;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -43,6 +41,7 @@ namespace RageCoop.Server
connection.Deny("Username is already taken!"); connection.Deny("Username is already taken!");
return; return;
} }
try try
{ {
Security.AddConnection(connection.RemoteEndPoint, packet.AesKeyCrypted, packet.AesIVCrypted); Security.AddConnection(connection.RemoteEndPoint, packet.AesKeyCrypted, packet.AesIVCrypted);
@ -68,6 +67,7 @@ namespace RageCoop.Server
connection.Deny("Malformed handshak packet!"); connection.Deny("Malformed handshak packet!");
return; return;
} }
var handshakeSuccess = MainNetServer.CreateMessage(); var handshakeSuccess = MainNetServer.CreateMessage();
var currentClients = ClientsByID.Values.ToArray(); var currentClients = ClientsByID.Values.ToArray();
var players = new Packets.PlayerData[currentClients.Length]; var players = new Packets.PlayerData[currentClients.Length];
@ -79,6 +79,7 @@ namespace RageCoop.Server
Username = currentClients[i].Username, Username = currentClients[i].Username,
}; };
} }
new Packets.HandshakeSuccess() new Packets.HandshakeSuccess()
{ {
Players = players Players = players
@ -146,8 +147,6 @@ namespace RageCoop.Server
// Send all blips to this player // Send all blips to this player
BaseScript.SendServerBlipsTo(new(Entities.Blips.Values), new() { newClient }); BaseScript.SendServerBlipsTo(new(Entities.Blips.Values), new() { newClient });
// Create P2P connection // Create P2P connection
if (Settings.UseP2P) if (Settings.UseP2P)
{ {
@ -181,7 +180,7 @@ namespace RageCoop.Server
MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0); MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0);
} }
Entities.CleanUp(localClient); Entities.CleanUp(localClient);
_worker.QueueJob(() => API.Events.InvokePlayerDisconnected(localClient)); QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.Player.ID}"); Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.Player.ID}");
if (ClientsByNetHandle.ContainsKey(localClient.NetHandle)) { ClientsByNetHandle.Remove(localClient.NetHandle); } if (ClientsByNetHandle.ContainsKey(localClient.NetHandle)) { ClientsByNetHandle.Remove(localClient.NetHandle); }
if (ClientsByName.ContainsKey(localClient.Username.ToLower())) { ClientsByName.Remove(localClient.Username.ToLower()); } if (ClientsByName.ContainsKey(localClient.Username.ToLower())) { ClientsByName.Remove(localClient.Username.ToLower()); }

View File

@ -1,11 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
namespace RageCoop.Server namespace RageCoop.Server
@ -14,12 +8,12 @@ namespace RageCoop.Server
{ {
private void PedSync(Packets.PedSync packet, Client client) private void PedSync(Packets.PedSync packet, Client client)
{ {
_worker.QueueJob(() => Entities.Update(packet, client)); QueueJob(() => Entities.Update(packet, client));
bool isPlayer = packet.ID == client.Player.ID; bool isPlayer = packet.ID == client.Player.ID;
if (isPlayer) if (isPlayer)
{ {
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client)); QueueJob(() => API.Events.InvokePlayerUpdate(client));
} }
if (Settings.UseP2P) { return; } if (Settings.UseP2P) { return; }
@ -49,7 +43,7 @@ namespace RageCoop.Server
} }
private void VehicleSync(Packets.VehicleSync packet, Client client) private void VehicleSync(Packets.VehicleSync packet, Client client)
{ {
_worker.QueueJob(() => Entities.Update(packet, client)); QueueJob(() => Entities.Update(packet, client));
bool isPlayer = packet.ID == client.Player?.LastVehicle?.ID; bool isPlayer = packet.ID == client.Player?.LastVehicle?.ID;
@ -64,7 +58,6 @@ namespace RageCoop.Server
{ {
continue; continue;
} }
} }
else if ((Settings.NpcStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.NpcStreamingDistance)) else if ((Settings.NpcStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.NpcStreamingDistance))
{ {
@ -72,12 +65,11 @@ namespace RageCoop.Server
} }
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.Pack(outgoingMessage); packet.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.VehicleSync);
} }
} }
private void ProjectileSync(Packets.ProjectileSync packet, Client client) private void ProjectileSync(Packets.ProjectileSync packet, Client client)
{ {
if (Settings.UseP2P) { return; } if (Settings.UseP2P) { return; }
Forward(packet, client, ConnectionChannel.ProjectileSync); Forward(packet, client, ConnectionChannel.ProjectileSync);
} }

View File

@ -1,12 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
namespace RageCoop.Server namespace RageCoop.Server
{ {

View File

@ -1,12 +1,7 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -56,9 +51,7 @@ namespace RageCoop.Server
{ {
try try
{ {
int len = message.ReadInt32(); GetHandshake(message.SenderConnection, message.GetPacket<Packets.Handshake>());
byte[] data = message.ReadBytes(len);
GetHandshake(message.SenderConnection, data.GetPacket<Packets.Handshake>());
} }
catch (Exception e) catch (Exception e)
{ {
@ -86,7 +79,7 @@ namespace RageCoop.Server
else if (status == NetConnectionStatus.Connected) else if (status == NetConnectionStatus.Connected)
{ {
PlayerConnected(sender); PlayerConnected(sender);
_worker.QueueJob(() => API.Events.InvokePlayerConnected(sender)); QueueJob(() => API.Events.InvokePlayerConnected(sender));
Resources.SendTo(sender); Resources.SendTo(sender);
} }
break; break;
@ -106,7 +99,7 @@ namespace RageCoop.Server
int id = message.ReadInt32(); int id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback)) if (PendingResponses.TryGetValue(id, out var callback))
{ {
callback((PacketType)message.ReadByte(), message.ReadBytes(message.ReadInt32())); callback((PacketType)message.ReadByte(), message);
PendingResponses.Remove(id); PendingResponses.Remove(id);
} }
break; break;
@ -114,19 +107,23 @@ namespace RageCoop.Server
case PacketType.Request: case PacketType.Request:
{ {
int id = message.ReadInt32(); int id = message.ReadInt32();
if (RequestHandlers.TryGetValue((PacketType)message.ReadByte(), out var handler)) var reqType = (PacketType)message.ReadByte();
if (RequestHandlers.TryGetValue(reqType, out var handler))
{ {
var response = MainNetServer.CreateMessage(); var response = MainNetServer.CreateMessage();
response.Write((byte)PacketType.Response); response.Write((byte)PacketType.Response);
response.Write(id); response.Write(id);
handler(message.ReadBytes(message.ReadInt32()), sender).Pack(response); handler(message, sender).Pack(response);
MainNetServer.SendMessage(response, message.SenderConnection, NetDeliveryMethod.ReliableOrdered); MainNetServer.SendMessage(response, message.SenderConnection, NetDeliveryMethod.ReliableOrdered);
} }
else
{
Logger.Warning("Did not find a request handler of type: " + reqType);
}
break; break;
} }
default: default:
{ {
byte[] data = message.ReadBytes(message.ReadInt32());
if (type.IsSyncEvent()) if (type.IsSyncEvent())
{ {
// Sync Events // Sync Events
@ -139,8 +136,7 @@ namespace RageCoop.Server
{ {
var outgoingMessage = MainNetServer.CreateMessage(); var outgoingMessage = MainNetServer.CreateMessage();
outgoingMessage.Write((byte)type); outgoingMessage.Write((byte)type);
outgoingMessage.Write(data.Length); outgoingMessage.Write(message.ReadBytes(message.LengthBytes - 1));
outgoingMessage.Write(data);
MainNetServer.SendMessage(outgoingMessage, toSend, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.SyncEvents); MainNetServer.SendMessage(outgoingMessage, toSend, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.SyncEvents);
} }
} }
@ -151,7 +147,7 @@ namespace RageCoop.Server
} }
else else
{ {
HandlePacket(type, data, sender); HandlePacket(type, message, sender);
} }
break; break;
} }
@ -191,22 +187,22 @@ namespace RageCoop.Server
MainNetServer.Recycle(message); MainNetServer.Recycle(message);
} }
private void HandlePacket(PacketType type, byte[] data, Client sender) private void HandlePacket(PacketType type, NetIncomingMessage msg, Client sender)
{ {
try try
{ {
switch (type) switch (type)
{ {
case PacketType.PedSync: case PacketType.PedSync:
PedSync(data.GetPacket<Packets.PedSync>(), sender); PedSync(msg.GetPacket<Packets.PedSync>(), sender);
break; break;
case PacketType.VehicleSync: case PacketType.VehicleSync:
VehicleSync(data.GetPacket<Packets.VehicleSync>(), sender); VehicleSync(msg.GetPacket<Packets.VehicleSync>(), sender);
break; break;
case PacketType.ProjectileSync: case PacketType.ProjectileSync:
ProjectileSync(data.GetPacket<Packets.ProjectileSync>(), sender); ProjectileSync(msg.GetPacket<Packets.ProjectileSync>(), sender);
break; break;
case PacketType.ChatMessage: case PacketType.ChatMessage:
@ -215,7 +211,7 @@ namespace RageCoop.Server
{ {
return Security.Decrypt(b, sender.EndPoint); return Security.Decrypt(b, sender.EndPoint);
}); });
packet.Deserialize(data); packet.Deserialize(msg);
ChatMessageReceived(packet.Username, packet.Message, sender); ChatMessageReceived(packet.Username, packet.Message, sender);
} }
break; break;
@ -224,7 +220,7 @@ namespace RageCoop.Server
{ {
if (Settings.UseVoice && !Settings.UseP2P) if (Settings.UseVoice && !Settings.UseP2P)
{ {
Forward(data.GetPacket<Packets.Voice>(), sender, ConnectionChannel.Voice); Forward(msg.GetPacket<Packets.Voice>(), sender, ConnectionChannel.Voice);
} }
} }
break; break;
@ -232,8 +228,8 @@ namespace RageCoop.Server
case PacketType.CustomEvent: case PacketType.CustomEvent:
{ {
Packets.CustomEvent packet = new Packets.CustomEvent(); Packets.CustomEvent packet = new Packets.CustomEvent();
packet.Deserialize(data); packet.Deserialize(msg);
_worker.QueueJob(() => API.Events.InvokeCustomEventReceived(packet, sender)); QueueJob(() => API.Events.InvokeCustomEventReceived(packet, sender));
} }
break; break;
default: default:

View File

@ -1,23 +1,16 @@
using System; using Lidgren.Network;
using System.Diagnostics;
using System.Text;
using System.Net;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Net.Http;
using RageCoop.Core; using RageCoop.Core;
using Newtonsoft.Json;
using Lidgren.Network;
using System.Timers;
using System.Security.Cryptography;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
using System.Net.Sockets;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -42,7 +35,7 @@ namespace RageCoop.Server
internal readonly Dictionary<int, Client> ClientsByID = new(); internal readonly Dictionary<int, Client> ClientsByID = new();
internal Client _hostClient; internal Client _hostClient;
private Dictionary<int,FileTransfer> InProgressFileTransfers=new(); private readonly Dictionary<int, FileTransfer> InProgressFileTransfers = new();
internal Resources Resources; internal Resources Resources;
internal Logger Logger; internal Logger Logger;
internal Security Security; internal Security Security;
@ -54,8 +47,8 @@ namespace RageCoop.Server
private readonly Timer _updateTimer = new(); private readonly Timer _updateTimer = new();
private readonly Worker _worker; private readonly Worker _worker;
private readonly HashSet<char> _allowedCharacterSet; private readonly HashSet<char> _allowedCharacterSet;
private Dictionary<int,Action<PacketType,byte[]>> PendingResponses=new(); private readonly Dictionary<int, Action<PacketType, NetIncomingMessage>> PendingResponses = new();
internal Dictionary<PacketType, Func<byte[],Client,Packet>> RequestHandlers=new(); internal Dictionary<PacketType, Func<NetIncomingMessage, Client, Packet>> RequestHandlers = new();
/// <summary> /// <summary>
/// Get the current server version /// Get the current server version
/// </summary> /// </summary>
@ -118,11 +111,22 @@ namespace RageCoop.Server
public void Start() public void Start()
{ {
Logger?.Info("================"); Logger?.Info("================");
Logger?.Info($"Server bound to: 0.0.0.0:{Settings.Port}"); Logger?.Info($"Listening port: {Settings.Port}");
Logger?.Info($"Server version: {Version}"); Logger?.Info($"Server version: {Version}");
Logger?.Info($"Compatible RAGECOOP versions: {Version.ToString(3)}"); Logger?.Info($"Compatible client version: {Version.ToString(3)}");
Logger?.Info($"Runtime: {CoreUtils.GetInvariantRID()} => {System.Runtime.InteropServices.RuntimeInformation.RuntimeIdentifier}");
Logger?.Info("================"); Logger?.Info("================");
Logger?.Info($"Listening addresses:");
foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
{
Logger?.Info($"[{netInterface.Description}]:");
IPInterfaceProperties ipProps = netInterface.GetIPProperties();
foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses)
{
Logger.Info(string.Join(", ", addr.Address));
}
Logger.Info("");
}
if (Settings.UseZeroTier) if (Settings.UseZeroTier)
{ {
Logger?.Info($"Joining ZeroTier network: " + Settings.ZeroTierNetworkID); Logger?.Info($"Joining ZeroTier network: " + Settings.ZeroTierNetworkID);
@ -151,12 +155,12 @@ namespace RageCoop.Server
MainNetServer = new NetServer(config); MainNetServer = new NetServer(config);
MainNetServer.Start(); MainNetServer.Start();
Logger?.Info(string.Format("Server listening on {0}:{1}", config.LocalAddress.ToString(), config.Port));
BaseScript.API = API; BaseScript.API = API;
BaseScript.OnStart(); BaseScript.OnStart();
Resources.LoadAll(); Resources.LoadAll();
_listenerThread.Start(); _listenerThread.Start();
Logger?.Info("Listening for clients");
_playerUpdateTimer.Enabled = true; _playerUpdateTimer.Enabled = true;
if (Settings.AnnounceSelf) if (Settings.AnnounceSelf)
{ {
@ -169,7 +173,6 @@ namespace RageCoop.Server
_antiAssholesTimer.Enabled = true; _antiAssholesTimer.Enabled = true;
Logger?.Info("Listening for clients");
} }
/// <summary> /// <summary>
/// Terminate threads and stop the server /// Terminate threads and stop the server
@ -196,12 +199,12 @@ namespace RageCoop.Server
{ {
string[] cmdArgs = message.Split(" "); string[] cmdArgs = message.Split(" ");
string cmdName = cmdArgs[0].Remove(0, 1); string cmdName = cmdArgs[0].Remove(0, 1);
_worker.QueueJob(()=>API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender)); QueueJob(() => API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender));
return; return;
} }
message = message.Replace("~", ""); message = message.Replace("~", "");
_worker.QueueJob(() => API.Events.InvokeOnChatMessage(message, sender)); QueueJob(() => API.Events.InvokeOnChatMessage(message, sender));
foreach (var c in ClientsByNetHandle.Values) foreach (var c in ClientsByNetHandle.Values)
{ {
@ -273,12 +276,13 @@ namespace RageCoop.Server
{ {
throw new InvalidOperationException("Cannot wait for response from the listener thread!"); throw new InvalidOperationException("Cannot wait for response from the listener thread!");
} }
var received = new AutoResetEvent(false); var received = new AutoResetEvent(false);
byte[] response=null; T response = new T();
var id = NewRequestID(); var id = NewRequestID();
PendingResponses.Add(id, (type,p) => PendingResponses.Add(id, (type, m) =>
{ {
response=p; response.Deserialize(m);
received.Set(); received.Set();
}); });
var msg = MainNetServer.CreateMessage(); var msg = MainNetServer.CreateMessage();
@ -288,15 +292,11 @@ namespace RageCoop.Server
MainNetServer.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableOrdered, (int)channel); MainNetServer.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableOrdered, (int)channel);
if (received.WaitOne(timeout)) if (received.WaitOne(timeout))
{ {
var p = new T(); return response;
p.Deserialize(response);
return p;
} }
else
{
return null; return null;
} }
}
internal void SendFile(string path, string name, Client client, Action<float> updateCallback = null) internal void SendFile(string path, string name, Client client, Action<float> updateCallback = null)
{ {
var fs = File.OpenRead(path); var fs = File.OpenRead(path);
@ -307,11 +307,9 @@ namespace RageCoop.Server
internal void SendFile(Stream stream, string name, Client client, int id = default, Action<float> updateCallback = null) internal void SendFile(Stream stream, string name, Client client, int id = default, Action<float> updateCallback = null)
{ {
stream.Seek(0, SeekOrigin.Begin); stream.Seek(0, SeekOrigin.Begin);
// Logger.Debug("1");
id = id == default ? NewFileID() : id; id = id == default ? NewFileID() : id;
// Logger.Debug("2");
var total = stream.Length; var total = stream.Length;
// Logger.Debug("3"); Logger?.Debug($"Requesting file transfer:{name}, {total}");
if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferRequest() if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferRequest()
{ {
FileLength = total, FileLength = total,
@ -320,8 +318,6 @@ namespace RageCoop.Server
}, ConnectionChannel.File)?.Response != FileResponse.NeedToDownload) }, ConnectionChannel.File)?.Response != FileResponse.NeedToDownload)
{ {
Logger?.Info($"Skipping file transfer \"{name}\" to {client.Username}"); Logger?.Info($"Skipping file transfer \"{name}\" to {client.Username}");
// stream.Close();
// stream.Dispose();
return; return;
} }
Logger?.Debug($"Initiating file transfer:{name}, {total}"); Logger?.Debug($"Initiating file transfer:{name}, {total}");
@ -362,8 +358,6 @@ namespace RageCoop.Server
{ {
Logger.Warning($"File trasfer to {client.Username} failed: " + name); Logger.Warning($"File trasfer to {client.Username} failed: " + name);
} }
// stream.Close();
// stream.Dispose();
Logger?.Debug($"All file chunks sent:{name}"); Logger?.Debug($"All file chunks sent:{name}");
InProgressFileTransfers.Remove(id); InProgressFileTransfers.Remove(id);
} }

View File

@ -1,27 +1,24 @@
using System; using RageCoop.Core;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using RageCoop.Core;
using Newtonsoft.Json;
using System.Linq;
namespace RageCoop.Server namespace RageCoop.Server
{ {
class Program internal class Program
{ {
private static bool Stopping = false; private static bool Stopping = false;
static Logger mainLogger; private static Logger mainLogger;
static void Main(string[] args)
private static void Main(string[] args)
{ {
if (args.Length >= 2 && args[0] == "update") if (args.Length >= 2 && args[0] == "update")
{ {
var target = args[1]; var target = args[1];
int i = 0; int i = 0;
while (i < 10) while (i++ < 10)
{ {
i++;
try try
{ {
Console.WriteLine("Applying update to " + target); Console.WriteLine("Applying update to " + target);
@ -99,11 +96,11 @@ namespace RageCoop.Server
private static void UnhandledException(object sender, UnhandledExceptionEventArgs e) private static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
mainLogger.Error($"Unhandled exception thrown from user thread:",e.ExceptionObject as Exception); mainLogger.Error($"Unhandled exception thrown from user thread", e.ExceptionObject as Exception);
mainLogger.Flush(); mainLogger.Flush();
} }
static void Fatal(Exception e) private static void Fatal(Exception e)
{ {
mainLogger.Error(e); mainLogger.Error(e);
mainLogger.Error($"Fatal error occurred, server shutting down."); mainLogger.Error($"Fatal error occurred, server shutting down.");

View File

@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Version information // Version information
[assembly: AssemblyVersion("1.5.3.107")] [assembly: AssemblyVersion("1.5.4.5")]
[assembly: AssemblyFileVersion("1.5.3.107")] [assembly: AssemblyFileVersion("1.5.4.5")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )] [assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -49,12 +49,12 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Fody" Version="6.6.3"> <PackageReference Include="Fody" Version="6.8.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="6.0.8" /> <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.9" />
<PackageReference Include="SharpZipLib" Version="1.3.3" /> <PackageReference Include="SharpZipLib" Version="1.4.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,13 +1,12 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System.Reflection; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -118,8 +117,7 @@ namespace RageCoop.Server.Scripting
internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender) internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender)
{ {
var args = new CustomEventReceivedArgs() { Hash = p.Hash, Args = p.Args, Client = sender }; var args = new CustomEventReceivedArgs() { Hash = p.Hash, Args = p.Args, Client = sender };
List<Action<CustomEventReceivedArgs>> handlers; if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
{ {
handlers.ForEach((x) => { x.Invoke(args); }); handlers.ForEach((x) => { x.Invoke(args); });
} }
@ -173,7 +171,7 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// All synchronized entities on this server. /// All synchronized entities on this server.
/// </summary> /// </summary>
public ServerEntities Entities { get { return Server.Entities; } } public ServerEntities Entities => Server.Entities;
#region FUNCTIONS #region FUNCTIONS
/// <summary> /// <summary>
@ -356,10 +354,9 @@ namespace RageCoop.Server.Scripting
/// <param name="handler">An handler to be invoked when the event is received from the server.</param> /// <param name="handler">An handler to be invoked when the event is received from the server.</param>
public void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler) public void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler)
{ {
List<Action<CustomEventReceivedArgs>> handlers;
lock (Events.CustomEventHandlers) lock (Events.CustomEventHandlers)
{ {
if (!Events.CustomEventHandlers.TryGetValue(hash,out handlers)) if (!Events.CustomEventHandlers.TryGetValue(hash, out List<Action<CustomEventReceivedArgs>> handlers))
{ {
Events.CustomEventHandlers.Add(hash, handlers = new List<Action<CustomEventReceivedArgs>>()); Events.CustomEventHandlers.Add(hash, handlers = new List<Action<CustomEventReceivedArgs>>());
} }
@ -415,7 +412,7 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Get a <see cref="Core.Logger"/> that the server is currently using, you should use <see cref="ServerResource.Logger"/> to display resource-specific information. /// Get a <see cref="Core.Logger"/> that the server is currently using, you should use <see cref="ServerResource.Logger"/> to display resource-specific information.
/// </summary> /// </summary>
public Logger Logger { get { return Server.Logger; } } public Logger Logger => Server.Logger;
/// <summary> /// <summary>
@ -423,8 +420,9 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public Client Host public Client Host
{ {
get { return Server._hostClient; } get => Server._hostClient;
set { set
{
if (Server._hostClient != value) if (Server._hostClient != value)
{ {
Server._hostClient?.SendCustomEvent(CustomEvents.IsHost, false); Server._hostClient?.SendCustomEvent(CustomEvents.IsHost, false);

View File

@ -1,10 +1,7 @@
using System; using RageCoop.Core.Scripting;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using RageCoop.Core;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -41,7 +38,7 @@ namespace RageCoop.Server.Scripting
}); });
API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) => API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) =>
{ {
API.SendCustomEventQueued(API.GetAllClients().Values.Where(x=>x!=e.Client).ToList(),CustomEvents.OnPlayerDied,e.Client.Username); API.SendCustomEventQueued(API.GetAllClients().Values.Where(x => x != e.Client).ToList(), CustomEvents.OnPlayerDied, e.Args);
}); });
API.Events.OnChatMessage += (s, e) => API.Events.OnChatMessage += (s, e) =>
Server.Logger?.Info((e.Client?.Username ?? e.ClaimedSender ?? "Unknown") + ": " + e.Message); Server.Logger?.Info((e.Client?.Username ?? e.ClaimedSender ?? "Unknown") + ": " + e.Message);
@ -75,15 +72,15 @@ namespace RageCoop.Server.Scripting
API.SendCustomEventQueued(clients, CustomEvents.ServerBlipSync, obj.ID, (ushort)obj.Sprite, (byte)obj.Color, obj.Scale, obj.Position, obj.Rotation, obj.Name); API.SendCustomEventQueued(clients, CustomEvents.ServerBlipSync, obj.ID, (ushort)obj.Sprite, (byte)obj.Color, obj.Scale, obj.Position, obj.Rotation, obj.Name);
} }
} }
void NativeResponse(CustomEventReceivedArgs e)
private void NativeResponse(CustomEventReceivedArgs e)
{ {
try try
{ {
int id = (int)e.Args[0]; int id = (int)e.Args[0];
Action<object> callback;
lock (e.Client.Callbacks) lock (e.Client.Callbacks)
{ {
if (e.Client.Callbacks.TryGetValue(id, out callback)) if (e.Client.Callbacks.TryGetValue(id, out Action<object> callback))
{ {
callback(e.Args[1]); callback(e.Args[1]);
e.Client.Callbacks.Remove(id); e.Client.Callbacks.Remove(id);

View File

@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net; using System.Net;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting

View File

@ -1,14 +1,9 @@
using System; using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using RageCoop.Core; using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using ICSharpCode.SharpZipLib.Zip; using System.Threading.Tasks;
using System.Reflection;
using McMaster.NETCore.Plugins;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
internal class Resources internal class Resources
@ -22,9 +17,8 @@ namespace RageCoop.Server.Scripting
Server = server; Server = server;
Logger = server.Logger; Logger = server.Logger;
} }
private Dictionary<string,Func<Stream>> ClientResources=new(); private readonly Dictionary<string, Stream> ClientResources = new();
private Dictionary<string,Func<Stream>> ResourceStreams=new(); private readonly Dictionary<string, Stream> ResourceStreams = new();
private List<MemoryStream> MemStreams = new();
public void LoadAll() public void LoadAll()
{ {
// Packages // Packages
@ -33,7 +27,7 @@ namespace RageCoop.Server.Scripting
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
foreach (var pkg in Directory.GetFiles(path, "*.respkg", SearchOption.AllDirectories)) foreach (var pkg in Directory.GetFiles(path, "*.respkg", SearchOption.AllDirectories))
{ {
Logger?.Debug($"Adding resourece from package \"{Path.GetFileNameWithoutExtension(pkg)}\""); Logger?.Debug($"Adding resources from package \"{Path.GetFileNameWithoutExtension(pkg)}\"");
var pkgZip = new ZipFile(pkg); var pkgZip = new ZipFile(pkg);
foreach (ZipEntry e in pkgZip) foreach (ZipEntry e in pkgZip)
{ {
@ -41,15 +35,13 @@ namespace RageCoop.Server.Scripting
if (e.Name.StartsWith("Client") && e.Name.EndsWith(".res")) if (e.Name.StartsWith("Client") && e.Name.EndsWith(".res"))
{ {
var stream = pkgZip.GetInputStream(e).ToMemStream(); var stream = pkgZip.GetInputStream(e).ToMemStream();
MemStreams.Add(stream); ClientResources.Add(Path.GetFileNameWithoutExtension(e.Name), stream);
ClientResources.Add(Path.GetFileNameWithoutExtension(e.Name), () => stream);
Logger?.Debug("Resource added: " + Path.GetFileNameWithoutExtension(e.Name)); Logger?.Debug("Resource added: " + Path.GetFileNameWithoutExtension(e.Name));
} }
else if (e.Name.StartsWith("Server") && e.Name.EndsWith(".res")) else if (e.Name.StartsWith("Server") && e.Name.EndsWith(".res"))
{ {
var stream = pkgZip.GetInputStream(e).ToMemStream(); var stream = pkgZip.GetInputStream(e).ToMemStream();
MemStreams.Add(stream); ResourceStreams.Add(Path.GetFileNameWithoutExtension(e.Name), stream);
ResourceStreams.Add(Path.GetFileNameWithoutExtension(e.Name), () => stream);
Logger?.Debug("Resource added: " + Path.GetFileNameWithoutExtension(e.Name)); Logger?.Debug("Resource added: " + Path.GetFileNameWithoutExtension(e.Name));
} }
} }
@ -91,7 +83,7 @@ namespace RageCoop.Server.Scripting
} }
zip.CommitUpdate(); zip.CommitUpdate();
zip.Close(); zip.Close();
ClientResources.Add(Path.GetFileNameWithoutExtension(zipPath), () => File.OpenRead(zipPath)); ClientResources.Add(Path.GetFileNameWithoutExtension(zipPath), File.OpenRead(zipPath));
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -105,7 +97,7 @@ namespace RageCoop.Server.Scripting
{ {
foreach (var file in packed) foreach (var file in packed)
{ {
ClientResources.Add(Path.GetFileNameWithoutExtension(file),()=>File.OpenRead(file)); ClientResources.Add(Path.GetFileNameWithoutExtension(file), File.OpenRead(file));
} }
} }
} }
@ -138,7 +130,7 @@ namespace RageCoop.Server.Scripting
} }
foreach (var res in Directory.GetFiles(path, "*.res", SearchOption.TopDirectoryOnly)) foreach (var res in Directory.GetFiles(path, "*.res", SearchOption.TopDirectoryOnly))
{ {
if (!ResourceStreams.TryAdd(Path.GetFileNameWithoutExtension(res),()=>File.OpenRead(res))) if (!ResourceStreams.TryAdd(Path.GetFileNameWithoutExtension(res), File.OpenRead(res)))
{ {
Logger?.Warning($"Resource \"{res}\" cannot be loaded, ignoring..."); Logger?.Warning($"Resource \"{res}\" cannot be loaded, ignoring...");
continue; continue;
@ -155,7 +147,7 @@ namespace RageCoop.Server.Scripting
continue; continue;
} }
Logger?.Info($"Loading resource: " + name); Logger?.Info($"Loading resource: " + name);
var r = ServerResource.LoadFrom(res.Value(),name, Path.Combine("Resources", "Temp", "Server"), dataFolder, Logger); var r = ServerResource.LoadFrom(res.Value, name, Path.Combine("Resources", "Temp", "Server"), dataFolder, Logger);
LoadedResources.Add(r.Name, r); LoadedResources.Add(r.Name, r);
} }
catch (Exception ex) catch (Exception ex)
@ -215,7 +207,7 @@ namespace RageCoop.Server.Scripting
} }
LoadedResources.Clear(); LoadedResources.Clear();
} }
foreach(var s in MemStreams) foreach (var s in ResourceStreams.Values)
{ {
try try
{ {
@ -224,13 +216,27 @@ namespace RageCoop.Server.Scripting
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger?.Error("[Resources.CloseMemStream]",ex); Logger?.Error("[Resources.CloseStream]", ex);
}
}
foreach (var s in ClientResources.Values)
{
try
{
s.Close();
s.Dispose();
}
catch (Exception ex)
{
Logger?.Error("[Resources.CloseStream]", ex);
} }
} }
} }
public void SendTo(Client client) public void SendTo(Client client)
{ {
Task.Run(() => Task.Run(() =>
{
try
{ {
if (ClientResources.Count != 0) if (ClientResources.Count != 0)
@ -239,7 +245,7 @@ namespace RageCoop.Server.Scripting
foreach (var rs in ClientResources) foreach (var rs in ClientResources)
{ {
Logger?.Debug(rs.Key); Logger?.Debug(rs.Key);
Server.SendFile(rs.Value(),rs.Key+".res", client); Server.SendFile(rs.Value, rs.Key + ".res", client);
} }
Logger?.Info($"Resources sent to:{client.Username}"); Logger?.Info($"Resources sent to:{client.Username}");
@ -253,6 +259,12 @@ namespace RageCoop.Server.Scripting
{ {
Logger?.Warning($"Client {client.Username} failed to load resource."); Logger?.Warning($"Client {client.Username} failed to load resource.");
} }
}
catch (Exception ex)
{
Logger.Error("Failed to send resource to client: " + client.Username, ex);
client.Kick("Resource error!");
}
}); });
} }
} }

View File

@ -1,14 +1,11 @@
using System; using GTA;
using System.Collections.Generic; using GTA.Math;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using GTA.Math;
using GTA;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -33,68 +30,28 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public ServerPed GetPedByID(int id) public ServerPed GetPedByID(int id) => Peds.TryGetValue(id, out var ped) ? ped : null;
{
if(Peds.TryGetValue(id,out var ped))
{
return ped;
}
else
{
return null;
}
}
/// <summary> /// <summary>
/// Get a <see cref="ServerVehicle"/> by it's id /// Get a <see cref="ServerVehicle"/> by it's id
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public ServerVehicle GetVehicleByID(int id) public ServerVehicle GetVehicleByID(int id) => Vehicles.TryGetValue(id, out var veh) ? veh : null;
{
if (Vehicles.TryGetValue(id, out var veh))
{
return veh;
}
else
{
return null;
}
}
/// <summary> /// <summary>
/// Get a <see cref="ServerProp"/> owned by server from it's ID. /// Get a <see cref="ServerProp"/> owned by server from it's ID.
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public ServerProp GetPropByID(int id) public ServerProp GetPropByID(int id) => ServerProps.TryGetValue(id, out var obj) ? obj : null;
{
if (ServerProps.TryGetValue(id, out var obj))
{
return obj;
}
else
{
return null;
}
}
/// <summary> /// <summary>
/// Get a <see cref="ServerBlip"/> by it's id. /// Get a <see cref="ServerBlip"/> by it's id.
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public ServerBlip GetBlipByID(int id) public ServerBlip GetBlipByID(int id) => Blips.TryGetValue(id, out var obj) ? obj : null;
{
if (Blips.TryGetValue(id, out var obj))
{
return obj;
}
else
{
return null;
}
}
/// <summary> /// <summary>
/// Create a static prop owned by server. /// Create a static prop owned by server.
@ -164,45 +121,32 @@ namespace RageCoop.Server.Scripting
/// Get all peds on this server /// Get all peds on this server
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public ServerPed[] GetAllPeds() public ServerPed[] GetAllPeds() => Peds.Values.ToArray();
{
return Peds.Values.ToArray();
}
/// <summary> /// <summary>
/// Get all vehicles on this server /// Get all vehicles on this server
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public ServerVehicle[] GetAllVehicles() public ServerVehicle[] GetAllVehicles() => Vehicles.Values.ToArray();
{
return Vehicles.Values.ToArray();
}
/// <summary> /// <summary>
/// Get all static prop objects owned by server /// Get all static prop objects owned by server
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public ServerProp[] GetAllProps() public ServerProp[] GetAllProps() => ServerProps.Values.ToArray();
{
return ServerProps.Values.ToArray();
}
/// <summary> /// <summary>
/// Get all blips owned by server /// Get all blips owned by server
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public ServerBlip[] GetAllBlips() public ServerBlip[] GetAllBlips() => Blips.Values.ToArray();
{
return Blips.Values.ToArray();
}
/// <summary> /// <summary>
/// Not thread safe /// Not thread safe
/// </summary> /// </summary>
internal void Update(Packets.PedSync p, Client sender) internal void Update(Packets.PedSync p, Client sender)
{ {
ServerPed ped; if (!Peds.TryGetValue(p.ID, out ServerPed ped))
if(!Peds.TryGetValue(p.ID,out ped))
{ {
Peds.TryAdd(p.ID, ped = new ServerPed(Server)); Peds.TryAdd(p.ID, ped = new ServerPed(Server));
ped.ID = p.ID; ped.ID = p.ID;
@ -229,8 +173,7 @@ namespace RageCoop.Server.Scripting
} }
internal void Update(Packets.VehicleSync p, Client sender) internal void Update(Packets.VehicleSync p, Client sender)
{ {
ServerVehicle veh; if (!Vehicles.TryGetValue(p.ID, out ServerVehicle veh))
if (!Vehicles.TryGetValue(p.ID, out veh))
{ {
Vehicles.TryAdd(p.ID, veh = new ServerVehicle(Server)); Vehicles.TryAdd(p.ID, veh = new ServerVehicle(Server));
veh.ID = p.ID; veh.ID = p.ID;
@ -277,14 +220,8 @@ namespace RageCoop.Server.Scripting
} }
} }
internal void RemoveProp(int id) internal void RemoveProp(int id) => ServerProps.TryRemove(id, out _);
{ internal void RemoveServerBlip(int id) => Blips.TryRemove(id, out _);
ServerProps.TryRemove(id, out _);
}
internal void RemoveServerBlip(int id)
{
Blips.TryRemove(id, out _);
}
internal void RemovePed(int id) internal void RemovePed(int id)
{ {
Peds.TryRemove(id, out var ped); Peds.TryRemove(id, out var ped);
@ -299,12 +236,11 @@ namespace RageCoop.Server.Scripting
if (Peds.ContainsKey(ped.ID)) if (Peds.ContainsKey(ped.ID))
{ {
Peds[ped.ID] = ped; Peds[ped.ID] = ped;
return;
} }
else
{
Peds.TryAdd(ped.ID, ped); Peds.TryAdd(ped.ID, ped);
} }
}
internal int RequestNetworkID() internal int RequestNetworkID()
{ {
int ID = 0; int ID = 0;

View File

@ -1,14 +1,11 @@
using System; using GTA;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GTA;
using GTA.Native;
using GTA.Math; using GTA.Math;
using GTA.Native;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -70,7 +67,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public virtual Vector3 Position public virtual Vector3 Position
{ {
get { return _pos; } get => _pos;
set { _pos = value; Owner.SendNativeCall(Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); } set { _pos = value; Owner.SendNativeCall(Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); }
} }
internal Vector3 _pos; internal Vector3 _pos;
@ -80,7 +77,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public virtual Vector3 Rotation public virtual Vector3 Rotation
{ {
get { return _rot; } get => _rot;
set { _rot = value; Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); } set { _rot = value; Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); }
} }
internal Vector3 _rot; internal Vector3 _rot;
@ -137,7 +134,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public override Vector3 Position public override Vector3 Position
{ {
get { return _pos; } get => _pos;
set { _pos = value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); } set { _pos = value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); }
} }
@ -146,7 +143,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public override Vector3 Rotation public override Vector3 Rotation
{ {
get { return _rot; } get => _rot;
set { _rot = value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); } set { _rot = value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); }
} }
@ -198,7 +195,8 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Get or set whether this ped is invincible /// Get or set whether this ped is invincible
/// </summary> /// </summary>
public bool IsInvincible { public bool IsInvincible
{
get => _isInvincible; get => _isInvincible;
set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE, Handle, value); set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE, Handle, value);
} }
@ -215,7 +213,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public override Vector3 Rotation public override Vector3 Rotation
{ {
get { return _quat.ToEulerAngles().ToDegree(); } get => _quat.ToEulerAngles().ToDegree();
set { Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z); } set { Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z); }
} }
@ -225,7 +223,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public Quaternion Quaternion public Quaternion Quaternion
{ {
get { return _quat; } get => _quat;
set { _quat = value; Owner.SendNativeCall(Hash.SET_ENTITY_QUATERNION, Handle, value.X, value.Y, value.Z, value.W); } set { _quat = value; Owner.SendNativeCall(Hash.SET_ENTITY_QUATERNION, Handle, value.X, value.Y, value.Z, value.W); }
} }
} }
@ -263,8 +261,9 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Color of this blip /// Color of this blip
/// </summary> /// </summary>
public BlipColor Color { public BlipColor Color
get { return _color; } {
get => _color;
set { _color = value; Update(); } set { _color = value; Update(); }
} }
@ -272,8 +271,9 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Sprite of this blip /// Sprite of this blip
/// </summary> /// </summary>
public BlipSprite Sprite { public BlipSprite Sprite
get { return _sprite; } {
get => _sprite;
set { _sprite = value; Update(); } set { _sprite = value; Update(); }
} }
@ -283,7 +283,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public float Scale public float Scale
{ {
get { return _scale; } get => _scale;
set { _scale = value; Update(); } set { _scale = value; Update(); }
} }
@ -293,7 +293,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public Vector3 Position public Vector3 Position
{ {
get { return _pos; } get => _pos;
set { _pos = value; Update(); } set { _pos = value; Update(); }
} }
@ -303,7 +303,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public int Rotation public int Rotation
{ {
get { return _rot; } get => _rot;
set { _rot = value; Update(); } set { _rot = value; Update(); }
} }
@ -313,7 +313,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public string Name public string Name
{ {
get { return _name;} get => _name;
set { _name = value; Update(); } set { _name = value; Update(); }
} }
@ -372,7 +372,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public BlipColor Color public BlipColor Color
{ {
get { return _color; } get => _color;
set { _color = value; Update(); } set { _color = value; Update(); }
} }
@ -382,7 +382,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public BlipSprite Sprite public BlipSprite Sprite
{ {
get { return _sprite; } get => _sprite;
set { _sprite = value; Update(); } set { _sprite = value; Update(); }
} }
@ -392,7 +392,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public float Scale public float Scale
{ {
get { return _scale; } get => _scale;
set { _scale = value; Update(); } set { _scale = value; Update(); }
} }

View File

@ -1,12 +1,13 @@
using System; using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using System.Linq;
using RageCoop.Core;
using System.Reflection;
using McMaster.NETCore.Plugins; using McMaster.NETCore.Plugins;
using System.IO; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using ICSharpCode.SharpZipLib.Zip; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -17,8 +18,22 @@ namespace RageCoop.Server.Scripting
{ {
internal ServerResource(PluginConfig config) : base(config) { } internal ServerResource(PluginConfig config) : base(config) { }
internal static ServerResource LoadFrom(string resDir, string dataFolder, Logger logger = null, bool isTemp = false) internal static ServerResource LoadFrom(string resDir, string dataFolder, Logger logger = null)
{ {
var runtimeLibs = Path.Combine(resDir, "RuntimeLibs", CoreUtils.GetInvariantRID());
if (Directory.Exists(runtimeLibs))
{
logger?.Debug("Applying runtime libraries from " + CoreUtils.GetInvariantRID());
CoreUtils.CopyFilesRecursively(new(runtimeLibs), new(resDir));
}
runtimeLibs = Path.Combine(resDir, "RuntimeLibs", RuntimeInformation.RuntimeIdentifier);
if (Directory.Exists(runtimeLibs))
{
logger?.Debug("Applying runtime libraries from " + CoreUtils.GetInvariantRID());
CoreUtils.CopyFilesRecursively(new(runtimeLibs), new(resDir));
}
var conf = new PluginConfig(Path.GetFullPath(Path.Combine(resDir, Path.GetFileName(resDir) + ".dll"))) var conf = new PluginConfig(Path.GetFullPath(Path.Combine(resDir, Path.GetFileName(resDir) + ".dll")))
{ {
PreferSharedTypes = true, PreferSharedTypes = true,
@ -66,6 +81,9 @@ namespace RageCoop.Server.Scripting
} }
foreach (var a in assemblies) foreach (var a in assemblies)
{ {
if (a.Key.Name.ToLower() == r.Name.ToLower() + ".dll")
{
try try
{ {
r.LoadScriptsFromAssembly(a.Key, a.Value); r.LoadScriptsFromAssembly(a.Key, a.Value);
@ -79,13 +97,16 @@ namespace RageCoop.Server.Scripting
} }
} }
} }
}
return r; return r;
} }
internal static ServerResource LoadFrom(Stream input, string name, string tmpDir, string dataFolder, Logger logger = null) internal static ServerResource LoadFrom(Stream input, string name, string tmpDir, string dataFolder, Logger logger = null)
{ {
tmpDir = Path.Combine(tmpDir, name); tmpDir = Path.Combine(tmpDir, name);
if (Directory.Exists(tmpDir)) { Directory.Delete(tmpDir, true); }
Directory.CreateDirectory(tmpDir);
new FastZip().ExtractZip(input, tmpDir, FastZip.Overwrite.Always, null, null, null, true, true); new FastZip().ExtractZip(input, tmpDir, FastZip.Overwrite.Always, null, null, null, true, true);
return LoadFrom(tmpDir, dataFolder, logger, true); return LoadFrom(tmpDir, dataFolder, logger);
} }
/// <summary> /// <summary>
/// Name of the resource /// Name of the resource

View File

@ -1,5 +1,5 @@
using System; using RageCoop.Core.Scripting;
using RageCoop.Core.Scripting; using System;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -35,7 +35,7 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Eqivalent of <see cref="ServerResource.Logger"/> in <see cref="CurrentResource"/> /// Eqivalent of <see cref="ServerResource.Logger"/> in <see cref="CurrentResource"/>
/// </summary> /// </summary>
public Core.Logger Logger { get { return CurrentResource.Logger; } } public Core.Logger Logger => CurrentResource.Logger;
} }
/// <summary> /// <summary>
/// Decorate your method with this attribute and use <see cref="API.RegisterCommands{T}"/> or <see cref="API.RegisterCommands(object)"/> to register commands. /// Decorate your method with this attribute and use <see cref="API.RegisterCommands{T}"/> or <see cref="API.RegisterCommands(object)"/> to register commands.

View File

@ -1,12 +1,7 @@
using System; using RageCoop.Core;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO; using System.IO;
using RageCoop.Core; using System.Net;
using System.Runtime.Serialization;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -18,7 +13,7 @@ namespace RageCoop.Server
Logger = logger; Logger = logger;
} }
public RSA RSA = RSA.Create(2048); public RSA RSA = RSA.Create(2048);
private Dictionary<IPEndPoint, Aes> SecuredConnections = new Dictionary<IPEndPoint, Aes>(); private readonly Dictionary<IPEndPoint, Aes> SecuredConnections = new Dictionary<IPEndPoint, Aes>();
public bool HasSecuredConnection(IPEndPoint target) public bool HasSecuredConnection(IPEndPoint target)
{ {

View File

@ -28,7 +28,7 @@
/// <summary> /// <summary>
/// The website address to be shown on master server /// The website address to be shown on master server
/// </summary> /// </summary>
public string Website { get; set; } = "https://ragecoop.online/"; public string Website { get; set; } = "https://ragecoop.com/";
/// <summary> /// <summary>
/// The description to be shown on master server /// The description to be shown on master server
@ -58,7 +58,7 @@
/// <summary> /// <summary>
/// Master server address, mostly doesn't need to be changed. /// Master server address, mostly doesn't need to be changed.
/// </summary> /// </summary>
public string MasterServer { get; set; } = "https://masterserver.ragecoop.online/"; public string MasterServer { get; set; } = "https://masterserver.ragecoop.com/";
/// <summary> /// <summary>
/// See <see cref="Core.Logger.LogLevel"/>. /// See <see cref="Core.Logger.LogLevel"/>.
@ -119,5 +119,10 @@
/// Kick spamming assholes /// Kick spamming assholes
/// </summary> /// </summary>
public bool KickSpamming { get; set; } = true; public bool KickSpamming { get; set; } = true;
/// <summary>
/// Player that spawned entities more than this amount will be kicked if <see cref="KickSpamming"/> is enabled.
/// </summary>
public int SpamLimit { get; set; } = 100;
} }
} }

View File

@ -1,16 +1,15 @@
using System; global using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using System.Collections.Generic;
using Lidgren.Network; using Lidgren.Network;
using System;
using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Xml;
using System.Xml.Serialization;
namespace RageCoop.Server namespace RageCoop.Server
{ {
static partial class Util internal static partial class Util
{ {
public static string DownloadString(string url) public static string DownloadString(string url)
@ -35,22 +34,6 @@ namespace RageCoop.Server
return ""; return "";
} }
} }
public static (byte, byte[]) GetBytesFromObject(object obj)
{
return obj switch
{
byte _ => (0x01, BitConverter.GetBytes((byte)obj)),
short _ => (0x02, BitConverter.GetBytes((short)obj)),
ushort _ => (0x03, BitConverter.GetBytes((ushort)obj)),
int _ => (0x04, BitConverter.GetBytes((int)obj)),
uint _ => (0x05, BitConverter.GetBytes((uint)obj)),
long _ => (0x06, BitConverter.GetBytes((long)obj)),
ulong _ => (0x07, BitConverter.GetBytes((ulong)obj)),
float _ => (0x08, BitConverter.GetBytes((float)obj)),
bool _ => (0x09, BitConverter.GetBytes((bool)obj)),
_ => (0x0, null),
};
}
public static List<NetConnection> Exclude(this IEnumerable<NetConnection> connections, NetConnection toExclude) public static List<NetConnection> Exclude(this IEnumerable<NetConnection> connections, NetConnection toExclude)
{ {
return new(connections.Where(e => e != toExclude)); return new(connections.Where(e => e != toExclude));

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More